src/mediascanner.cpp \
src/tagresolver.cpp \
src/playerform.cpp \
- src/libraryform.cpp
+ src/libraryform.cpp \
+ src/busywidget.cpp
HEADERS += src/mainwindow.h \
src/player/player.h \
src/mediascanner.h \
src/tagresolver.h \
src/playerform.h \
- src/libraryform.h
+ src/libraryform.h \
+ src/busywidget.h
FORMS += src/ui/mainwindow.ui \
src/ui/playerform.ui \
- src/ui/libraryform.ui
+ src/ui/libraryform.ui \
+ src/ui/busywidget.ui
CONFIG += mobility
MOBILITY =
--- /dev/null
+#include "busywidget.h"
+#include "ui_busywidget.h"
+
+BusyWidget::BusyWidget(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::BusyWidget)
+{
+ ui->setupUi(this);
+}
+
+BusyWidget::~BusyWidget()
+{
+ delete ui;
+}
+
+void BusyWidget::setText(QString text) {
+ ui->label->setText(text);
+}
--- /dev/null
+#ifndef BUSYWIDGET_H
+#define BUSYWIDGET_H
+
+#include <QWidget>
+
+namespace Ui {
+ class BusyWidget;
+}
+
+class BusyWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit BusyWidget(QWidget *parent = 0);
+ ~BusyWidget();
+ void setText(QString text);
+
+private:
+ Ui::BusyWidget *ui;
+};
+
+#endif // BUSYWIDGET_H
#include <QFileInfo>
#include <QTextStream>
#include <QRegExp>
+#include <QDebug>
using namespace SomePlayer::Storage;
using namespace SomePlayer::DataObjects;
_path_prefix = path;
_meta_regexp.setPattern("#META \\[(\\d+)\\].*::(.+)::,::(.+)::,::(.+)::");
_path_regexp.setPattern("#PATH (.+)");
+
+ Playlist current = getCurrentPlaylist();
+ if (current.name() == PLAYLIST_BAD_NAME) {
+ current.setName(_CURRENT_PLAYLIST_NAME_);
+ saveCurrentPlaylist(current);
+ }
}
QList<Playlist> FileStorage::getPlaylists() {
Playlist FileStorage::getPlaylist(QString name) {
QFile playlistFile (_path_prefix+"/"+name+"."+_PLAYLIST_FILE_EXTENSION_);
Playlist playlist;
- playlist.setName("Bad playlist");
+ playlist.setName(PLAYLIST_BAD_NAME);
if (playlistFile.exists()) {
playlist.setName(name);
playlistFile.open(QFile::ReadOnly);
QFileInfo info(entry);
QString suffix = info.suffix().toLower();
if (suffix == _PLAYLIST_FILE_EXTENSION_) {
- playlistNames.append(info.fileName()
- .replace(QString(".%1").arg(_PLAYLIST_FILE_EXTENSION_), "", Qt::CaseInsensitive));
+ QString name = info.fileName().replace(QString(".%1").arg(_PLAYLIST_FILE_EXTENSION_), "", Qt::CaseInsensitive);
+ playlistNames.append(name);
}
}
return playlistNames;
}
void FileStorage::savePlaylist(Playlist playlist) {
- QString filename = _path_prefix+playlist.name()+_PLAYLIST_FILE_EXTENSION_;
+ QString filename = _path_prefix + "/" +playlist.name()+"."_PLAYLIST_FILE_EXTENSION_;
QFile playlistFile(filename);
if (playlistFile.exists()) {
playlistFile.remove();
}
+ playlistFile.open(QFile::WriteOnly);
QTextStream stream(&playlistFile);
stream << _PLAYLIST_SIGNATURE_ << endl;
const QList<Track> &tracks = playlist.tracks();
_scanner = new MediaScanner();
_resolver = new TagResolver(this);
connect(_scanner, SIGNAL(scanFinish(QStringList)), _resolver, SLOT(decode(QStringList)));
+ connect(_resolver, SIGNAL(done()), this, SIGNAL(addingDone()));
connect(_resolver, SIGNAL(decoded(Track)), this, SLOT(addTrack(Track)));
}
return _playlist_storage->getPlaylist(name);
}
-void Library::savePlaylist(Playlist playlist) {
+void Library::savePlaylist(const Playlist &playlist) {
_playlist_storage->savePlaylist(playlist);
}
-void Library::removePlaylist(Playlist playlist) {
+void Library::removePlaylist(const Playlist &playlist) {
_playlist_storage->removePlaylist(playlist);
}
return _playlist_storage->getCurrentPlaylist();
}
-void Library::saveCurrentPlaylist(Playlist playlist) {
+void Library::saveCurrentPlaylist(const Playlist &playlist) {
_playlist_storage->saveCurrentPlaylist(playlist);
}
QList<Playlist> getPlaylists();
QStringList getPlaylistsNames();
Playlist getPlaylist(QString name);
- void savePlaylist(Playlist playlist);
- void removePlaylist(Playlist playlist);
+ void savePlaylist(const Playlist &playlist);
+ void removePlaylist(const Playlist &playlist);
void removePlaylist(QString name);
Playlist getCurrentPlaylist();
- void saveCurrentPlaylist(Playlist playlist);
+ void saveCurrentPlaylist(const Playlist &playlist);
+
+ signals:
+ void addingDone();
private:
DbStorage *_library_storage;
#include "playlist.h"
#include <QDebug>
#include <QTime>
+#include <QQueue>
using namespace SomePlayer::DataObjects;
connect(ui->listView, SIGNAL(clicked(QModelIndex)), this, SLOT(_process_list_click(QModelIndex)));
connect(ui->addButton, SIGNAL(clicked()), this, SLOT(_add_button()));
connect(ui->backButton, SIGNAL(clicked()), this, SLOT(_back_button()));
+ connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(_delete_button()));
_view_button();
}
LibraryForm::~LibraryForm()
{
+ _lib->saveCurrentPlaylist(_lib->getCurrentPlaylist());
delete ui;
}
_state = STATE_ARTIST;
ui->backButton->setEnabled(false);
ui->listLabel->setText("Artists");
+ ui->addButton->setEnabled(true);
+ ui->deleteButton->setEnabled(false);
}
void LibraryForm::_dynamic_button() {
__fill_model_tracks(_model, _current_tracks);
_state = STATE_PLAYLIST_TRACK;
ui->backButton->setEnabled(true);
+ ui->deleteButton->setEnabled(true);
ui->listLabel->setText(QString("Tracks in playlist \"%1\"").arg(data));
}
break;
void LibraryForm::_add_track(Track track) {
qDebug() << "adding TRACK " << track.metadata().title() << " from " << track.metadata().album() << " by " << track.metadata().artist();
+ Playlist current = _lib->getCurrentPlaylist();
+ current.addTrack(track);
+ _lib->saveCurrentPlaylist(current);
}
void LibraryForm::_add_playlist(QString name) {
_state = STATE_PLAYLIST;
ui->backButton->setEnabled(false);
ui->listLabel->setText("Playlists");
+ ui->addButton->setEnabled(false);
+}
+
+void LibraryForm::_delete_button() {
+ if (_state == STATE_PLAYLIST_TRACK) {
+ QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
+ ui->listView->selectionModel()->clearSelection();
+ QQueue<int> to_delete;
+ foreach (QModelIndex id, selected) {
+ _delete_track(_current_tracks.at(id.row()));
+ to_delete.append(id.row());
+ }
+ qSort(to_delete);
+ int count = to_delete.count();
+ for (int i = count-1; i >= 0; i--) {
+ _current_tracks.removeAt(to_delete.at(i));
+ }
+ __fill_model_tracks(_model, _current_tracks);
+ }
+}
+
+void LibraryForm::_delete_track(Track track) {
+ Playlist current = _lib->getCurrentPlaylist();
+ current.removeTrack(track);
+ _lib->saveCurrentPlaylist(current);
}
using SomePlayer::DataObjects::Library;
using SomePlayer::DataObjects::Track;
+using SomePlayer::DataObjects::Playlist;
enum LibraryFormListState {STATE_NONE, STATE_ARTIST, STATE_ALBUM, STATE_TRACK, STATE_PLAYLIST, STATE_PLAYLIST_TRACK};
void _dynamic_button();
void _playlists_button();
void _add_button();
+ void _delete_button();
void _back_button();
void _process_list_click(QModelIndex);
void _add_album(QString artist, QString album);
void _add_track(Track track);
void _add_playlist(QString name);
+ void _delete_track(Track track);
};
#endif // LIBRARYFORM_H
connect(ui->actionPlayer, SIGNAL(triggered()), this, SLOT(player()));
connect(ui->actionLibrary, SIGNAL(triggered()), this, SLOT(library()));
setAnimated(true);
- _playerForm = new PlayerForm(_library, ui->stackedWidget);
- _libraryForm = new LibraryForm(_library, ui->stackedWidget);
- ui->stackedWidget->insertWidget(0, _playerForm);
- ui->stackedWidget->insertWidget(1, _libraryForm);
- connect(_playerForm, SIGNAL(library()), this, SLOT(library()));
- connect(_libraryForm, SIGNAL(player()), this, SLOT(player()));
+ _player_form = new PlayerForm(_library, ui->stackedWidget);
+ _library_form = new LibraryForm(_library, ui->stackedWidget);
+ _busy_widget = new BusyWidget(ui->stackedWidget);
+ ui->stackedWidget->insertWidget(0, _player_form);
+ ui->stackedWidget->insertWidget(1, _library_form);
+ ui->stackedWidget->insertWidget(2, _busy_widget);
+ _library_menu = new QMenu("Lirary");
+ QAction *add_directory = _library_menu->addAction("Add directory");
+ _player_menu = new QMenu("Player");
+ connect(_player_form, SIGNAL(library()), this, SLOT(library()));
+ connect(_library_form, SIGNAL(player()), this, SLOT(player()));
+ connect(add_directory, SIGNAL(triggered()), this, SLOT(_add_directory()));
+ connect(_library, SIGNAL(addingDone()), this, SLOT(library()));
library();
}
MainWindow::~MainWindow()
{
- delete _playerForm;
- delete _libraryForm;
+ delete _player_form;
+ delete _library_form;
delete ui;
}
}
void MainWindow::player() {
- _playerForm->show();
ui->stackedWidget->setCurrentIndex(0);
+ _player_form->reload();
setWindowTitle("SomePlayer");
}
void MainWindow::library() {
- _libraryForm->show();
+ ui->menuBar->setEnabled(true);
ui->stackedWidget->setCurrentIndex(1);
setWindowTitle("SomePlayer Library");
+ ui->menuBar->addMenu(_library_menu);
+}
+
+void MainWindow::_add_directory() {
+ QString directory = QFileDialog::getExistingDirectory (this, "Select directory", "/home/user/MyDocs", QFileDialog::ShowDirsOnly );
+ if (!directory.isEmpty()) {
+ _busy_widget->setText("<H1>Scanning... Please wait</H1>");
+ ui->menuBar->setEnabled(false);
+ ui->stackedWidget->setCurrentIndex(2);
+ _library->addDirectory(directory);
+ }
}
#include <QMainWindow>
#include <QMessageBox>
+#include <QMenu>
#include "playerform.h"
#include "libraryform.h"
+#include "busywidget.h"
#include "library.h"
namespace Ui {
void about();
void player();
void library();
+private slots:
+ void _add_directory();
private:
- PlayerForm *_playerForm;
- LibraryForm *_libraryForm;
+ PlayerForm *_player_form;
+ LibraryForm *_library_form;
+ BusyWidget *_busy_widget;
+ QMenu *_library_menu;
+ QMenu *_player_menu;
Library *_library;
};
using namespace SomePlayer::Storage;
#include <QMap>
+#include <QDir>
MediaScanner::MediaScanner(QObject *parent) :
QThread(parent), _stopped(false), _initialized(false)
{
REGISTERED_FILE_EXTENSIONS << "mp3" << "flac" << "wma" << "acc";
- _iterator = NULL;
}
void MediaScanner::run() {
if (!_initialized)
return;
_foundMedia.clear();
- while(!_stopped && _iterator->hasNext()) {
- QString entry(_iterator->next());
- QFileInfo info(entry);
- if (info.isReadable()) {
+ _scan_directory(_dir);
+ emit scanFinish(_foundMedia);
+ _stopped = true;
+}
+
+void MediaScanner::_scan_directory(QDir dir) {
+ QFileInfoList items = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (QFileInfo info, items) {
+ if (info.isDir()) {
+ QDir ndir(info.absoluteFilePath());
+ _scan_directory(ndir);
+ } else {
QString suffix = info.suffix().toLower();
if (REGISTERED_FILE_EXTENSIONS.contains(suffix)) {
if (!_foundMedia.contains(info.absoluteFilePath()))
}
}
}
- emit scanFinish(_foundMedia);
- _stopped = true;
}
void MediaScanner::stop() {
void MediaScanner::init(QString dir) {
_stopped = false;
_initialized = true;
- if (!_iterator)
- delete _iterator;
- _iterator = new QDirIterator(QDir(dir), QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
+ _dir = dir;
}
void stop();
void init(QString);
private:
- QDirIterator *_iterator;
+ QDir _dir;
bool _stopped;
bool _initialized;
QStringList REGISTERED_FILE_EXTENSIONS;
QStringList _foundMedia;
+
+ void _scan_directory(QDir);
};
};
Player::Player(QObject *parent) :
QObject(parent)
{
- _player = NULL;
+ _player = new Phonon::MediaObject(this);
+ _output = new Phonon::AudioOutput(Phonon::MusicCategory, this);
+ _player->setTickInterval(1000);
+ connect(_player, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(_stateChanged(Phonon::State,Phonon::State)));
+ connect(_player, SIGNAL(tick(qint64)), this, SLOT(_tick(qint64)));
+ Phonon::createPath(_player, _output);
+ int seed = reinterpret_cast<int> (_player);
+ srand(seed);
+ _random = false;
+ _repeat = false;
}
-void Player::setTrack(Track &track) {
- _current_track = track;
- _create_player();
- emit stateChanged(PLAYER_LOADING);
+void Player::setTrackId(int id) {
+ _current = id;
+ _history.push(_current);
+ _set_source();
+ _state = PLAYER_LOADING;
+ emit stateChanged(_state);
}
void Player::play() {
- if (_player) {
- _player->play();
- emit stateChanged(PLAYER_PLAYING);
- }
+ _player->play();
+ _state = PLAYER_PLAYING;
+ emit stateChanged(_state);
}
void Player::stop() {
- if (_player) {
- _player->stop();
- emit stateChanged(PLAYER_STOPPED);
- }
+ _player->stop();
+ _state = PLAYER_STOPPED;
+ emit stateChanged(_state);
}
void Player::pause() {
- if (_player) {
- _player->pause();
- emit stateChanged(PLAYER_PAUSED);
- }
+ _player->pause();
+ _state = PLAYER_PAUSED;
+ emit stateChanged(_state);
}
-void Player::_create_player() {
- if (_player) {
- disconnect(_player, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(_stateChanged(Phonon::State,Phonon::State)));
- delete _player;
+void Player::next() {
+ _history.push(_current);
+ if (_random) {
+ _current = rand() % _playlist.tracks().count();
+ } else {
+ _current = (_current + 1) % _playlist.tracks().count();
+ }
+ if (_history.count()-1 == _playlist.tracks().count() && !_repeat) {
+ _history.clear();
+ stop();
+ } else {
+ _set_source();
+ play();
}
- _player = Phonon::createPlayer(Phonon::MusicCategory, Phonon::MediaSource(_current_track.source()));
- _player->setTickInterval(1000);
- connect(_player, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(_stateChanged(Phonon::State,Phonon::State)));
- connect(_player, SIGNAL(tick(qint64)), this, SLOT(_tick(qint64)));
- emit stateChanged(PLAYER_STOPPED);
+}
+
+void Player::_set_source() {
+ qDebug() << "id: " << _current << " all: " << _playlist.tracks().count();
+ Track track = _playlist.tracks().at(_current);
+ _player->setCurrentSource(Phonon::MediaSource(track.source()));
+ emit trackChanged(track);
+}
+
+void Player::prev() {
+ if (_history.count() > 0)
+ _current = _history.pop();
+ _set_source();
+ play();
}
void Player::_stateChanged(Phonon::State newState, Phonon::State oldState) {
+ qDebug() << "state changed: " << oldState << "->" << newState;
+ switch (newState) {
+ case Phonon::PlayingState:
+ if (_state == PLAYER_LOADING) {
+ _state = PLAYER_PLAYING;
+ emit stateChanged(_state);
+ }
+ break;
+ case Phonon::StoppedState:
+ break;
+ case Phonon::LoadingState:
+ break;
+ case Phonon::PausedState:
+ if (_state == PLAYER_PLAYING) {
+ next();
+ } else if (_state == PLAYER_ERROR) {
+ play();
+ }
+ break;
+ case Phonon::BufferingState:
+ break;
+ case Phonon::ErrorState:
+ _state = PLAYER_ERROR;
+ qDebug() << _player->errorString();
+ break;
+ }
}
void Player::_tick(qint64 ticks) {
- emit tick(ticks/1000, _current_track.metadata().length());
+ emit tick(ticks/1000, _playlist.tracks().at(_current).metadata().length());
+}
+
+void Player::setPlaylist(Playlist playlist) {
+ _playlist = playlist;
+ _history.clear();
+}
+
+void Player::seek(int s) {
+ qDebug() << "seeking " << s;
+ _player->seek(s*1000);
}
#include <QObject>
#include "../someplayer.h"
#include "../track.h"
+#include "../trackmetainformation.h"
+#include "../playlist.h"
#include <phonon/MediaObject>
#include <phonon/AudioOutput>
+#include <QStack>
// represents player
using SomePlayer::DataObjects::Track;
+using SomePlayer::DataObjects::TrackMetadata;
+using SomePlayer::DataObjects::Playlist;
namespace SomePlayer {
namespace Playback {
- enum PlayerState { PLAYER_STOPPED, PLAYER_PLAYING, PLAYER_PAUSED, PLAYER_LOADING, PLAYER_DONE };
+ enum PlayerState { PLAYER_STOPPED, PLAYER_PLAYING, PLAYER_PAUSED, PLAYER_LOADING, PLAYER_DONE, PLAYER_ERROR };
class Player : public QObject
{
public:
explicit Player(QObject *parent = 0);
+ bool random() {return _random;}
+ bool repeat() {return _repeat;}
+ Phonon::MediaObject* mediaObject() {return _player;}
+
signals:
void stateChanged (PlayerState);
+ void trackChanged (Track);
void tick (int, int); // played | all (seconds)
public slots:
- void setTrack(Track&);
+ void setTrackId(int id);
void play();
void pause();
void stop();
+ void next();
+ void prev();
+ void setPlaylist(Playlist);
+ void toggleRandom() {_random = !_random;}
+ void toggleRepeat() {_repeat = !_repeat;}
+ void seek(int);
private slots:
void _stateChanged(Phonon::State, Phonon::State);
void _tick(qint64);
private:
- Track _current_track;
+ int _current;
+ bool _random;
+ bool _repeat;
+ QStack<int> _history;
+ Playlist _playlist;
Phonon::MediaObject *_player;
- void _create_player();
+ Phonon::AudioOutput *_output;
+ PlayerState _state;
+
+ void _set_source();
};
};
};
#include "playerform.h"
#include "ui_playerform.h"
+#include "library.h"
+#include <QDebug>
+#include <QTime>
+#include <QSlider>
using namespace SomePlayer::DataObjects;
+using namespace SomePlayer::Playback;
+
+inline void __fill_list(QStandardItemModel *_model, Playlist playlist) {
+ _model->clear();
+ QList<Track> tracks = playlist.tracks();
+ int count = tracks.count();
+ _model->setRowCount(count);
+ for (int i = 0; i < count; i++) {
+ TrackMetadata meta = tracks.at(i).metadata();
+ _model->setItem(i, 0, new QStandardItem(meta.title()));
+ _model->setItem(i, 1, new QStandardItem(meta.artist()));
+ }
+}
PlayerForm::PlayerForm(Library* lib, QWidget *parent) :
- _lib(lib),
QWidget(parent),
ui(new Ui::PlayerForm)
{
+ _lib = lib;
+ _player = new Player(this);
ui->setupUi(this);
connect(ui->libraryButton, SIGNAL(clicked()), this, SLOT(_library()));
+ connect(ui->viewButton, SIGNAL(clicked()), this, SLOT(_toggle_view()));
+ connect(ui->playlistView, SIGNAL(clicked(QModelIndex)), this, SLOT(_process_click(QModelIndex)));
+ connect(ui->playButton, SIGNAL(clicked()), _player, SLOT(play()));
+ connect(ui->pauseButton, SIGNAL(clicked()), _player, SLOT(pause()));
+ connect(ui->stopButton, SIGNAL(clicked()), _player, SLOT(stop()));
+ connect(ui->nextButton, SIGNAL(clicked()), _player, SLOT(next()));
+ connect(ui->prevButton, SIGNAL(clicked()), _player, SLOT(prev()));
+ connect(_player, SIGNAL(trackChanged(Track)), this, SLOT(_track_changed(Track)));
+ connect(_player, SIGNAL(tick(int,int)), this, SLOT(_tick(int,int)));
+ _seek_slider = new QSlider(Qt::Horizontal);
+ ui->progressLayout->insertWidget(1, _seek_slider);
+ _seek_slider->setTracking(false);
+ connect(_seek_slider, SIGNAL(sliderMoved(int)), _player, SLOT(seek(int)));
+ _model = new QStandardItemModel(0, 2, this);
+ ui->playlistView->setModel(_model);
}
PlayerForm::~PlayerForm()
void PlayerForm::_library() {
emit library();
}
+
+void PlayerForm::reload() {
+ _current_playlist = _lib->getCurrentPlaylist();
+ _player->setPlaylist(_current_playlist);
+ __fill_list(_model, _current_playlist);
+}
+
+void PlayerForm::_toggle_view() {
+ int index = ui->stackedWidget->currentIndex();
+ index = (!index % 2);
+ ui->stackedWidget->setCurrentIndex(index);
+}
+
+void PlayerForm::_process_click(QModelIndex index) {
+ int id = index.row();
+ _player->stop();
+ _player->setTrackId(id);
+ _player->play();
+}
+
+void PlayerForm::_track_changed(Track track) {
+ int id = _current_playlist.tracks().indexOf(track);
+ QModelIndex index = _model->index(id, 0);
+ ui->playlistView->setCurrentIndex(index);
+ _display_track(track);
+}
+
+void PlayerForm::_display_track(Track track) {
+ ui->countLabel->setText(QString("%1/%2").
+ arg(_current_playlist.tracks().indexOf(track)+1).
+ arg(_current_playlist.tracks().count()));
+ ui->titleLabel->setText(QString("<h3>%1</h3>").arg(track.metadata().title()));
+ ui->artistAlbumLabel->setText(QString("<h3>%1</h3><br/>%2").
+ arg(track.metadata().artist()).
+ arg(track.metadata().album()));
+ _seek_slider->setMinimum(0);
+ _seek_slider->setMaximum(track.metadata().length());
+}
+
+void PlayerForm::_tick(int done, int all) {
+ QTime time1(0, all/60, all%60);
+ QTime time2(0, done/60, done%60);
+ ui->allTimeLabel->setText(time1.toString("mm:ss"));
+ ui->doneTimeLabel->setText(time2.toString("mm:ss"));
+ _seek_slider->setValue(done);
+}
+
+void PlayerForm::_slider_released() {
+ _player->seek(_seek_slider->value());
+}
#include <QWidget>
#include "someplayer.h"
+#include "playlist.h"
+#include <QStandardItemModel>
+#include "player/player.h"
+#include <QSlider>
namespace Ui {
class PlayerForm;
}
using SomePlayer::DataObjects::Library;
+using SomePlayer::DataObjects::Playlist;
+using SomePlayer::DataObjects::Track;
+using SomePlayer::Playback::Player;
class PlayerForm : public QWidget
{
signals:
void library();
+public slots:
+ void reload();
+
private slots:
void _library();
+ void _toggle_view();
+ void _process_click(QModelIndex);
+ void _track_changed(Track);
+ void _tick(int, int);
+ void _slider_released();
private:
Ui::PlayerForm *ui;
Library *_lib;
+ Playlist _current_playlist;
+ QStandardItemModel *_model;
+ Player *_player;
+ QSlider *_seek_slider;
+
+ void _display_track(Track);
};
#endif // PLAYERFORM_H
#include "playlist.h"
+#include <QDebug>
using namespace SomePlayer::DataObjects;
}
Playlist::Playlist(const Playlist &playlist) {
- _name = playlist.name();
- _tracks = playlist.tracks();
+ _name = playlist._name;
+ _tracks = playlist._tracks;
}
-Playlist& Playlist::operator =(const Playlist &playlist) {
- _name = playlist.name();
- _tracks = playlist.tracks();
- return *this;
-}
-
-QString Playlist::name() const {
+QString Playlist::name() {
return _name;
}
-const QList<Track> &Playlist::tracks() const {
+QList<Track> Playlist::tracks() {
return _tracks;
}
}
void Playlist::addTrack(Track track) {
- _tracks.append(track);
+ if (!_tracks.contains(track))
+ _tracks.append(track);
+}
+
+void Playlist::removeTrack(Track track) {
+ _tracks.removeOne(track);
}
#include "track.h"
#include "someplayer.h"
+#define PLAYLIST_BAD_NAME "Bad playlist"
+#define PLAYLIST_CURRENT_NAME "Current"
+
// represents playlist: list of tracks, name
namespace SomePlayer {
Playlist();
Playlist(const Playlist &playlist);
- Playlist &operator=(const Playlist &playlist);
-
- QString name() const;
- const QList<Track> &tracks() const;
+ QString name();
+ QList<Track> tracks();
void setName(QString name);
void addTrack(Track track);
+ void removeTrack(Track track);
private:
QString _name;
QMap<QString, QString> meta = _metaObject->metaData();
TrackMetadata metadata(meta.value("TITLE"), meta.value("ARTIST"), meta.value("ALBUM"), time/1000);
Track track(0, metadata, source.fileName());
- emit decoded(track);
int index = _sources.indexOf(source)+1;
+ emit decoded(track);
if (index != _sources.size()) {
Phonon::MediaSource newSource = _sources.at(index);
+ _metaObject->clear();
_metaObject->setCurrentSource(newSource);
+ } else {
+ emit done();
}
+ } else if (newState == Phonon::ErrorState) {
+ Phonon::MediaSource s = _metaObject->currentSource();
+ _metaObject->clear();
+ _metaObject->setCurrentSource(s);
}
}
signals:
void decoded(Track);
+ void done();
private slots:
void metaStateChanged(Phonon::State newState, Phonon::State /*oldState*/);
}
Track::~Track() {}
+
+bool Track::operator ==(const Track &track) {
+ return _source == track._source;
+}
void setSource (QString source);
int count() const; //count of plays
void setCount(int count); //for restoring from database and counting from player
+ bool operator == (const Track &track);
private:
TrackMetadata _metadata;
}
TrackMetadata::TrackMetadata(QString title = "", QString artist = "", QString album = "", int length = 0) {
- _metadata["TITLE"] = title == "" ? "Unknown title" : title;
- _metadata["ARTIST"] = artist == "" ? "Unknown artist" : artist;
- _metadata["ALBUM"] = album == "" ? "Unknown album" : album;
+ _metadata["TITLE"] = title == "" ? "Unknown title" : title.trimmed();
+ _metadata["ARTIST"] = artist == "" ? "Unknown artist" : artist.trimmed();
+ _metadata["ALBUM"] = album == "" ? "Unknown album" : album.trimmed();
_length = length;
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BusyWidget</class>
+ <widget class="QWidget" name="BusyWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>BUSY</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
</spacer>
</item>
<item>
+ <widget class="QPushButton" name="deleteButton">
+ <property name="text">
+ <string>Delete</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
<widget class="QPushButton" name="playerButton">
<property name="text">
<string>Player</string>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
<item>
<widget class="QLabel" name="listLabel">
<property name="enabled">
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QPushButton" name="libraryButton">
- <property name="text">
- <string>Library</string>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="stackedWidget">
+ <property name="currentIndex">
+ <number>1</number>
</property>
+ <widget class="QWidget" name="page">
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QListView" name="playlistView">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="textElideMode">
+ <enum>Qt::ElideLeft</enum>
+ </property>
+ <property name="uniformItemSizes">
+ <bool>true</bool>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_2">
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QWidget" name="widget" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="countLabel">
+ <property name="text">
+ <string>0/0</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="titleLabel">
+ <property name="text">
+ <string><h3>Title</h3></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="progressLayout">
+ <item>
+ <widget class="QLabel" name="doneTimeLabel">
+ <property name="text">
+ <string>00:00</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="allTimeLabel">
+ <property name="text">
+ <string>00:00</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="artistAlbumLabel">
+ <property name="text">
+ <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Droid Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:600;">Artist</span></p>
+<p style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large;">album</span></p></body></html></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="libraryButton">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Library</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="viewButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>^</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="prevButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="text">
+ <string><|</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="playButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>></string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pauseButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>||</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="stopButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>[]</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="nextButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>70</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>|></string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
</layout>
</widget>
<resources/>