aboutsummaryrefslogtreecommitdiff
path: root/src/ui/playlistmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/playlistmodel.cpp')
-rw-r--r--src/ui/playlistmodel.cpp899
1 files changed, 899 insertions, 0 deletions
diff --git a/src/ui/playlistmodel.cpp b/src/ui/playlistmodel.cpp
new file mode 100644
index 000000000..196608438
--- /dev/null
+++ b/src/ui/playlistmodel.cpp
@@ -0,0 +1,899 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <QWidget>
+#include <QFile>
+#include <QDir>
+#include <QtAlgorithms>
+#include <QFileInfo>
+#include <QTextStream>
+#include <QPluginLoader>
+#include <QApplication>
+#include <QTimer>
+#include <QSettings>
+
+#include <time.h>
+
+#include <decoder.h>
+#include <decoderfactory.h>
+
+#include "fileloader.h"
+#include "playlistmodel.h"
+#include "mediafile.h"
+#include "playlistformat.h"
+#include "playstate.h"
+
+#include <QMetaType>
+
+#define INVALID_ROW -1
+
+TagUpdater::TagUpdater(QObject* o,MediaFile* f):m_observable(o),m_file(f)
+{
+ m_file->setFlag(MediaFile::EDITING);
+ connect (m_observable, SIGNAL(destroyed (QObject * )),SLOT(updateTag()));
+ connect (m_observable, SIGNAL(destroyed (QObject * )),SLOT(deleteLater()));
+}
+
+void TagUpdater::updateTag()
+{
+ if(m_file->flag() == MediaFile::SCHEDULED_FOR_DELETION)
+ {
+ delete m_file;
+ m_file = NULL;
+ }
+ else
+ {
+ m_file->updateTags();
+ m_file->setFlag(MediaFile::FREE);
+ }
+}
+
+
+PlayListModel::PlayListModel ( QObject *parent )
+ : QObject ( parent ) , m_selection()
+{
+ qsrand(time(0));
+ m_total_length = 0;
+ m_current = 0;
+ m_block_update_signals = false;
+ is_repeatable_list = false;
+ m_play_state = new NormalPlayState(this);
+ //readSettings();
+
+ registerPlaylistFormat( new PLSPlaylistFormat);
+ registerPlaylistFormat( new M3UPlaylistFormat);
+#ifndef XSPF_PLUGIN
+ registerPlaylistFormat( new XSPFPlaylistFormat);
+#endif
+ loadExternalPlaylistFormats();
+}
+
+PlayListModel::~PlayListModel()
+{
+ writeSettings();
+ clear();
+ delete m_play_state;
+ qDeleteAll(m_registered_pl_formats);
+
+ foreach(GuardedFileLoader l,m_running_loaders)
+ {
+ if (!l.isNull())
+ {
+ l->finish();
+ l->wait();
+ }
+ }
+}
+
+void PlayListModel::load ( MediaFile *file )
+{
+ if (m_files.isEmpty())
+ m_currentItem = file;
+
+ m_total_length += file->length();
+ m_files << file;
+
+ //if (!m_block_update_signals)
+ emit listChanged();
+}
+
+int PlayListModel::count()
+{
+ return m_files.size();
+}
+
+MediaFile* PlayListModel::currentItem()
+{
+ if ( m_files.isEmpty() )
+ return 0;
+ else
+ return m_files.at ( qMin(m_files.size() - 1, m_current));
+}
+
+int PlayListModel::currentRow()
+{
+ return m_current;
+}
+
+bool PlayListModel::setCurrent ( int c )
+{
+ if ( c > count()-1 || c < 0)
+ return FALSE;
+ m_current = c;
+ m_currentItem = m_files.at(c);
+ emit currentChanged();
+ emit listChanged();
+ return TRUE;
+}
+
+
+bool PlayListModel::next()
+{
+ if (isFileLoaderRunning())
+ m_play_state->prepare();
+
+ return m_play_state->next();
+}
+
+bool PlayListModel::previous()
+{
+ if (isFileLoaderRunning())
+ m_play_state->prepare();
+
+ return m_play_state->previous();//)
+}
+
+void PlayListModel::clear()
+{
+ foreach(GuardedFileLoader l,m_running_loaders)
+ {
+ if (!l.isNull())
+ {
+ l->finish();
+ l->wait();
+ }
+ }
+
+ m_running_loaders.clear();
+
+ m_current = 0;
+ while ( !m_files.isEmpty() )
+ {
+ MediaFile* mf = m_files.takeFirst();
+
+ if(mf->flag() == MediaFile::FREE)
+ {
+ delete mf;
+ }
+ else if(mf->flag() == MediaFile::EDITING)
+ {
+ mf->setFlag(MediaFile::SCHEDULED_FOR_DELETION);
+ }
+ }
+
+ m_total_length = 0;
+ m_play_state->resetState();
+ emit listChanged();
+}
+
+void PlayListModel::clearSelection()
+{
+ for ( int i = 0; i<m_files.size(); ++i )
+ m_files.at ( i )->setSelected ( FALSE );
+ emit listChanged();
+}
+
+QList <QString> PlayListModel::getTitles ( int b,int l )
+{
+ QList <QString> m_titles;
+ for ( int i = b; ( i < b + l ) && ( i < m_files.size() ); ++i )
+ m_titles << m_files.at ( i )->title();
+ return m_titles;
+}
+
+QList <QString> PlayListModel::getTimes ( int b,int l )
+{
+ QList <QString> m_times;
+ for ( int i = b; ( i < b + l ) && ( i < m_files.size() ); ++i )
+ m_times << QString ( "%1" ).arg ( m_files.at ( i )->length() /60 ) +":"
+ +QString ( "%1" ).arg ( m_files.at ( i )->length() %60/10 ) +
+ QString ( "%1" ).arg ( m_files.at ( i )->length() %60%10 );
+ return m_times;
+}
+
+bool PlayListModel::isSelected ( int row )
+{
+ if (m_files.count() > row && row >= 0)
+ return m_files.at ( row )->isSelected();
+
+ return false;
+}
+
+void PlayListModel::setSelected ( int row, bool yes )
+{
+ if (m_files.count() > row && row >= 0)
+ m_files.at ( row )->setSelected ( yes );
+}
+
+void PlayListModel::removeSelected()
+{
+ removeSelection(false);
+}
+
+void PlayListModel::removeUnselected()
+{
+ removeSelection(true);
+}
+
+void PlayListModel::removeSelection(bool inverted)
+{
+ int i = 0;
+
+ int select_after_delete = -1;
+
+ while ( !m_files.isEmpty() && i<m_files.size() )
+ {
+ if ( m_files.at ( i )->isSelected() ^ inverted )
+ {
+ MediaFile* f = m_files.takeAt ( i );
+ m_total_length -= f->length();
+ if (m_total_length < 0)
+ m_total_length = 0;
+
+ if(f->flag() == MediaFile::FREE)
+ {
+ delete f;
+ f = NULL;
+ }
+ else if(f->flag() == MediaFile::EDITING)
+ f->setFlag(MediaFile::SCHEDULED_FOR_DELETION);
+
+ select_after_delete = i;
+
+ if ( m_current >= i && m_current!=0 )
+ m_current--;
+ }
+ else
+ i++;
+ }
+
+ if (!m_files.isEmpty())
+ m_currentItem = m_files.at(m_current);
+
+ if (select_after_delete >= m_files.count())
+ select_after_delete = m_files.count() - 1;
+
+ setSelected(select_after_delete,true);
+
+ m_play_state->prepare();
+
+ emit listChanged();
+}
+
+void PlayListModel::invertSelection()
+{
+ for ( int i = 0; i<m_files.size(); ++i )
+ m_files.at ( i )->setSelected ( !m_files.at ( i )->isSelected() );
+ emit listChanged();
+}
+
+void PlayListModel::selectAll()
+{
+ for ( int i = 0; i<m_files.size(); ++i )
+ m_files.at ( i )->setSelected ( TRUE );
+ emit listChanged();
+}
+
+void PlayListModel::showDetails()
+{
+ for ( int i = 0; i<m_files.size(); ++i )
+ {
+ if ( m_files.at ( i )->isSelected() )
+ {
+ DecoderFactory *fact = Decoder::findByPath ( m_files.at ( i )->path() );
+ if ( fact )
+ {
+ QObject* o = fact->showDetails ( 0, m_files.at ( i )->path() );
+ if(o)
+ {
+ TagUpdater *updater = new TagUpdater(o,m_files.at(i));
+ m_editing_files.append(m_files.at(i));
+ connect (updater, SIGNAL(destroyed (QObject * )),SIGNAL(listChanged()));
+ }
+ }
+
+ return;
+ }
+ }
+
+}
+
+
+void PlayListModel::readSettings()
+{
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ m_current = settings.value("Playlist/current",0).toInt();
+
+ QFile file ( QDir::homePath() +"/.qmmp/playlist.txt" );
+ file.open ( QIODevice::ReadOnly );
+
+ QStringList files;
+ QByteArray line;
+ m_files.clear();
+
+ while (!file.atEnd ())
+ {
+ line = file.readLine();
+ files << QString::fromUtf8 ( line ).trimmed ();
+ }
+
+ file.close ();
+
+ if(m_current > files.count() - 1)
+ m_current = 0;
+
+ int preload = (files.count() < 100) ? files.count() : 100;
+
+ for (int i = 0;i < preload;i++)
+ {
+ load(new MediaFile(files.takeAt(0)));
+ }
+
+ if (files.isEmpty())
+ {
+ doCurrentVisibleRequest ();
+ return;
+ }
+
+ FileLoader* f_loader = createFileLoader();
+ connect(f_loader, SIGNAL(finished ()), SLOT(doCurrentVisibleRequest ()));
+
+ f_loader->setFilesToLoad(files);
+ //f_loader->start(QThread::IdlePriority);
+ QTimer::singleShot(1000,f_loader,SLOT(start()));
+ //m_play_state->prepare();
+}
+
+void PlayListModel::writeSettings()
+{
+ QFile file ( QDir::homePath() +"/.qmmp/playlist.txt" );
+ file.open ( QIODevice::WriteOnly );
+ foreach ( MediaFile* m, m_files )
+ file.write ( m->path().toUtf8 () +"\n" );
+ file.close ();
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.setValue("Playlist/current", m_current);
+}
+
+void PlayListModel::addFile(const QString& path)
+{
+ if (path.isEmpty ())
+ return;
+ if (path.startsWith("http://"))
+ load(new MediaFile(path));
+ else if (Decoder::supports(path))
+ load(new MediaFile(path));
+
+ m_play_state->prepare();
+}
+
+FileLoader * PlayListModel::createFileLoader()
+{
+ FileLoader* f_loader = new FileLoader(this);
+// f_loader->setStackSize(20 * 1024 * 1024);
+ m_running_loaders << f_loader;
+ connect(f_loader,SIGNAL(newMediaFile(MediaFile*)),this,SLOT(load(MediaFile*)),Qt::QueuedConnection);
+ connect(f_loader,SIGNAL(finished()),this,SLOT(preparePlayState()));
+ connect(f_loader,SIGNAL(finished()),f_loader,SLOT(deleteLater()));
+ return f_loader;
+}
+
+void PlayListModel::addFiles(const QStringList &files)
+{
+ FileLoader* f_loader = createFileLoader();
+ f_loader->setFilesToLoad(files);
+ f_loader->start(QThread::IdlePriority);
+}
+
+void PlayListModel::addDirectory(const QString& s)
+{
+ FileLoader* f_loader = createFileLoader();
+ f_loader->setDirectoryToLoad(s);
+ f_loader->start(QThread::IdlePriority);
+}
+
+void PlayListModel::addFileList(const QStringList &l)
+{
+// qWarning("void// PlayListModel::addFileList(const QStringList &l)");
+ foreach(QString str,l)
+ {
+ QFileInfo f_info(str);
+ if (f_info.exists())
+ {
+ if (f_info.isDir())
+ addDirectory(str);
+ else
+ addFile(str);
+ }
+ // Do processing the rest of events to avoid GUI freezing
+ QApplication::processEvents(QEventLoop::AllEvents,10);
+ }
+}
+
+bool PlayListModel::setFileList(const QStringList & l)
+{
+ bool model_cleared = FALSE;
+ foreach(QString str,l)
+ {
+ QFileInfo f_info(str);
+ if (f_info.exists())
+ {
+ if (!model_cleared)
+ {
+ clear();
+ model_cleared = TRUE;
+ }
+ if (f_info.isDir())
+ addDirectory(str);
+ else
+ addFile(str);
+ }
+ // Do processing the rest of events to avoid GUI freezing
+ QApplication::processEvents(QEventLoop::AllEvents,10);
+ }
+
+ return model_cleared;
+}
+
+int PlayListModel::firstSelectedUpper(int row)
+{
+ for (int i = row - 1;i >= 0;i--)
+ {
+ if (isSelected(i))
+ return i;
+ }
+ return -1;
+}
+
+int PlayListModel::firstSelectedLower(int row)
+{
+ for (int i = row + 1;i < count() ;i++)
+ {
+ if (isSelected(i))
+ return i;
+ }
+ return -1;
+}
+
+void PlayListModel::moveItems( int from, int to )
+{
+ // Get rid of useless work
+ if (from == to)
+ return;
+
+ QList<int> selected_rows = getSelectedRows();
+
+ if (! (bottommostInSelection(from) == INVALID_ROW ||
+ from == INVALID_ROW ||
+ topmostInSelection(from) == INVALID_ROW)
+ )
+ {
+ if (from > to)
+ foreach(int i, selected_rows)
+ if (i + to - from < 0)
+ break;
+ else
+ m_files.move(i,i + to - from);
+ else
+ for (int i = selected_rows.count() - 1; i >= 0; i--)
+ if (selected_rows[i] + to -from >= m_files.count())
+ break;
+ else
+ m_files.move(selected_rows[i],selected_rows[i] + to - from);
+
+ m_current = m_files.indexOf(m_currentItem);
+
+ emit listChanged();
+ }
+}
+
+
+
+int PlayListModel::topmostInSelection( int row)
+{
+ if ( row == 0)
+ return 0;
+
+ for (int i = row - 1;i >= 0;i--)
+ {
+ if (isSelected(i))
+ continue;
+ else
+ return i + 1;
+ }
+ return 0;
+}
+
+int PlayListModel::bottommostInSelection( int row )
+{
+ if (row >= m_files.count() - 1)
+ return row;
+
+ for (int i = row + 1;i < count() ;i++)
+ {
+ if (isSelected(i))
+ continue;
+ else
+ return i - 1;
+ }
+ return count() - 1;
+}
+
+const SimpleSelection& PlayListModel::getSelection(int row )
+{
+ m_selection.m_top = topmostInSelection( row );
+ m_selection.m_anchor = row;
+ m_selection.m_bottom = bottommostInSelection( row );
+ m_selection.m_selected_rows = getSelectedRows();
+ return m_selection;
+}
+
+QList<int> PlayListModel::getSelectedRows() const
+{
+ QList<int>selected_rows;
+ for (int i = 0;i<m_files.count();i++)
+ {
+ if (m_files[i]->isSelected())
+ {
+ selected_rows.append(i);
+ }
+ }
+ return selected_rows;
+}
+
+QList< MediaFile * > PlayListModel::getSelectedItems() const
+{
+ QList<MediaFile*>selected_items;
+ for (int i = 0;i<m_files.count();i++)
+ {
+ if (m_files[i]->isSelected())
+ {
+ selected_items.append(m_files[i]);
+ }
+ }
+ return selected_items;
+}
+
+void PlayListModel::addToQueue()
+{
+ QList<MediaFile*> selected_items = getSelectedItems();
+ foreach(MediaFile* file,selected_items)
+ {/*
+ if (isQueued(file))
+ m_queued_songs.removeAt(m_queued_songs.indexOf(file));
+ else
+ m_queued_songs.append(file);
+ */
+ setQueued(file);
+ }
+ emit listChanged();
+}
+
+void PlayListModel::setQueued(MediaFile* file)
+{
+ if (isQueued(file))
+ m_queued_songs.removeAt(m_queued_songs.indexOf(file));
+ else
+ m_queued_songs.append(file);
+
+ emit listChanged();
+}
+
+bool PlayListModel::isQueued(MediaFile* f) const
+{
+ return m_queued_songs.contains(f);
+}
+
+void PlayListModel::setCurrentToQueued()
+{
+ setCurrent(row(m_queued_songs.at(0)));
+ m_queued_songs.pop_front();
+}
+
+bool PlayListModel::isEmptyQueue() const
+{
+ return m_queued_songs.isEmpty();
+}
+
+void PlayListModel::randomizeList()
+{
+ for (int i = 0;i < m_files.size();i++)
+ m_files.swap(qrand()%m_files.size(),qrand()%m_files.size());
+
+ m_current = m_files.indexOf(m_currentItem);
+ emit listChanged();
+}
+
+void PlayListModel::reverseList()
+{
+ for (int i = 0;i < m_files.size()/2;i++)
+ m_files.swap(i,m_files.size() - i - 1);
+
+ m_current = m_files.indexOf(m_currentItem);
+ emit listChanged();
+}
+
+////===============THE BEGINNING OF SORT IMPLEMENTATION =======================////
+
+// First we'll implement bundle of static compare procedures
+// to sort items in different ways
+static bool _titleLessComparator(MediaFile* s1,MediaFile* s2)
+{
+ return s1->title() < s2->title();
+}
+
+static bool _titleGreaterComparator(MediaFile* s1,MediaFile* s2)
+{
+ return s1->title() > s2->title();
+}
+
+static bool _pathAndFilenameLessComparator(MediaFile* s1,MediaFile* s2)
+{
+ return s1->path() < s2->path();
+}
+
+static bool _pathAndFilenameGreaterComparator(MediaFile* s1,MediaFile* s2)
+{
+ return s1->path() > s2->path();
+}
+
+static bool _filenameLessComparator(MediaFile* s1,MediaFile* s2)
+{
+ QFileInfo i_s1(s1->path());
+ QFileInfo i_s2(s2->path());
+ return i_s1.baseName() < i_s2.baseName();
+}
+
+static bool _filenameGreaterComparator(MediaFile* s1,MediaFile* s2)
+{
+ QFileInfo i_s1(s1->path());
+ QFileInfo i_s2(s2->path());
+ return i_s1.baseName() > i_s2.baseName();
+}
+
+static bool _dateLessComparator(MediaFile* s1,MediaFile* s2)
+{
+ return s1->year() < s2->year();
+}
+
+static bool _dateGreaterComparator(MediaFile* s1,MediaFile* s2)
+{
+ return s1->year() > s2->year();
+}
+
+// This is main sort method
+void PlayListModel::doSort(int sort_mode,QList<MediaFile*>& list_to_sort)
+{
+ QList<MediaFile*>::iterator begin;
+ QList<MediaFile*>::iterator end;
+
+ begin = list_to_sort.begin();
+ end = list_to_sort.end();
+
+ bool (*compareLessFunc)(MediaFile*,MediaFile*) = 0;
+ bool (*compareGreaterFunc)(MediaFile*,MediaFile*) = 0;
+
+ switch (sort_mode)
+ {
+ case TITLE:
+ compareLessFunc = _titleLessComparator;
+ compareGreaterFunc = _titleGreaterComparator;
+ break;
+ case FILENAME:
+ compareLessFunc = _filenameLessComparator;
+ compareGreaterFunc = _filenameGreaterComparator;
+ break;
+ case PATH_AND_FILENAME:
+ compareLessFunc = _pathAndFilenameLessComparator;
+ compareGreaterFunc = _pathAndFilenameGreaterComparator;
+ break;
+ case DATE:
+ compareLessFunc = _dateLessComparator;
+ compareGreaterFunc = _dateGreaterComparator;
+ break;
+ //qWarning("TODO Sort by Date: %s\t%d",__FILE__,__LINE__);
+ default:
+ compareLessFunc = _titleLessComparator;
+ compareGreaterFunc = _titleGreaterComparator;
+ }
+
+ static bool sorted_asc = false;
+ if (!sorted_asc)
+ {
+ qSort(begin,end,compareLessFunc);
+ sorted_asc = true;
+ }
+ else
+ {
+ qSort(begin,end,compareGreaterFunc);
+ sorted_asc = false;
+ }
+
+ m_current = m_files.indexOf(m_currentItem);
+}
+
+void PlayListModel::sortSelection(int mode)
+{
+ QList<MediaFile*>selected_items = getSelectedItems();
+ QList<int>selected_rows = getSelectedRows();
+
+ doSort(mode,selected_items);
+
+ for (int i = 0;i < selected_rows.count();i++)
+ m_files.replace(selected_rows[i],selected_items[i]);
+
+ m_current = m_files.indexOf(m_currentItem);
+ emit listChanged();
+}
+
+void PlayListModel::sort(int mode)
+{
+ doSort(mode,m_files);
+ emit listChanged();
+}
+
+////=============== THE END OF SORT IMPLEMENTATION =======================////
+
+void PlayListModel::prepareForShufflePlaying(bool val)
+{
+ if (m_play_state)
+ delete m_play_state;
+
+ if (val)
+ m_play_state = new ShufflePlayState(this);
+ else
+ m_play_state = new NormalPlayState(this);
+
+}
+
+void PlayListModel::prepareForRepeatablePlaying(bool val)
+{
+ is_repeatable_list = val;
+}
+
+void PlayListModel::doCurrentVisibleRequest()
+{
+ emit currentChanged();
+ emit listChanged();
+}
+
+void PlayListModel::setUpdatesEnabled(bool yes)
+{
+ if (yes)
+ {
+ m_block_update_signals = false;
+ emit listChanged();
+ }
+ else
+ {
+ m_block_update_signals = true;
+ }
+}
+
+void PlayListModel::loadPlaylist(const QString & f_name)
+{
+
+ foreach(PlaylistFormat* prs,m_registered_pl_formats.values())
+ {
+ if (prs->hasFormat(QFileInfo(f_name).completeSuffix().toLower()))
+ {
+ QFile file(f_name);
+ if (file.open(QIODevice::ReadOnly))
+ {
+ clear();
+ addFiles(prs->decode(QTextStream(&file).readAll()));
+ file.close();
+ }
+ else
+ qWarning("Error opening %s",f_name.toLocal8Bit().data());
+ }
+ }
+}
+
+void PlayListModel::savePlaylist(const QString & f_name)
+{
+ foreach(PlaylistFormat* prs,m_registered_pl_formats.values())
+ {
+ if (prs->hasFormat(QFileInfo(f_name).completeSuffix().toLower()))
+ {
+ QFile file(f_name);
+ if (file.open(QIODevice::WriteOnly))
+ {
+ QTextStream ts(&file);
+ ts << prs->encode(m_files);
+ file.close();
+ }
+ else
+ qWarning("Error opening %s",f_name.toLocal8Bit().data());
+ }
+ }
+}
+
+
+void PlayListModel::loadExternalPlaylistFormats()
+{
+ QDir pluginsDir (QDir::homePath()+"/.qmmp/plugins/PlaylistFormats");
+ //pluginsDir.cdUp();
+ //pluginsDir.cd("plugins/PlaylistFormats");
+ foreach (QString fileName, pluginsDir.entryList(QDir::Files))
+ {
+ QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
+ QObject *plugin = loader.instance();
+ if (loader.isLoaded())
+ qDebug("PlaylistFormat: plugin loaded - %s", qPrintable(fileName));
+
+ PlaylistFormat *fmt = 0;
+ if (plugin)
+ fmt = qobject_cast<PlaylistFormat *>(plugin);
+
+ if (fmt)
+ if (!registerPlaylistFormat(fmt))
+ qDebug("Warning: Plugin with name %s is already registered...",
+ qPrintable(fmt->name()));
+ }
+}
+
+bool PlayListModel::registerPlaylistFormat(PlaylistFormat* p)
+{
+ QString name = p->name();
+ if (!m_registered_pl_formats.contains(name))
+ {
+ m_registered_pl_formats.insert(name,p);
+ return true;
+ }
+ return false;
+}
+
+bool PlayListModel::isFileLoaderRunning() const
+{
+ foreach(FileLoader* l,m_running_loaders)
+ if (l && l->isRunning())
+ return TRUE;
+
+ return FALSE;
+}
+
+void PlayListModel::preparePlayState()
+{
+ m_play_state->prepare();
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+