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

« back to all changes in this revision

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