1 /*  smplayer, GUI front-end for mplayer.
2     Copyright (C) 2006-2021 Ricardo Villalba <ricardo@smplayer.info>
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 
19 #ifndef PLAYLIST_H
20 #define PLAYLIST_H
21 
22 #include <QList>
23 #include <QStringList>
24 #include <QWidget>
25 #include <QModelIndex>
26 #include <QStandardItem>
27 #include <QProcess>
28 #include "mediadata.h"
29 
30 #ifdef YOUTUBE_SUPPORT
31 #define PLAYLIST_DOWNLOAD
32 #define YT_PLAYLIST_SUPPORT
33 #include "youtube/retrieveyoutubeurl.h"
34 #endif
35 
36 //#define PLAYLIST_DOUBLE_TOOLBAR
37 #define PLAYLIST_DELETE_FROM_DISK
38 
39 #define DELAYED_PLAY
40 
41 class PLItem : public QStandardItem {
42 public:
43 	 enum PLItem_Roles { Role_Played = Qt::UserRole + 2, Role_Current = Qt::UserRole + 3, Role_Params = Qt::UserRole + 4,
44                          Role_Video_URL = Qt::UserRole + 5, Role_Icon_URL = Qt::UserRole + 6 };
45 
46 	PLItem();
47 	PLItem(const QString filename, const QString name, double duration);
48 	~PLItem();
49 
50 	void setFilename(const QString filename);
51 	void setName(const QString name);
52 	void setDuration(double duration);
53 	void setExtraParams(const QStringList & pars);
54 	void setVideoURL(const QString & url);
55 	void setIconURL(const QString & url);
56 	void setPlayed(bool played);
57 	void setPosition(int position);
58 	void setShufflePosition(int position);
59 	void setCurrent(bool b);
60 
61 	QString filename();
62 	QString name();
63 	double duration();
64 	QStringList extraParams();
65 	QString videoURL();
66 	QString iconURL();
67 	bool played();
68 	int position();
69 	int shufflePosition();
70 	bool isCurrent();
71 
72 	QList<QStandardItem *> items();
73 
74 protected:
75 	QStandardItem * col_num;
76 	QStandardItem * col_duration;
77 	QStandardItem * col_filename;
78 	QStandardItem * col_shuffle;
79 };
80 
81 
82 class QTableView;
83 class QStandardItemModel;
84 class QStandardItem;
85 class QSortFilterProxyModel;
86 class QToolBar;
87 class MyAction;
88 class MyLineEdit;
89 class LoadPage;
90 class QMenu;
91 class QSettings;
92 class QToolButton;
93 class QTimer;
94 class QMovie;
95 class URLHistory;
96 
97 class Playlist : public QWidget
98 {
99 	Q_OBJECT
100 
101 public:
102 	enum AutoGetInfo { NoGetInfo = 0, GetInfo = 1, UserDefined = 2 };
103 	enum M3UFormat { M3U = 0, M3U8 = 1, DetectFormat = 2 };
104 
105 	Playlist(QWidget * parent = 0, Qt::WindowFlags f = Qt::Window );
106 	~Playlist();
107 
108 	void setConfigPath(const QString & config_path);
109 
110 	void clear();
111 	void list();
112 
113 	int count();
114 	bool isEmpty();
115 
isModified()116 	bool isModified() { return modified; };
117 
118 	PLItem * itemData(int row);
119 	PLItem * itemFromProxy(int row);
120 	bool existsItem(int row);
121 
122 	/*
123 	void changeItem(int row, const QString & filename, const QString name, double duration, bool played = false, int pos = -1);
124 	*/
125 
126 public slots:
127 	void addItem(QString filename, QString name, double duration, QStringList params = QStringList(),
128                  QString video_url = QString(), QString icon_url = QString(), int shuffle_pos = 0);
129 
130 	// Start playing, from item 0 if shuffle is off, or from
131 	// a random item otherwise
132 	void startPlay();
133 
134 	void playItem(int n, bool later = false);
135 
136 	void playNext();
137 	void playPrev();
138 
139 	void playNextAuto(); // Called from GUI when a file finished
140 
141 	void resumePlay();
142 
143 	void removeSelected();
144 	void removeAll();
145 
146 	void addCurrentFile();
147 	void addFiles();
148 	void addDirectory();
149 	void addUrls();
150 
151 	void addFile(QString file, AutoGetInfo auto_get_info = UserDefined);
152 	void addFiles(QStringList files, AutoGetInfo auto_get_info = UserDefined);
153 
154 	// Adds a directory, no recursive
155 	void addOneDirectory(QString dir);
156 
157 	// Adds a directory, maybe with recursion (depends on user config)
158 	void addDirectory(QString dir);
159 
160 #ifdef PLAYLIST_DELETE_FROM_DISK
161 	void deleteSelectedFileFromDisk();
162 #endif
163 
164 	bool maybeSave();
165 	void load();
166 
167 	bool saveCurrentPlaylist();
168 	bool save(const QString & filename = QString());
169 
170 #ifdef PLAYLIST_DOWNLOAD
171 	void openUrl();
172 	void openUrl(const QString & url);
173 #endif
174 
175 	void load_m3u(QString file, M3UFormat format = DetectFormat);
176 	bool save_m3u(QString file);
177 
178 	void load_pls(QString file);
179 	bool save_pls(QString file);
180 
181 	void loadXSPF(const QString & filename);
182 	bool saveXSPF(const QString & filename);
183 
184 #ifdef YT_PLAYLIST_SUPPORT
185 	void loadYoutubeList(QList<itemMap> list);
186 #endif
187 
188 	void setModified(bool);
189 
190 	void setFilter(const QString & filter);
191 
192 	void shuffle(bool enable);
193 
194 	// Slots to connect from basegui
195 	void getMediaInfo(const MediaData &);
196 	void playerFailed(QProcess::ProcessError);
197 	void playerFinishedWithError(int);
198 
199 public:
200 	// Preferences
setDirectoryRecursion(bool b)201 	void setDirectoryRecursion(bool b) { recursive_add_directory = b; };
setAutoGetInfo(bool b)202 	void setAutoGetInfo(bool b) { automatically_get_info = b; };
setSavePlaylistOnExit(bool b)203 	void setSavePlaylistOnExit(bool b) { save_playlist_in_config = b; };
setPlayFilesFromStart(bool b)204 	void setPlayFilesFromStart(bool b) { play_files_from_start = b; };
setIgnorePlayerErrors(bool b)205 	void setIgnorePlayerErrors(bool b) { ignore_player_errors = b; };
setStartPlayOnLoad(bool b)206 	void setStartPlayOnLoad(bool b) { start_play_on_load = b; };
setAutomaticallyPlayNext(bool b)207 	void setAutomaticallyPlayNext(bool b) { automatically_play_next = b; };
208 	void setAutoSort(bool b);
209 	void setSortCaseSensitive(bool b);
210 	void setFilterCaseSensitive(bool b);
211 
directoryRecursion()212 	bool directoryRecursion() { return recursive_add_directory; };
autoGetInfo()213 	bool autoGetInfo() { return automatically_get_info; };
savePlaylistOnExit()214 	bool savePlaylistOnExit() { return save_playlist_in_config; };
playFilesFromStart()215 	bool playFilesFromStart() { return play_files_from_start; };
ignorePlayerErrors()216 	bool ignorePlayerErrors() { return ignore_player_errors; };
startPlayOnLoad()217 	bool startPlayOnLoad() { return start_play_on_load; };
automaticallyPlayNext()218 	bool automaticallyPlayNext() { return automatically_play_next; };
219 	bool autoSort();
220 	bool sortCaseSensitive();
221 	bool filterCaseSensitive();
222 
223 #ifdef PLAYLIST_DOWNLOAD
224 	void setMaxItemsUrlHistory(int max_items);
225 	int maxItemsUrlHistory();
226 #endif
227 
228 #ifdef PLAYLIST_DELETE_FROM_DISK
allowDeleteFromDisk(bool enabled)229 	void allowDeleteFromDisk(bool enabled) { allow_delete_from_disk = enabled; };
isDeleteFromDiskAllowed()230 	bool isDeleteFromDiskAllowed() { return allow_delete_from_disk; };
231 #endif
232 
233 #ifdef YT_PLAYLIST_SUPPORT
234 	static bool isYTPlaylist(const QString & url);
235 #endif
236 
237 /*
238 public:
239 	MyAction * playPrevAct() { return prevAct; };
240 	MyAction * playNextAct() { return nextAct; };
241 */
242 
243 signals:
244 	void requestToPlayFile(const QString & filename, int seek = -1);
245 	void requestToPlayStream(const QString & filename, QStringList params = QStringList());
246 
247 	void requestToAddCurrentFile();
248 	void playlistEnded();
249 	void visibilityChanged(bool visible);
250 	void modifiedChanged(bool);
251 	void windowTitleChanged(const QString & title);
252 
253 protected:
254 	void setCurrentItem(int current);
255 	int findCurrentItem();
256 	void clearPlayedTag();
257 	QString lastDir();
258 
259 	void setPlaylistFilename(const QString &);
playlistFilename()260 	QString playlistFilename() { return playlist_filename; };
261 
262 	void updateWindowTitle();
263 
264 protected slots:
265 	void playCurrent();
266 	void itemActivated(const QModelIndex & index );
267 	void showPopup(const QPoint & pos);
268 	void upItem();
269 	void downItem();
270 	void editCurrentItem();
271 	void editItem(int row);
272 
273 	void copyURL();
274 	void openFolder();
275 
276 #ifdef CHROMECAST_SUPPORT
277 	void playOnChromecast();
278 #else
279 	void openURLInWeb();
280 #endif
281 
282 	void saveSettings();
283 	void loadSettings();
284 
285 	void maybeSaveSettings();
286 
287 	void filterEditChanged(const QString &);
288 
289 #ifdef PLAYLIST_DOWNLOAD
290 	void playlistDownloaded(QByteArray);
291 	void errorOcurred(int error_number, QString error_str);
292 	void showLoadingAnimation(bool b);
293 #endif
294 
295 	void setPositionColumnVisible(bool b);
296 	void setNameColumnVisible(bool b);
297 	void setDurationColumnVisible(bool b);
298 	void setFilenameColumnVisible(bool b);
299 	void setShuffleColumnVisible(bool b);
300 
301 #ifdef DELAYED_PLAY
302 	void playItemLater();
303 #endif
304 
305 protected:
306 	void createTable();
307 	void createActions();
308 	void createToolbar();
309 
310 protected:
311 	void retranslateStrings();
312 	virtual void changeEvent ( QEvent * event ) ;
313 	virtual void dragEnterEvent( QDragEnterEvent * ) ;
314 	virtual void dropEvent ( QDropEvent * );
315 	virtual void hideEvent ( QHideEvent * );
316 	virtual void showEvent ( QShowEvent * );
317 	virtual void closeEvent( QCloseEvent * e );
318 
319 protected:
320 	QString playlist_path;
321 	QString playlist_filename;
322 	QString latest_dir;
323 
324 	QMenu * file_menu;
325 	QMenu * add_menu;
326 	QMenu * remove_menu;
327 	QMenu * popup;
328 
329 	QTableView * listView;
330 	QStandardItemModel * table;
331 	QSortFilterProxyModel * proxy;
332 
333 	QToolBar * toolbar;
334 #ifdef PLAYLIST_DOUBLE_TOOLBAR
335 	QToolBar * toolbar2;
336 #endif
337 
338 	QToolButton * file_button;
339 	QToolButton * add_button;
340 	QToolButton * remove_button;
341 
342 	MyLineEdit * filter_edit;
343 
344 	MyAction * openAct;
345 #ifdef PLAYLIST_DOWNLOAD
346 	MyAction * openUrlAct;
347 #endif
348 	MyAction * saveAct;
349 	MyAction * saveAsAct;
350 	MyAction * playAct;
351 	MyAction * prevAct;
352 	MyAction * nextAct;
353 	MyAction * repeatAct;
354 	MyAction * shuffleAct;
355 	MyAction * showSearchAct;
356 
357 	MyAction * moveUpAct;
358 	MyAction * moveDownAct;
359 	MyAction * editAct;
360 
361 	MyAction * addCurrentAct;
362 	MyAction * addFilesAct;
363 	MyAction * addDirectoryAct;
364 	MyAction * addUrlsAct;
365 
366 	MyAction * removeSelectedAct;
367 	MyAction * removeAllAct;
368 
369 #ifdef PLAYLIST_DELETE_FROM_DISK
370 	MyAction * deleteSelectedFileFromDiskAct;
371 #endif
372 
373 	MyAction * copyURLAct;
374 	MyAction * openFolderAct;
375 
376 #ifdef CHROMECAST_SUPPORT
377 	MyAction * playOnChromecastAct;
378 #else
379 	MyAction * openURLInWebAct;
380 #endif
381 
382 	MyAction * showPositionColumnAct;
383 	MyAction * showNameColumnAct;
384 	MyAction * showDurationColumnAct;
385 	MyAction * showFilenameColumnAct;
386 	MyAction * showShuffleColumnAct;
387 
388 	QSettings * set;
389 
390 #ifdef PLAYLIST_DOWNLOAD
391 	LoadPage * downloader;
392 	URLHistory * history_urls;
393 	QMovie * animation;
394 	QAction * loading_label_action;
395 #endif
396 
397 #ifdef DELAYED_PLAY
398 	QTimer * play_later_timer;
399 	qint64 last_timestamp;
400 	struct {
401 		QString filename;
402 		QStringList params;
403 		int seek;
404 	} play_later;
405 #endif
406 
407 private:
408 	bool modified;
409 	QTimer * save_timer;
410 
411 	//Preferences
412 	bool recursive_add_directory;
413 	bool automatically_get_info;
414 	bool save_playlist_in_config;
415 	bool play_files_from_start;
416 	int row_spacing;
417 
418 	bool start_play_on_load;
419 	bool automatically_play_next;
420 	bool ignore_player_errors;
421 	bool change_name;
422 	bool save_dirs;
423 
424 #ifdef PLAYLIST_DELETE_FROM_DISK
425 	bool allow_delete_from_disk;
426 #endif
427 };
428 
429 #endif
430