Diffstat (limited to 'core/multimedia/opieplayer/playlistwidget.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/playlistwidget.cpp | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/playlistwidget.cpp b/core/multimedia/opieplayer/playlistwidget.cpp new file mode 100644 index 0000000..969fc4b --- a/dev/null +++ b/core/multimedia/opieplayer/playlistwidget.cpp | |||
@@ -0,0 +1,448 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | ||
3 | ** | ||
4 | ** This file is part of Qtopia Environment. | ||
5 | ** | ||
6 | ** This file may be distributed and/or modified under the terms of the | ||
7 | ** GNU General Public License version 2 as published by the Free Software | ||
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
9 | ** packaging of this file. | ||
10 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | ** | ||
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
15 | ** | ||
16 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
17 | ** not clear to you. | ||
18 | ** | ||
19 | **********************************************************************/ | ||
20 | #include <qpe/qpemenubar.h> | ||
21 | #include <qpe/qpetoolbar.h> | ||
22 | #include <qpe/fileselector.h> | ||
23 | #include <qpe/applnk.h> | ||
24 | #include <qpe/config.h> | ||
25 | #include <qpe/global.h> | ||
26 | #include <qpe/resource.h> | ||
27 | #include <qaction.h> | ||
28 | #include <qimage.h> | ||
29 | #include <qfile.h> | ||
30 | #include <qlayout.h> | ||
31 | #include <qlabel.h> | ||
32 | #include <qlist.h> | ||
33 | #include <qlistbox.h> | ||
34 | #include <qmainwindow.h> | ||
35 | #include <qmessagebox.h> | ||
36 | #include <qtoolbutton.h> | ||
37 | |||
38 | #include "playlistselection.h" | ||
39 | #include "playlistwidget.h" | ||
40 | #include "mediaplayerstate.h" | ||
41 | |||
42 | #include <stdlib.h> | ||
43 | |||
44 | |||
45 | extern MediaPlayerState *mediaPlayerState; | ||
46 | |||
47 | |||
48 | class PlayListWidgetPrivate { | ||
49 | public: | ||
50 | QToolButton *tbPlay; | ||
51 | QToolButton *tbFull; | ||
52 | QToolButton *tbLoop; | ||
53 | QToolButton *tbScale; | ||
54 | QToolButton *tbShuffle; | ||
55 | |||
56 | QFrame *playListFrame; | ||
57 | FileSelector *files; | ||
58 | PlayListSelection *selectedFiles; | ||
59 | bool setDocumentUsed; | ||
60 | DocLnk *current; | ||
61 | }; | ||
62 | |||
63 | |||
64 | class ToolButton : public QToolButton { | ||
65 | public: | ||
66 | ToolButton( QWidget *parent, const char *name, const QString& icon, QObject *handler, const QString& slot, bool t = FALSE ) | ||
67 | : QToolButton( parent, name ) { | ||
68 | setTextLabel( name ); | ||
69 | setPixmap( Resource::loadPixmap( icon ) ); | ||
70 | setAutoRaise( TRUE ); | ||
71 | setFocusPolicy( QWidget::NoFocus ); | ||
72 | setToggleButton( t ); | ||
73 | connect( this, t ? SIGNAL( toggled(bool) ) : SIGNAL( clicked() ), handler, slot ); | ||
74 | QPEMenuToolFocusManager::manager()->addWidget( this ); | ||
75 | } | ||
76 | }; | ||
77 | |||
78 | |||
79 | class MenuItem : public QAction { | ||
80 | public: | ||
81 | MenuItem( QWidget *parent, const QString& text, QObject *handler, const QString& slot ) | ||
82 | : QAction( text, QString::null, 0, 0 ) { | ||
83 | connect( this, SIGNAL( activated() ), handler, slot ); | ||
84 | addTo( parent ); | ||
85 | } | ||
86 | }; | ||
87 | |||
88 | |||
89 | PlayListWidget::PlayListWidget( QWidget* parent, const char* name, WFlags fl ) | ||
90 | : QMainWindow( parent, name, fl ) { | ||
91 | |||
92 | d = new PlayListWidgetPrivate; | ||
93 | d->setDocumentUsed = FALSE; | ||
94 | d->current = NULL; | ||
95 | |||
96 | setBackgroundMode( PaletteButton ); | ||
97 | |||
98 | setCaption( tr("MediaPlayer") ); | ||
99 | setIcon( Resource::loadPixmap( "MPEGPlayer" ) ); | ||
100 | |||
101 | setToolBarsMovable( FALSE ); | ||
102 | |||
103 | // Create Toolbar | ||
104 | QPEToolBar *toolbar = new QPEToolBar( this ); | ||
105 | toolbar->setHorizontalStretchable( TRUE ); | ||
106 | |||
107 | // Create Menubar | ||
108 | QPEMenuBar *menu = new QPEMenuBar( toolbar ); | ||
109 | menu->setMargin( 0 ); | ||
110 | |||
111 | QPEToolBar *bar = new QPEToolBar( this ); | ||
112 | bar->setLabel( tr( "Play Operations" ) ); | ||
113 | #ifdef BUTTONS_ON_TOOLBAR | ||
114 | d->tbPlay = new ToolButton( bar, tr( "Play" ), "mpegplayer/play", mediaPlayerState, SLOT(setPlaying(bool)), TRUE ); | ||
115 | d->tbShuffle = new ToolButton( bar, tr( "Randomize" ), "mpegplayer/shuffle", mediaPlayerState, SLOT(setShuffled(bool)), TRUE ); | ||
116 | #endif | ||
117 | d->tbLoop = new ToolButton( bar, tr( "Loop" ), "mpegplayer/loop", mediaPlayerState, SLOT(setLooping(bool)), TRUE ); | ||
118 | d->tbFull = new ToolButton( bar, tr( "Fullscreen" ), "fullscreen", mediaPlayerState, SLOT(setFullscreen(bool)), TRUE ); | ||
119 | d->tbScale = new ToolButton( bar, tr( "Scale" ), "mpegplayer/scale", mediaPlayerState, SLOT(setScaled(bool)), TRUE ); | ||
120 | |||
121 | QPopupMenu *pmPlayList = new QPopupMenu( this ); | ||
122 | menu->insertItem( tr( "PlayList" ), pmPlayList ); | ||
123 | new MenuItem( pmPlayList, tr( "Toggle PlayList" ), mediaPlayerState, SLOT( togglePlaylist() ) ); | ||
124 | new MenuItem( pmPlayList, tr( "Clear List" ), this, SLOT( clearList() ) ); | ||
125 | new MenuItem( pmPlayList, tr( "Add all music files" ), this, SLOT( addAllMusicToList() ) ); | ||
126 | new MenuItem( pmPlayList, tr( "Add all video files" ), this, SLOT( addAllVideoToList() ) ); | ||
127 | new MenuItem( pmPlayList, tr( "Add all files" ), this, SLOT( addAllToList() ) ); | ||
128 | #ifdef CAN_SAVE_LOAD_PLAYLISTS | ||
129 | new MenuItem( pmPlayList, tr( "Save PlayList" ), this, SLOT( saveList() ) ); | ||
130 | new MenuItem( pmPlayList, tr( "Load PlayList" ), this, SLOT( loadList() ) ); | ||
131 | #endif | ||
132 | |||
133 | QVBox *vbox5 = new QVBox( this ); vbox5->setBackgroundMode( PaletteButton ); | ||
134 | |||
135 | // Add the playlist area | ||
136 | QVBox *vbox3 = new QVBox( vbox5 ); vbox3->setBackgroundMode( PaletteButton ); | ||
137 | d->playListFrame = vbox3; | ||
138 | |||
139 | QLabel *plString = new QLabel( tr(" PlayList"), vbox3 ); | ||
140 | plString->setBackgroundMode( QButton::PaletteButton ); | ||
141 | plString->setFont( QFont( "Helvetica", 8, QFont::Bold ) ); | ||
142 | |||
143 | QHBox *hbox2 = new QHBox( vbox3 ); hbox2->setBackgroundMode( PaletteButton ); | ||
144 | d->selectedFiles = new PlayListSelection( hbox2 ); | ||
145 | QVBox *vbox1 = new QVBox( hbox2 ); vbox1->setBackgroundMode( PaletteButton ); | ||
146 | |||
147 | #ifndef BUTTONS_ON_TOOLBAR | ||
148 | d->tbPlay = new ToolButton( vbox1, tr( "Play" ), "mpegplayer/play", mediaPlayerState, SLOT(setPlaying(bool)), TRUE ); | ||
149 | QVBox *stretch1 = new QVBox( vbox1 ); stretch1->setBackgroundMode( PaletteButton ); // add stretch | ||
150 | #endif | ||
151 | new ToolButton( vbox1, tr( "Move Up" ), "mpegplayer/up", d->selectedFiles, SLOT(moveSelectedUp()) ); | ||
152 | new ToolButton( vbox1, tr( "Remove" ), "mpegplayer/cut", d->selectedFiles, SLOT(removeSelected()) ); | ||
153 | new ToolButton( vbox1, tr( "Move Down" ), "mpegplayer/down", d->selectedFiles, SLOT(moveSelectedDown()) ); | ||
154 | QVBox *stretch2 = new QVBox( vbox1 ); stretch2->setBackgroundMode( PaletteButton ); // add stretch | ||
155 | #ifndef BUTTONS_ON_TOOLBAR | ||
156 | d->tbShuffle = new ToolButton( vbox1, tr( "Randomize" ), "mpegplayer/shuffle", mediaPlayerState, SLOT(setShuffled(bool)), TRUE ); | ||
157 | #endif | ||
158 | |||
159 | // add the library area | ||
160 | QVBox *vbox4 = new QVBox( vbox5 ); vbox4->setBackgroundMode( PaletteButton ); | ||
161 | |||
162 | QLabel *libString = new QLabel( tr(" Media Library"), vbox4 ); | ||
163 | libString->setBackgroundMode( QButton::PaletteButton ); | ||
164 | libString->setFont( QFont( "Helvetica", 8, QFont::Bold ) ); | ||
165 | |||
166 | QHBox *hbox6 = new QHBox( vbox4 ); hbox6->setBackgroundMode( PaletteButton ); | ||
167 | d->files = new FileSelector( "video/*;audio/*", hbox6, "Find Media Files", FALSE, FALSE ); | ||
168 | d->files->setBackgroundMode( PaletteButton ); | ||
169 | QVBox *vbox7 = new QVBox( hbox6 ); vbox7->setBackgroundMode( PaletteButton ); | ||
170 | |||
171 | #ifdef SIDE_BUTTONS | ||
172 | new ToolButton( vbox7, tr( "Add to Playlist" ), "mpegplayer/add_to_playlist", d->selectedFiles, SLOT(addSelected()) ); | ||
173 | new ToolButton( vbox7, tr( "Remove from Playlist" ), "mpegplayer/remove_from_playlist", d->selectedFiles, SLOT(removeSelected()) ); | ||
174 | QVBox *stretch3 = new QVBox( vbox1 ); stretch3->setBackgroundMode( PaletteButton ); // add stretch | ||
175 | #endif | ||
176 | |||
177 | connect( d->files, SIGNAL( fileSelected( const DocLnk & ) ), this, SLOT( addToSelection( const DocLnk & ) ) ); | ||
178 | connect( mediaPlayerState, SIGNAL( playingToggled( bool ) ), d->tbPlay, SLOT( setOn( bool ) ) ); | ||
179 | connect( mediaPlayerState, SIGNAL( loopingToggled( bool ) ), d->tbLoop, SLOT( setOn( bool ) ) ); | ||
180 | connect( mediaPlayerState, SIGNAL( shuffledToggled( bool ) ), d->tbShuffle, SLOT( setOn( bool ) ) ); | ||
181 | connect( mediaPlayerState, SIGNAL( fullscreenToggled( bool ) ), d->tbFull, SLOT( setOn( bool ) ) ); | ||
182 | connect( mediaPlayerState, SIGNAL( scaledToggled( bool ) ), d->tbScale, SLOT( setOn( bool ) ) ); | ||
183 | connect( mediaPlayerState, SIGNAL( fullscreenToggled( bool ) ), d->tbScale, SLOT( setEnabled( bool ) ) ); | ||
184 | connect( mediaPlayerState, SIGNAL( playlistToggled( bool ) ), this, SLOT( setPlaylist( bool ) ) ); | ||
185 | |||
186 | setCentralWidget( vbox5 ); | ||
187 | |||
188 | Config cfg( "MediaPlayer" ); | ||
189 | readConfig( cfg ); | ||
190 | |||
191 | initializeStates(); | ||
192 | } | ||
193 | |||
194 | |||
195 | PlayListWidget::~PlayListWidget() { | ||
196 | Config cfg( "MediaPlayer" ); | ||
197 | writeConfig( cfg ); | ||
198 | |||
199 | if ( d->current ) | ||
200 | delete d->current; | ||
201 | delete d; | ||
202 | } | ||
203 | |||
204 | |||
205 | void PlayListWidget::initializeStates() { | ||
206 | d->tbPlay->setOn( mediaPlayerState->playing() ); | ||
207 | d->tbLoop->setOn( mediaPlayerState->looping() ); | ||
208 | d->tbShuffle->setOn( mediaPlayerState->shuffled() ); | ||
209 | d->tbFull->setOn( mediaPlayerState->fullscreen() ); | ||
210 | d->tbScale->setOn( mediaPlayerState->scaled() ); | ||
211 | d->tbScale->setEnabled( mediaPlayerState->fullscreen() ); | ||
212 | setPlaylist( mediaPlayerState->playlist() ); | ||
213 | } | ||
214 | |||
215 | |||
216 | void PlayListWidget::readConfig( Config& cfg ) { | ||
217 | cfg.setGroup("PlayList"); | ||
218 | |||
219 | int noOfFiles = cfg.readNumEntry("NumberOfFiles", 0 ); | ||
220 | |||
221 | for ( int i = 0; i < noOfFiles; i++ ) { | ||
222 | QString entryName; | ||
223 | entryName.sprintf( "File%i", i + 1 ); | ||
224 | QString linkFile = cfg.readEntry( entryName ); | ||
225 | DocLnk lnk( linkFile ); | ||
226 | if ( lnk.isValid() ) | ||
227 | d->selectedFiles->addToSelection( lnk ); | ||
228 | |||
229 | } | ||
230 | } | ||
231 | |||
232 | |||
233 | void PlayListWidget::writeConfig( Config& cfg ) const { | ||
234 | cfg.setGroup("PlayList"); | ||
235 | |||
236 | int noOfFiles = 0; | ||
237 | |||
238 | d->selectedFiles->first(); | ||
239 | do { | ||
240 | const DocLnk *lnk = d->selectedFiles->current(); | ||
241 | if ( lnk ) { | ||
242 | QString entryName; | ||
243 | entryName.sprintf( "File%i", noOfFiles + 1 ); | ||
244 | cfg.writeEntry( entryName, lnk->linkFile() ); | ||
245 | // if this link does exist, add it so we have the file | ||
246 | // next time... | ||
247 | if ( !QFile::exists( lnk->linkFile() ) ) { | ||
248 | // the way writing lnks doesn't really check for out | ||
249 | // of disk space, but check it anyway. | ||
250 | if ( !lnk->writeLink() ) { | ||
251 | QMessageBox::critical( 0, tr("Out of space"), | ||
252 | tr( "There was a problem saving " | ||
253 | "the playlist.\n" | ||
254 | "Your playlist " | ||
255 | "may be missing some entries\n" | ||
256 | "the next time you start it." ) | ||
257 | ); | ||
258 | } | ||
259 | } | ||
260 | noOfFiles++; | ||
261 | } | ||
262 | } while ( d->selectedFiles->next() ); | ||
263 | |||
264 | cfg.writeEntry("NumberOfFiles", noOfFiles ); | ||
265 | } | ||
266 | |||
267 | |||
268 | void PlayListWidget::addToSelection( const DocLnk& lnk ) { | ||
269 | d->setDocumentUsed = FALSE; | ||
270 | if ( mediaPlayerState->playlist() ) | ||
271 | d->selectedFiles->addToSelection( lnk ); | ||
272 | else | ||
273 | mediaPlayerState->setPlaying( TRUE ); | ||
274 | } | ||
275 | |||
276 | |||
277 | void PlayListWidget::clearList() { | ||
278 | while ( first() ) | ||
279 | d->selectedFiles->removeSelected(); | ||
280 | } | ||
281 | |||
282 | |||
283 | void PlayListWidget::addAllToList() { | ||
284 | DocLnkSet files; | ||
285 | Global::findDocuments(&files, "video/*;audio/*"); | ||
286 | QListIterator<DocLnk> dit( files.children() ); | ||
287 | for ( ; dit.current(); ++dit ) | ||
288 | d->selectedFiles->addToSelection( **dit ); | ||
289 | } | ||
290 | |||
291 | |||
292 | void PlayListWidget::addAllMusicToList() { | ||
293 | DocLnkSet files; | ||
294 | Global::findDocuments(&files, "audio/*"); | ||
295 | QListIterator<DocLnk> dit( files.children() ); | ||
296 | for ( ; dit.current(); ++dit ) | ||
297 | d->selectedFiles->addToSelection( **dit ); | ||
298 | } | ||
299 | |||
300 | |||
301 | void PlayListWidget::addAllVideoToList() { | ||
302 | DocLnkSet files; | ||
303 | Global::findDocuments(&files, "video/*"); | ||
304 | QListIterator<DocLnk> dit( files.children() ); | ||
305 | for ( ; dit.current(); ++dit ) | ||
306 | d->selectedFiles->addToSelection( **dit ); | ||
307 | } | ||
308 | |||
309 | |||
310 | void PlayListWidget::setDocument(const QString& fileref) { | ||
311 | if ( fileref.isNull() ) { | ||
312 | QMessageBox::critical( 0, tr( "Invalid File" ), tr( "There was a problem in getting the file." ) ); | ||
313 | return; | ||
314 | } | ||
315 | if ( mediaPlayerState->playlist() ) | ||
316 | addToSelection( DocLnk( fileref ) ); | ||
317 | else { | ||
318 | d->setDocumentUsed = TRUE; | ||
319 | if ( d->current ) | ||
320 | delete d->current; | ||
321 | d->current = new DocLnk( fileref ); | ||
322 | } | ||
323 | mediaPlayerState->setPlaying( FALSE ); | ||
324 | mediaPlayerState->setPlaying( TRUE ); | ||
325 | } | ||
326 | |||
327 | |||
328 | void PlayListWidget::setActiveWindow() { | ||
329 | // When we get raised we need to ensure that it switches views | ||
330 | char origView = mediaPlayerState->view(); | ||
331 | mediaPlayerState->setView( 'l' ); // invalidate | ||
332 | mediaPlayerState->setView( origView ); // now switch back | ||
333 | } | ||
334 | |||
335 | |||
336 | void PlayListWidget::useSelectedDocument() { | ||
337 | d->setDocumentUsed = FALSE; | ||
338 | } | ||
339 | |||
340 | |||
341 | const DocLnk *PlayListWidget::current() { | ||
342 | if ( mediaPlayerState->playlist() ) | ||
343 | return d->selectedFiles->current(); | ||
344 | else if ( d->setDocumentUsed && d->current ) { | ||
345 | return d->current; | ||
346 | } else | ||
347 | return d->files->selected(); | ||
348 | } | ||
349 | |||
350 | |||
351 | bool PlayListWidget::prev() { | ||
352 | if ( mediaPlayerState->playlist() ) { | ||
353 | if ( mediaPlayerState->shuffled() ) { | ||
354 | const DocLnk *cur = current(); | ||
355 | int j = 1 + (int)(97.0 * rand() / (RAND_MAX + 1.0)); | ||
356 | for ( int i = 0; i < j; i++ ) { | ||
357 | if ( !d->selectedFiles->next() ) | ||
358 | d->selectedFiles->first(); | ||
359 | } | ||
360 | if ( cur == current() ) | ||
361 | if ( !d->selectedFiles->next() ) | ||
362 | d->selectedFiles->first(); | ||
363 | return TRUE; | ||
364 | } else { | ||
365 | if ( !d->selectedFiles->prev() ) { | ||
366 | if ( mediaPlayerState->looping() ) { | ||
367 | return d->selectedFiles->last(); | ||
368 | } else { | ||
369 | return FALSE; | ||
370 | } | ||
371 | } | ||
372 | return TRUE; | ||
373 | } | ||
374 | } else { | ||
375 | return mediaPlayerState->looping(); | ||
376 | } | ||
377 | } | ||
378 | |||
379 | |||
380 | bool PlayListWidget::next() { | ||
381 | if ( mediaPlayerState->playlist() ) { | ||
382 | if ( mediaPlayerState->shuffled() ) { | ||
383 | return prev(); | ||
384 | } else { | ||
385 | if ( !d->selectedFiles->next() ) { | ||
386 | if ( mediaPlayerState->looping() ) { | ||
387 | return d->selectedFiles->first(); | ||
388 | } else { | ||
389 | return FALSE; | ||
390 | } | ||
391 | } | ||
392 | return TRUE; | ||
393 | } | ||
394 | } else { | ||
395 | return mediaPlayerState->looping(); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | |||
400 | bool PlayListWidget::first() { | ||
401 | if ( mediaPlayerState->playlist() ) | ||
402 | return d->selectedFiles->first(); | ||
403 | else | ||
404 | return mediaPlayerState->looping(); | ||
405 | } | ||
406 | |||
407 | |||
408 | bool PlayListWidget::last() { | ||
409 | if ( mediaPlayerState->playlist() ) | ||
410 | return d->selectedFiles->last(); | ||
411 | else | ||
412 | return mediaPlayerState->looping(); | ||
413 | } | ||
414 | |||
415 | |||
416 | void PlayListWidget::saveList() { | ||
417 | QString filename; | ||
418 | // pseudo code | ||
419 | // filename = QLineEdit->getText(); | ||
420 | Config cfg( filename + ".playlist" ); | ||
421 | writeConfig( cfg ); | ||
422 | } | ||
423 | |||
424 | |||
425 | void PlayListWidget::loadList() { | ||
426 | QString filename; | ||
427 | // pseudo code | ||
428 | // filename = FileSelector->openFile( "*.playlist" ); | ||
429 | Config cfg( filename + ".playlist" ); | ||
430 | readConfig( cfg ); | ||
431 | } | ||
432 | |||
433 | |||
434 | void PlayListWidget::setPlaylist( bool shown ) { | ||
435 | if ( shown ) | ||
436 | d->playListFrame->show(); | ||
437 | else | ||
438 | d->playListFrame->hide(); | ||
439 | } | ||
440 | |||
441 | |||
442 | void PlayListWidget::setView( char view ) { | ||
443 | if ( view == 'l' ) | ||
444 | showMaximized(); | ||
445 | else | ||
446 | hide(); | ||
447 | } | ||
448 | |||