~ubuntu-branches/debian/squeeze/smplayer/squeeze

« back to all changes in this revision

Viewing changes to src/playlist.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Breuil Cyril
  • Date: 2007-06-24 16:35:29 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070624163529-hhckbmd24uicada7
Tags: 0.5.20-0ubuntu1
* New upstream release
* Change Maintainer Email

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  smplayer, GUI front-end for mplayer.
 
2
    Copyright (C) 2007 Ricardo Villalba <rvm@escomposlinux.org>
 
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
#include "playlist.h"
 
20
 
 
21
#include <qtoolbar.h>
 
22
#include <mytable.h>
 
23
#include "myaction.h"
 
24
#include <qfile.h>
 
25
#include <qtextstream.h>
 
26
#include <qregexp.h>
 
27
#include "filedialog.h"
 
28
#include <qdir.h>
 
29
#include <qfileinfo.h>
 
30
#include <qmessagebox.h>
 
31
#include <qpushbutton.h>
 
32
#include <qpopupmenu.h>
 
33
#include <qdragobject.h>
 
34
#include <qurl.h>
 
35
#include <qdatetime.h>
 
36
#include <qsettings.h>
 
37
#include <qinputdialog.h>
 
38
#include <qtoolbutton.h>
 
39
#include <qtooltip.h>
 
40
#include <qtimer.h>
 
41
 
 
42
#include <stdlib.h>
 
43
 
 
44
#include "helper.h"
 
45
#include "images.h"
 
46
#include "preferences.h"
 
47
#include "version.h"
 
48
#include "global.h"
 
49
#include "core.h"
 
50
#include "config.h"
 
51
 
 
52
#if KDE_SUPPORT
 
53
#include <kurl.h>
 
54
#endif
 
55
 
 
56
 
 
57
#define COL_PLAY 0
 
58
#define COL_NAME 1
 
59
#define COL_TIME 2
 
60
 
 
61
 
 
62
Playlist::Playlist( Core *c, QWidget * parent, const char * name, WFlags f)
 
63
        : QMainWindow(parent, name, f)
 
64
{
 
65
        modified = false;
 
66
 
 
67
        core = c;
 
68
    playlist_path = "";
 
69
    latest_dir = "";
 
70
 
 
71
        createTable();
 
72
        setCentralWidget( listView );
 
73
 
 
74
        createActions();
 
75
        createToolbar();
 
76
 
 
77
    clear();
 
78
 
 
79
        languageChange();
 
80
 
 
81
#if !DOCK_PLAYLIST
 
82
        setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding );
 
83
        adjustSize();
 
84
#else
 
85
        //setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
 
86
        setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
 
87
#endif
 
88
 
 
89
        setAcceptDrops(TRUE);
 
90
 
 
91
        // Random seed
 
92
        QTime t;
 
93
        t.start();
 
94
        srand( t.hour() * 3600 + t.minute() * 60 + t.second() );
 
95
 
 
96
        loadSettings();
 
97
 
 
98
        // Save config every 5 minutes.
 
99
        save_timer = new QTimer(this);
 
100
        connect( save_timer, SIGNAL(timeout()), this, SLOT(maybeSaveSettings()) );
 
101
        save_timer->start( 5 * 60000 ); 
 
102
}
 
103
 
 
104
Playlist::~Playlist() {
 
105
        saveSettings();
 
106
}
 
107
 
 
108
void Playlist::setModified(bool mod) {
 
109
        qDebug("Playlist::setModified: %d", mod);
 
110
 
 
111
        modified = mod;
 
112
        emit modifiedChanged(modified);
 
113
}
 
114
 
 
115
void Playlist::createTable() {
 
116
        listView = new MyTable( this, "listView" );
 
117
        listView->setSizeHint(QSize(100,100));
 
118
 
 
119
        listView->setShowGrid( FALSE );
 
120
        listView->setNumCols(COL_TIME + 1);
 
121
        listView->setReadOnly(TRUE);
 
122
        listView->setFocusStyle(QTable::FollowStyle);
 
123
        listView->setSelectionMode(QTable::MultiRow);
 
124
        //listView->verticalHeader()->hide();
 
125
        listView->setSorting(FALSE);
 
126
 
 
127
        connect( listView, SIGNAL(doubleClicked(int,int,int,const QPoint &)),
 
128
             this, SLOT(itemDoubleClicked(int)) );
 
129
 
 
130
        connect( core, SIGNAL(mediaFinished()), this, SLOT(playNext()) );
 
131
        
 
132
        connect( core, SIGNAL(mediaLoaded()),
 
133
             this, SLOT(getMediaInfo()) );
 
134
}
 
135
 
 
136
void Playlist::createActions() {
 
137
        openAct = new MyAction(this, "pl_open");
 
138
        connect( openAct, SIGNAL(activated()), this, SLOT(load()) );
 
139
 
 
140
        saveAct = new MyAction(this, "pl_save");
 
141
        connect( saveAct, SIGNAL(activated()), this, SLOT(save()) );
 
142
 
 
143
        playAct = new MyAction(this, "pl_play");
 
144
        connect( playAct, SIGNAL(activated()), this, SLOT(playCurrent()) );
 
145
 
 
146
        nextAct = new MyAction(Qt::Key_N /*Qt::Key_Greater*/, this, "pl_next");
 
147
        connect( nextAct, SIGNAL(activated()), this, SLOT(playNext()) );
 
148
 
 
149
        prevAct = new MyAction(Qt::Key_P /*Qt::Key_Less*/, this, "pl_prev");
 
150
        connect( prevAct, SIGNAL(activated()), this, SLOT(playPrev()) );
 
151
 
 
152
        moveUpAct = new MyAction(this, "pl_move_up");
 
153
        connect( moveUpAct, SIGNAL(activated()), this, SLOT(upItem()) );
 
154
 
 
155
        moveDownAct = new MyAction(this, "pl_move_down");
 
156
        connect( moveDownAct, SIGNAL(activated()), this, SLOT(downItem()) );
 
157
 
 
158
        repeatAct = new MyAction(this, "pl_repeat");
 
159
        repeatAct->setToggleAction(true);
 
160
 
 
161
        shuffleAct = new MyAction(this, "pl_shuffle");
 
162
        shuffleAct->setToggleAction(true);
 
163
 
 
164
        // Add actions
 
165
        addCurrentAct = new MyAction(this, "pl_add_current");
 
166
        connect( addCurrentAct, SIGNAL(activated()), this, SLOT(addCurrentFile()) );
 
167
 
 
168
        addFilesAct = new MyAction(this, "pl_add_files");
 
169
        connect( addFilesAct, SIGNAL(activated()), this, SLOT(addFiles()) );
 
170
 
 
171
        addDirectoryAct = new MyAction(this, "pl_add_directory");
 
172
        connect( addDirectoryAct, SIGNAL(activated()), this, SLOT(addDirectory()) );
 
173
 
 
174
        // Remove actions
 
175
        removeSelectedAct = new MyAction(this, "pl_remove_selected");
 
176
        connect( removeSelectedAct, SIGNAL(activated()), this, SLOT(removeSelected()) );
 
177
 
 
178
        removeAllAct = new MyAction(this, "pl_remove_all");
 
179
        connect( removeAllAct, SIGNAL(activated()), this, SLOT(removeAll()) );
 
180
 
 
181
        // Edit
 
182
        editAct = new MyAction(this, "pl_edit");
 
183
        connect( editAct, SIGNAL(activated()), this, SLOT(editCurrentItem()) );
 
184
}
 
185
 
 
186
void Playlist::createToolbar() {
 
187
        toolbar = new QToolBar(this, "toolbar");
 
188
        toolbar->setResizeEnabled(false);
 
189
        toolbar->setMovingEnabled(false);
 
190
        addDockWindow(toolbar, Qt::DockBottom );
 
191
 
 
192
        openAct->addTo( toolbar );
 
193
        saveAct->addTo( toolbar );
 
194
        toolbar->addSeparator();
 
195
 
 
196
        add_menu = new QPopupMenu( this, "add_menu" );
 
197
        addCurrentAct->addTo( add_menu );
 
198
        addFilesAct->addTo( add_menu );
 
199
        addDirectoryAct->addTo( add_menu );
 
200
 
 
201
        add_button = new QToolButton( toolbar, "add_button" );
 
202
        add_button->setPopup( add_menu );
 
203
        add_button->setPopupDelay(1);
 
204
 
 
205
        remove_menu = new QPopupMenu( this, "remove_menu" );
 
206
        removeSelectedAct->addTo( remove_menu );
 
207
        removeAllAct->addTo( remove_menu );
 
208
 
 
209
        remove_button = new QToolButton( toolbar, "remove_button" );
 
210
        remove_button->setPopup( remove_menu );
 
211
        remove_button->setPopupDelay(1);
 
212
 
 
213
        toolbar->addSeparator();
 
214
        playAct->addTo( toolbar );
 
215
        toolbar->addSeparator();
 
216
        prevAct->addTo( toolbar );
 
217
        nextAct->addTo( toolbar );
 
218
        toolbar->addSeparator();
 
219
        repeatAct->addTo( toolbar );
 
220
        shuffleAct->addTo( toolbar );
 
221
        toolbar->addSeparator();
 
222
        moveUpAct->addTo( toolbar );
 
223
        moveDownAct->addTo( toolbar );
 
224
 
 
225
        // Popup menu
 
226
        popup = new QPopupMenu(this, "popup");
 
227
        playAct->addTo( popup );
 
228
        removeSelectedAct->addTo( popup );
 
229
        editAct->addTo( popup );
 
230
        connect( listView, SIGNAL(contextMenuRequested(int,int,const QPoint &)),
 
231
             this, SLOT(showPopup(int,int,const QPoint &)) );
 
232
}
 
233
 
 
234
void Playlist::languageChange() {
 
235
        listView->horizontalHeader()->setLabel( COL_PLAY, "   " );
 
236
        listView->horizontalHeader()->setLabel( COL_NAME, tr("Name") );
 
237
        listView->horizontalHeader()->setLabel( COL_TIME, tr("Length") );
 
238
 
 
239
        openAct->change( Images::icon("open"), tr("&Load") );
 
240
        saveAct->change( Images::icon("save"), tr("&Save") );
 
241
 
 
242
        playAct->change( Images::icon("play"), tr("&Play") );
 
243
 
 
244
        nextAct->change( Images::icon("next"), tr("&Next") );
 
245
        prevAct->change( Images::icon("previous"), tr("Pre&vious") );
 
246
 
 
247
        moveUpAct->change( Images::icon("up"), tr("Move &up") );
 
248
        moveDownAct->change( Images::icon("down"), tr("Move &down") );
 
249
 
 
250
        repeatAct->change( Images::icon("repeat"), tr("&Repeat") );
 
251
        shuffleAct->change( Images::icon("shuffle"), tr("S&huffle") );
 
252
 
 
253
        // Add actions
 
254
        addCurrentAct->change( tr("Add &current file") );
 
255
        addFilesAct->change( tr("Add &file(s)") );
 
256
        addDirectoryAct->change( tr("Add &directory") );
 
257
 
 
258
        // Remove actions
 
259
        removeSelectedAct->change( tr("Remove &selected") );
 
260
        removeAllAct->change( tr("Remove &all") );
 
261
 
 
262
        // Edit
 
263
        editAct->change( tr("&Edit") );
 
264
 
 
265
        // Tool buttons
 
266
        add_button->setIconSet( Images::icon("plus") );
 
267
        QToolTip::add( add_button, tr("Add...") );
 
268
        remove_button->setIconSet( Images::icon("minus") );
 
269
        QToolTip::add( remove_button, tr("Remove...") );
 
270
 
 
271
        // Icon
 
272
        setIcon( Images::icon("logo", 64) );
 
273
        setCaption( tr( "SMPlayer - Playlist" ) );
 
274
}
 
275
 
 
276
void Playlist::list() {
 
277
        qDebug("Playlist::list");
 
278
 
 
279
        PlaylistItemList::iterator it;
 
280
        for ( it = pl.begin(); it != pl.end(); ++it ) {
 
281
                qDebug( "filename: '%s', name: '%s' duration: %f",
 
282
               (*it).filename().utf8().data(), (*it).name().utf8().data(),
 
283
               (*it).duration() );
 
284
        }
 
285
}
 
286
 
 
287
void Playlist::updateView() {
 
288
        listView->setNumRows( pl.count() );
 
289
 
 
290
        int n=0;
 
291
        QString number;
 
292
        QString name;
 
293
        QString time;
 
294
 
 
295
        PlaylistItemList::iterator it;
 
296
 
 
297
        for ( it = pl.begin(); it != pl.end(); ++it ) {
 
298
                number.sprintf("%03d", n +1 );
 
299
                name = (*it).name();
 
300
                if (name.isEmpty()) name = (*it).filename();
 
301
                time = Helper::formatTime( (int) (*it).duration() );
 
302
                
 
303
                //listView->setText(n, COL_POS, number);
 
304
                listView->setText(n, COL_NAME, name);
 
305
                listView->setText(n, COL_TIME, time);
 
306
 
 
307
                if ((*it).played()) {
 
308
                        listView->setPixmap(n, COL_PLAY, Images::icon("ok_small") );
 
309
                } else {
 
310
                        listView->setPixmap(n, COL_PLAY, QPixmap() );
 
311
                }
 
312
 
 
313
                n++;
 
314
        }
 
315
 
 
316
        for (n=0; n <= COL_TIME; n++) 
 
317
                listView->adjustColumn(n);
 
318
 
 
319
        setCurrentItem(current_item);
 
320
 
 
321
        //adjustSize();
 
322
}
 
323
 
 
324
void Playlist::setCurrentItem(int current) {
 
325
        int old_current = current_item;
 
326
        current_item = current;
 
327
 
 
328
        if ((current_item > -1) && (current_item < pl.count())) {
 
329
                pl[current_item].setPlayed(TRUE);
 
330
        }
 
331
 
 
332
        if ( (old_current >= 0) && (old_current < listView->numRows()) ) {
 
333
                listView->setPixmap(old_current, COL_PLAY, QPixmap() );
 
334
        }
 
335
 
 
336
        if ( (current_item >= 0) && (current_item < listView->numRows()) ) {
 
337
                listView->setPixmap(current_item, COL_PLAY, Images::icon("play") );
 
338
        }
 
339
        //if (current_item >= 0) listView->selectRow(current_item);
 
340
        if (current_item >= 0) {
 
341
                listView->clearSelection();
 
342
                listView->setCurrentCell( current_item, 0);
 
343
                listView->selectRow(current_item);
 
344
        }
 
345
}
 
346
 
 
347
void Playlist::clear() {
 
348
        pl.clear();
 
349
        listView->setNumRows(0);
 
350
        setCurrentItem(0);
 
351
 
 
352
        setModified( false );
 
353
}
 
354
 
 
355
int Playlist::count() {
 
356
        return pl.count();
 
357
}
 
358
 
 
359
bool Playlist::isEmpty() {
 
360
        return pl.isEmpty();
 
361
}
 
362
 
 
363
void Playlist::addItem(QString filename, QString name, double duration) {
 
364
        qDebug("Playlist::addItem: '%s'", filename.utf8().data());
 
365
 
 
366
        #ifdef Q_OS_WIN
 
367
        filename = Helper::changeSlashes(filename);
 
368
        #endif
 
369
 
 
370
        // Test if already is in the list
 
371
        bool exists = FALSE;
 
372
        PlaylistItemList::iterator it;
 
373
        for ( it = pl.begin(); it != pl.end(); ++it ) {
 
374
                if ( (*it).filename() == filename ) {
 
375
                        exists = TRUE;
 
376
                        break;
 
377
                }
 
378
        }
 
379
 
 
380
        if (!exists) {
 
381
                if (name.isEmpty()) {
 
382
                        QFileInfo fi(filename);
 
383
                        if (fi.exists()) {
 
384
                                // Local file
 
385
                                name = fi.fileName(); //fi.baseName(TRUE);
 
386
                        } else {
 
387
                                // Stream
 
388
                                name = filename;
 
389
                        }
 
390
                }
 
391
                pl.append( PlaylistItem(filename, name, duration) );
 
392
                //setModified( true ); // Better set the modified on a higher level
 
393
        } else {
 
394
                qDebug(" Not added. File already in the list");
 
395
        }
 
396
}
 
397
 
 
398
void Playlist::load_m3u(QString file) {
 
399
        qDebug("Playlist::load_m3u");
 
400
 
 
401
        bool utf8 = (QFileInfo(file).extension(FALSE).lower() == "m3u8");
 
402
 
 
403
        QRegExp m3u_id("^#EXTM3U|^#M3U");
 
404
        QRegExp info("^#EXTINF:(.*),(.*)");
 
405
 
 
406
    QFile f( file );
 
407
    if ( f.open( IO_ReadOnly ) ) {
 
408
                playlist_path = QFileInfo(file).dirPath();
 
409
 
 
410
                clear();
 
411
                QString filename="";
 
412
                QString name="";
 
413
                double duration=0;
 
414
 
 
415
        QTextStream stream( &f );
 
416
 
 
417
                if (utf8)
 
418
                        stream.setEncoding(QTextStream::UnicodeUTF8);
 
419
                else
 
420
                        stream.setEncoding(QTextStream::Locale);
 
421
 
 
422
        QString line;
 
423
        while ( !stream.atEnd() ) {
 
424
            line = stream.readLine(); // line of text excluding '\n'
 
425
            qDebug( " * line: '%s'", line.utf8().data() );
 
426
                        if (m3u_id.search(line)!=-1) {
 
427
                                //#EXTM3U
 
428
                                // Ignore line
 
429
                        }
 
430
                        else
 
431
                        if (info.search(line)!=-1) {
 
432
                                duration = info.cap(1).toDouble();
 
433
                                name = info.cap(2);
 
434
                                qDebug(" * name: '%s', duration: %f", name.utf8().data(), duration );
 
435
                        } 
 
436
                        else
 
437
                        if (line.startsWith("#")) {
 
438
                                // Comment
 
439
                                // Ignore
 
440
                        } else {
 
441
                                filename = line;
 
442
                                QFileInfo fi(filename);
 
443
                                if (fi.exists()) {
 
444
                                        filename = fi.absFilePath();
 
445
                                }
 
446
                                if (!fi.exists()) {
 
447
                                        if (QFileInfo( playlist_path + "/" + filename).exists() ) {
 
448
                                                filename = playlist_path + "/" + filename;
 
449
                                        }
 
450
                                }
 
451
                                addItem( filename, name, duration );
 
452
                                name=""; 
 
453
                                duration = 0;
 
454
                        }
 
455
        }
 
456
        f.close();
 
457
                list();
 
458
                updateView();
 
459
 
 
460
                setModified( false );
 
461
 
 
462
                startPlay();
 
463
        }
 
464
}
 
465
 
 
466
bool Playlist::save_m3u(QString file) {
 
467
        qDebug("Playlist::save_m3u: '%s'", file.utf8().data());
 
468
 
 
469
        QString dir_path = QFileInfo(file).dirPath();
 
470
        if (!dir_path.endsWith("/")) dir_path += "/";
 
471
 
 
472
        #ifdef Q_OS_WIN
 
473
        dir_path = Helper::changeSlashes(dir_path);
 
474
        #endif
 
475
 
 
476
        qDebug(" * dirPath: '%s'", dir_path.utf8().data());
 
477
 
 
478
        bool utf8 = (QFileInfo(file).extension(FALSE).lower() == "m3u8");
 
479
 
 
480
        QFile f( file );
 
481
    if ( f.open( IO_WriteOnly ) ) {
 
482
        QTextStream stream( &f );
 
483
 
 
484
                if (utf8) 
 
485
                        stream.setEncoding(QTextStream::UnicodeUTF8);
 
486
                else
 
487
                        stream.setEncoding(QTextStream::Locale);
 
488
 
 
489
                QString filename;
 
490
 
 
491
                stream << "#EXTM3U" << "\n";
 
492
                stream << "# Playlist created by SMPlayer " << VERSION << " \n";
 
493
 
 
494
                PlaylistItemList::iterator it;
 
495
                for ( it = pl.begin(); it != pl.end(); ++it ) {
 
496
                        filename = (*it).filename();
 
497
                        #ifdef Q_OS_WIN
 
498
                        filename = Helper::changeSlashes(filename);
 
499
                        #endif
 
500
                        stream << "#EXTINF:";
 
501
                        stream << (*it).duration() << ",";
 
502
                        stream << (*it).name() << "\n";
 
503
                        // Try to save the filename as relative instead of absolute
 
504
                        if (filename.startsWith( dir_path )) {
 
505
                                filename = filename.mid( dir_path.length() );
 
506
                        }
 
507
                        stream << filename << "\n";
 
508
                }
 
509
        f.close();
 
510
 
 
511
                setModified( false );
 
512
                return true;
 
513
    } else {
 
514
                return false;
 
515
        }
 
516
}
 
517
 
 
518
void Playlist::load() {
 
519
        if (maybeSave()) {
 
520
                QString s = MyFileDialog::getOpenFileName(
 
521
                    lastDir(),
 
522
                    tr("Playlists") +" (*.m3u *.m3u8)",
 
523
                    this,
 
524
                    "open file dialog",
 
525
                    tr("Choose a file") );
 
526
 
 
527
                if (!s.isEmpty()) {
 
528
                        latest_dir = QFileInfo(s).dirPath(TRUE);
 
529
                        load_m3u(s);
 
530
                }
 
531
        }
 
532
}
 
533
 
 
534
bool Playlist::save() {
 
535
        QString s = MyFileDialog::getSaveFileName(
 
536
                    lastDir(),
 
537
                    tr("Playlists") +" (*.m3u *.m3u8)",
 
538
                    this,
 
539
                    "save file dialog",
 
540
                    tr("Choose a filename") );
 
541
 
 
542
        if (!s.isEmpty()) {
 
543
                // If filename has no extension, add it
 
544
                if (QFileInfo(s).extension().isEmpty()) {
 
545
                        s = s + ".m3u";
 
546
                }
 
547
                if (QFileInfo(s).exists()) {
 
548
                        int res = QMessageBox::question( this,
 
549
                                        tr("Confirm overwrite?"),
 
550
                    tr("The file %1 already exists.\n"
 
551
                       "Do you want to overwrite?").arg(s),
 
552
                    QMessageBox::Yes,
 
553
                    QMessageBox::No,
 
554
                    QMessageBox::NoButton);
 
555
                        if (res == QMessageBox::No ) {
 
556
                return false;
 
557
                        }
 
558
                }
 
559
                latest_dir = QFileInfo(s).dirPath(TRUE);
 
560
                return save_m3u(s);
 
561
        } else {
 
562
                return false;
 
563
        }
 
564
}
 
565
 
 
566
bool Playlist::maybeSave() {
 
567
        if (!isModified()) return true;
 
568
 
 
569
        int res = QMessageBox::question( this,
 
570
                                tr("Playlist modified"),
 
571
                tr("There are unsaved changes, do you want to save the playlist?"),
 
572
                QMessageBox::Yes,
 
573
                QMessageBox::No,
 
574
                QMessageBox::Cancel);
 
575
 
 
576
        switch (res) {
 
577
                case QMessageBox::No : return true; // Discard changes
 
578
                case QMessageBox::Cancel : return false; // Cancel operation
 
579
                default : return save();
 
580
        }
 
581
}
 
582
 
 
583
void Playlist::playCurrent() {
 
584
        int current = listView->currentRow();
 
585
        if (current > -1) {
 
586
                playItem(current);
 
587
        }
 
588
}
 
589
 
 
590
void Playlist::itemDoubleClicked(int row) {
 
591
        qDebug("Playlist::itemDoubleClicked: row: %d", row );
 
592
        playItem(row);
 
593
}
 
594
 
 
595
void Playlist::showPopup(int row, int col, const QPoint & pos) {
 
596
        qDebug("Playlist::showPopup: row: %d col: %d", row, col );
 
597
        if (!popup->isVisible()) {
 
598
                popup->move( pos );
 
599
                popup->show();
 
600
        }
 
601
}
 
602
 
 
603
void Playlist::startPlay() {
 
604
        // Start to play
 
605
        if ( shuffleAct->isOn() ) 
 
606
                playItem( chooseRandomItem() );
 
607
        else
 
608
                playItem(0);
 
609
}
 
610
 
 
611
void Playlist::playItem( int n ) {
 
612
        qDebug("Playlist::playItem: %d (count:%d)", n, pl.count());
 
613
 
 
614
        if ( (n >= pl.count()) || (n < 0) ) {
 
615
                qDebug(" out of range");
 
616
                emit playlistEnded();
 
617
                return;
 
618
        }
 
619
 
 
620
        qDebug(" playlist_path: '%s'", playlist_path.utf8().data() );
 
621
 
 
622
        QString filename = pl[n].filename();
 
623
        QString filename_with_path = playlist_path + "/" + filename;
 
624
 
 
625
        if (!filename.isEmpty()) {
 
626
                //pl[n].setPlayed(TRUE);
 
627
                setCurrentItem(n);
 
628
                core->open(filename, 0);
 
629
        }
 
630
 
 
631
}
 
632
 
 
633
void Playlist::playNext() {
 
634
        qDebug("Playlist::playNext");
 
635
 
 
636
        if (shuffleAct->isOn()) {
 
637
                // Shuffle
 
638
                int chosen_item = chooseRandomItem();
 
639
                if (chosen_item == -1) {
 
640
                        clearPlayedTag();
 
641
                        if (repeatAct->isOn()) chosen_item = chooseRandomItem();
 
642
                }
 
643
                playItem( chosen_item );
 
644
        } else {
 
645
                bool finished_list = (current_item+1 >= pl.count());
 
646
                if (finished_list) clearPlayedTag();
 
647
 
 
648
                if ( (repeatAct->isOn()) && (finished_list) ) {
 
649
                        playItem(0);
 
650
                } else {
 
651
                        playItem( current_item+1 );
 
652
                }
 
653
        }
 
654
}
 
655
 
 
656
void Playlist::playPrev() {
 
657
        qDebug("Playlist::playPrev");
 
658
        playItem( current_item-1 );
 
659
}
 
660
 
 
661
void Playlist::getMediaInfo() {
 
662
        qDebug("Playlist:: getMediaInfo");
 
663
 
 
664
        QString filename = core->mdat.filename;
 
665
        double duration = core->mdat.duration;
 
666
        QString name = core->mdat.clip_name;
 
667
        QString artist = core->mdat.clip_artist;
 
668
 
 
669
        #ifdef Q_OS_WIN
 
670
        filename = Helper::changeSlashes(filename);
 
671
        #endif
 
672
 
 
673
        if (name.isEmpty()) {
 
674
                QFileInfo fi(filename);
 
675
                if (fi.exists()) {
 
676
                        // Local file
 
677
                        name = fi.fileName();
 
678
                } else {
 
679
                        // Stream
 
680
                        name = filename;
 
681
                }
 
682
        }
 
683
        if (!artist.isEmpty()) name = artist + " - " + name;
 
684
 
 
685
        int pos=0;
 
686
        PlaylistItemList::iterator it;
 
687
        for ( it = pl.begin(); it != pl.end(); ++it ) {
 
688
                if ( (*it).filename() == filename ) {
 
689
                        if ((*it).duration()<1) {
 
690
                                if (!name.isEmpty()) {
 
691
                                        (*it).setName(name);
 
692
                                }
 
693
                                (*it).setDuration(duration);
 
694
                                //setModified( true );
 
695
                        } 
 
696
                        else 
 
697
                        // Edited name (sets duration to 1)
 
698
                        if ((*it).duration()==1) {
 
699
                                (*it).setDuration(duration);
 
700
                                //setModified( true );
 
701
                        }
 
702
                        setCurrentItem(pos);
 
703
                }
 
704
                pos++;
 
705
        }
 
706
        updateView();
 
707
}
 
708
 
 
709
// Add current file to playlist
 
710
void Playlist::addCurrentFile() {
 
711
        qDebug("Playlist::addCurrentFile");
 
712
        if (!core->mdat.filename.isEmpty()) {
 
713
                addItem( core->mdat.filename, "", 0 );
 
714
                getMediaInfo();
 
715
        }
 
716
}
 
717
 
 
718
void Playlist::addFiles() {
 
719
        QStringList files = MyFileDialog::getOpenFileNames(
 
720
                            tr("All files") +" (*.*)",
 
721
                            lastDir(),
 
722
                            this,
 
723
                            "open files dialog",
 
724
                            tr("Select one or more files to open") );
 
725
 
 
726
        if (files.count()!=0) addFiles(files);  
 
727
}
 
728
 
 
729
void Playlist::addFiles(QStringList files) {
 
730
        qDebug("Playlist::addFiles");
 
731
 
 
732
    QStringList::Iterator it = files.begin();
 
733
    while( it != files.end() ) {
 
734
        addItem( (*it), "", 0 );
 
735
                // FIXME: set latest_dir only if the file is a local file,
 
736
        // to avoid that dvd:, vcd: and so on will be used.
 
737
                /* latest_dir = QFileInfo((*it)).dirPath(TRUE); */
 
738
        ++it;
 
739
    }
 
740
        updateView();
 
741
 
 
742
        qDebug( " * latest_dir: '%s'", latest_dir.utf8().data() );
 
743
}
 
744
 
 
745
void Playlist::addDirectory() {
 
746
        QString s = MyFileDialog::getExistingDirectory(
 
747
                    lastDir(),
 
748
                    this,
 
749
                    "get existing directory",
 
750
                    tr("Choose a directory"),
 
751
                    TRUE );
 
752
 
 
753
        if (!s.isEmpty()) {
 
754
                addDirectory(s);
 
755
                latest_dir = s;
 
756
        }
 
757
}
 
758
 
 
759
void Playlist::addDirectory(QString dir) {
 
760
        QStringList dir_list = QDir(dir).entryList();
 
761
 
 
762
        QString filename;
 
763
    QStringList::Iterator it = dir_list.begin();
 
764
    while( it != dir_list.end() ) {
 
765
                filename = dir;
 
766
                if (filename.right(1)!="/") filename += "/";
 
767
                filename += (*it);
 
768
                if (!QFileInfo(filename).isDir()) {
 
769
                        addItem( filename, "", 0 );
 
770
                }
 
771
                ++it;
 
772
        }
 
773
        updateView();
 
774
}
 
775
 
 
776
// Remove selected items
 
777
void Playlist::removeSelected() {
 
778
        qDebug("Playlist::removeSelected");
 
779
 
 
780
        int first_selected = -1;
 
781
 
 
782
        for (int n=0; n < listView->numRows(); n++) {
 
783
                if (listView->isRowSelected(n)) {
 
784
                        qDebug(" row %d selected", n);
 
785
                        pl[n].setMarkForDeletion(TRUE);
 
786
                        if (first_selected == -1) first_selected = n;
 
787
                }
 
788
        }
 
789
 
 
790
        PlaylistItemList::iterator it;
 
791
        for ( it = pl.begin(); it != pl.end(); ++it ) {
 
792
                if ( (*it).markedForDeletion() ) {
 
793
                        qDebug("Remove '%s'", (*it).filename().utf8().data());
 
794
                        it = pl.remove(it);
 
795
                        it--;
 
796
                        setModified( true );
 
797
                }
 
798
        }
 
799
 
 
800
        if (isEmpty()) setModified(false);
 
801
        updateView();
 
802
 
 
803
        if (first_selected >= listView->numRows()) 
 
804
                first_selected = listView->numRows() - 1;
 
805
 
 
806
        if ( ( first_selected > -1) && ( first_selected < listView->numRows() ) ) {
 
807
                listView->clearSelection();
 
808
                listView->setCurrentCell( first_selected, 0);
 
809
                listView->selectRow( first_selected );
 
810
        }
 
811
}
 
812
 
 
813
void Playlist::removeAll() {
 
814
        /*
 
815
        pl.clear();
 
816
        updateView();
 
817
        setModified( false );
 
818
        */
 
819
        clear();
 
820
}
 
821
 
 
822
void Playlist::clearPlayedTag() {
 
823
        PlaylistItemList::iterator it;
 
824
        for ( it = pl.begin(); it != pl.end(); ++it ) {
 
825
                (*it).setPlayed(FALSE);
 
826
        }
 
827
        updateView();
 
828
}
 
829
 
 
830
int Playlist::chooseRandomItem() {
 
831
        qDebug( "Playlist::chooseRandomItem");
 
832
        QValueList <int> fi; //List of not played items (free items)
 
833
 
 
834
        int n=0;
 
835
        PlaylistItemList::iterator it;
 
836
        for ( it = pl.begin(); it != pl.end(); ++it ) {
 
837
                if (! (*it).played() ) fi.append(n);
 
838
                n++;
 
839
        }
 
840
 
 
841
        qDebug(" * free items: %d", fi.count() );
 
842
 
 
843
        if (fi.count()==0) return -1; // none free
 
844
 
 
845
        qDebug(" * items: ");
 
846
        for (int i=0; i < fi.count(); i++) {
 
847
                qDebug("   * item: %d", fi[i]);
 
848
        }
 
849
 
 
850
        int selected = (int) ((double) fi.count() * rand()/(RAND_MAX+1.0));
 
851
        qDebug(" * selected item: %d (%d)", selected, fi[selected]);
 
852
        return fi[selected];
 
853
}
 
854
 
 
855
void Playlist::swapItems(int item1, int item2 ) {
 
856
        PlaylistItem it1 = pl[item1];
 
857
        pl[item1] = pl[item2];
 
858
        pl[item2] = it1;
 
859
        setModified( true );
 
860
}
 
861
 
 
862
 
 
863
void Playlist::upItem() {
 
864
        qDebug("Playlist::upItem");
 
865
 
 
866
        int current = listView->currentRow();
 
867
        qDebug(" currentRow: %d", current );
 
868
 
 
869
        if (current >= 1) {
 
870
                swapItems( current, current-1 );
 
871
                if (current_item == (current-1)) current_item = current;
 
872
                else
 
873
                if (current_item == current) current_item = current-1;
 
874
                updateView();
 
875
                listView->clearSelection();
 
876
                listView->setCurrentCell( current-1, 0);
 
877
        }
 
878
}
 
879
 
 
880
void Playlist::downItem() {
 
881
        qDebug("Playlist::downItem");
 
882
 
 
883
        int current = listView->currentRow();
 
884
        qDebug(" currentRow: %d", current );
 
885
 
 
886
        if ( (current > -1) && (current < (pl.count()-1)) ) {
 
887
                swapItems( current, current+1 );
 
888
                if (current_item == (current+1)) current_item = current;
 
889
                else
 
890
                if (current_item == current) current_item = current+1;
 
891
                updateView();
 
892
                listView->clearSelection();
 
893
                listView->setCurrentCell( current+1, 0);
 
894
        }
 
895
}
 
896
 
 
897
void Playlist::editCurrentItem() {
 
898
        int current = listView->currentRow();
 
899
        if (current > -1) editItem(current);
 
900
}
 
901
 
 
902
void Playlist::editItem(int item) {
 
903
        QString current_name = pl[item].name();
 
904
        if (current_name.isEmpty()) current_name = pl[item].filename();
 
905
 
 
906
        bool ok;
 
907
        QString text = QInputDialog::getText(
 
908
            tr("Edit name"), 
 
909
            tr("Type the name that will be displayed in the playlist for this file:"), 
 
910
            QLineEdit::Normal,
 
911
            current_name, &ok, this );
 
912
    if ( ok && !text.isEmpty() ) {
 
913
        // user entered something and pressed OK
 
914
                pl[item].setName(text);
 
915
 
 
916
                // If duration == 0 the name will be overwritten!
 
917
                if (pl[item].duration()<1) pl[item].setDuration(1); 
 
918
                updateView();
 
919
 
 
920
                setModified( true );
 
921
    } 
 
922
}
 
923
 
 
924
// Drag&drop
 
925
void Playlist::dragEnterEvent( QDragEnterEvent *e ) {
 
926
        qDebug("Playlist::dragEnterEvent");
 
927
         #if QT_VERSION < 0x040000
 
928
        e->accept( (QUriDrag::canDecode(e) || QTextDrag::canDecode(e)) );
 
929
        #else
 
930
        e->accept(QUriDrag::canDecode(e));
 
931
        #endif
 
932
}
 
933
 
 
934
 
 
935
void Playlist::dropEvent( QDropEvent *e ) {
 
936
        qDebug("Playlist::dropEvent");
 
937
 
 
938
        QStringList files;
 
939
 
 
940
        if (QUriDrag::canDecode(e)) {
 
941
                QStrList l;
 
942
                QUriDrag::decode(e, l);
 
943
 
 
944
                QString s;
 
945
        for ( unsigned int i= 0; i < l.count(); ++i ) {
 
946
                        s = l.at(i);
 
947
                        qDebug(" * '%s'", s.utf8().data() );
 
948
#if KDE_SUPPORT
 
949
                        KURL u(s);
 
950
#else
 
951
                        QUrl u(s);
 
952
#endif
 
953
                        qDebug(" * protocol: '%s'", u.protocol().utf8().data());
 
954
                        qDebug(" * path: '%s'", u.path().utf8().data());
 
955
                        //qDebug(" filename:='%s'", u.fileName().utf8().data());
 
956
                        if (u.protocol()=="file") {
 
957
                                s = u.path();
 
958
                        }
 
959
                        files.append( s );
 
960
 
 
961
                }
 
962
        }
 
963
 
 
964
        #if QT_VERSION < 0x040000
 
965
        else
 
966
        if (QTextDrag::canDecode(e)) {
 
967
                QString s;
 
968
                if (QTextDrag::decode(e, s)) {
 
969
                        qDebug(" * '%s'", s.utf8().data() );
 
970
                        files.append( s );
 
971
                }
 
972
        }
 
973
        #endif
 
974
 
 
975
        QStringList only_files;
 
976
        for (int n = 0; n < files.count(); n++) {
 
977
                if ( QFileInfo( files[n] ).isDir() ) {
 
978
                        addDirectory( files[n] );
 
979
                } else {
 
980
                        //addFiles( files[n] );
 
981
                        //addItem( files[n], "", 0 );
 
982
                        only_files.append( files[n] );
 
983
                }
 
984
        }
 
985
        //updateView();
 
986
        //addFiles(files);
 
987
        addFiles( only_files );
 
988
}
 
989
 
 
990
 
 
991
void Playlist::hideEvent( QHideEvent * ) {
 
992
        emit visibilityChanged();
 
993
}
 
994
 
 
995
void Playlist::showEvent( QShowEvent * ) {
 
996
        emit visibilityChanged();
 
997
}
 
998
 
 
999
void Playlist::closeEvent( QCloseEvent * e )  {
 
1000
        saveSettings();
 
1001
        e->accept();
 
1002
}
 
1003
 
 
1004
 
 
1005
void Playlist::maybeSaveSettings() {
 
1006
        qDebug("Playlist::maybeSaveSettings");
 
1007
        if (isModified()) saveSettings();
 
1008
}
 
1009
 
 
1010
void Playlist::saveSettings() {
 
1011
        qDebug("Playlist::saveSettings");
 
1012
 
 
1013
        QSettings * set = settings;
 
1014
 
 
1015
        set->beginGroup( "playlist");
 
1016
 
 
1017
        set->writeEntry( "repeat", repeatAct->isOn() );
 
1018
        set->writeEntry( "shuffle", shuffleAct->isOn() );
 
1019
#if !DOCK_PLAYLIST
 
1020
        set->writeEntry( "window_width", size().width() );
 
1021
        set->writeEntry( "window_height", size().height() );
 
1022
#endif
 
1023
        set->writeEntry( "latest_dir", latest_dir );
 
1024
 
 
1025
        set->endGroup();
 
1026
 
 
1027
        //Save current list
 
1028
        set->beginGroup( "playlist_contents");
 
1029
 
 
1030
        set->writeEntry( "count", (int) pl.count() );
 
1031
        for ( int n=0; n < pl.count(); n++ ) {
 
1032
                set->writeEntry( QString("item_%1_filename").arg(n), pl[n].filename() );
 
1033
                set->writeEntry( QString("item_%1_duration").arg(n), pl[n].duration() );
 
1034
                set->writeEntry( QString("item_%1_name").arg(n), pl[n].name() );
 
1035
        }
 
1036
        set->writeEntry( "current_item", current_item );
 
1037
        set->writeEntry( "modified", modified );
 
1038
 
 
1039
        set->endGroup();
 
1040
}
 
1041
 
 
1042
void Playlist::loadSettings() {
 
1043
        qDebug("Playlist::loadSettings");
 
1044
 
 
1045
        QSettings * set = settings;
 
1046
 
 
1047
        set->beginGroup( "playlist");
 
1048
 
 
1049
        repeatAct->setOn( set->readBoolEntry( "repeat", repeatAct->isOn() ) );
 
1050
        shuffleAct->setOn( set->readBoolEntry( "shuffle", shuffleAct->isOn() ) );
 
1051
 
 
1052
#if !DOCK_PLAYLIST
 
1053
        QSize s;
 
1054
        s.setWidth( set->readNumEntry( "window_width", size().width() ) );
 
1055
        s.setHeight( set->readNumEntry( "window_height", size().height() ) );
 
1056
        resize( s );
 
1057
#endif
 
1058
 
 
1059
        latest_dir = set->readEntry( "latest_dir", latest_dir );
 
1060
 
 
1061
        set->endGroup();
 
1062
 
 
1063
        //Load latest list
 
1064
        set->beginGroup( "playlist_contents");
 
1065
 
 
1066
        int count = set->readNumEntry( "count", 0 );
 
1067
        QString filename, name;
 
1068
        int duration;
 
1069
        for ( int n=0; n < count; n++ ) {
 
1070
                filename = set->readEntry( QString("item_%1_filename").arg(n), "" );
 
1071
                duration = set->readNumEntry( QString("item_%1_duration").arg(n), -1 );
 
1072
                name = set->readEntry( QString("item_%1_name").arg(n), "" );
 
1073
                addItem( filename, name, duration );
 
1074
        }
 
1075
        setCurrentItem( set->readNumEntry( "current_item", -1 ) );
 
1076
        setModified( set->readBoolEntry( "modified", false ) );
 
1077
        updateView();
 
1078
 
 
1079
        set->endGroup();
 
1080
}
 
1081
 
 
1082
QString Playlist::lastDir() {
 
1083
        QString last_dir = latest_dir;
 
1084
        if (last_dir.isEmpty()) last_dir = pref->latest_dir;
 
1085
        return last_dir;
 
1086
}
 
1087