diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2009-10-23 21:06:09 +0200 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2009-10-23 21:06:09 +0200 |
commit | 95fc9a918f123ec165f1048aa5ea8b522a4a806a (patch) | |
tree | 3a778fa417c954920fbf54071abde912236ace43 /qtspotifymain.cpp |
First commit
Diffstat (limited to 'qtspotifymain.cpp')
-rw-r--r-- | qtspotifymain.cpp | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/qtspotifymain.cpp b/qtspotifymain.cpp new file mode 100644 index 0000000..af8e2a2 --- /dev/null +++ b/qtspotifymain.cpp @@ -0,0 +1,431 @@ +#include "qtspotifymain.h" +#include "logindialog.h" + +#include <QtCore/QtConcurrentRun> +#include <QtCore/QFuture> +#include <QtCore/QFutureWatcher> +#include <QtCore/QStateMachine> +#include <QtCore/QState> +#include <QtCore/QSettings> + +#include <QtGui/QMenuBar> +#include <QtGui/QMenu> +#include <QtGui/QMessageBox> +#include <QtGui/QGridLayout> +#include <QtGui/QInputDialog> + +#include "despotify_cpp.h" + +Q_DECLARE_METATYPE(playlist *) +Q_DECLARE_METATYPE(track *) + +QtSpotifyMain::QtSpotifyMain(QWidget *parent) + : QMainWindow(parent), m_session(0), m_searchResult(0), m_storedPlaylist(0), + m_machine(new QStateMachine), m_debugging(false), + m_authenticationWatcher(0), m_retrievingPlayListWatcher(0) +{ + initUi(); + initWatchers(); + initMachine(); +} + +QtSpotifyMain::~QtSpotifyMain() +{ + QSettings settings("qtspotify", "qtspotify"); + settings.setValue(QString::fromLatin1("debuggingOutput"), + m_ui.actionDebuggingOutput->isChecked()); + + if (m_session != 0) { + endSession(); + } + +} + +void QtSpotifyMain::initUi() +{ + m_ui.setupUi(this); + + m_logInDialog = new LogInDialog(this); + + QSettings settings("qtspotify", "qtspotify"); + + bool debuggingOutput = settings.value(QString::fromLatin1("debuggingOutput")).toBool(); + setDebugging(debuggingOutput); + m_ui.actionDebuggingOutput->setChecked(debuggingOutput); + connect(m_ui.actionDebuggingOutput, SIGNAL(toggled(bool)), this, SLOT(setDebugging(bool))); + + QString userName = settings.value(QString::fromLatin1("userName")).toString(); + QString password = settings.value(QString::fromLatin1("password")).toString(); + + if (userName.isEmpty() || password.isEmpty()) { + m_logInDialog->setRememberSettings(false); + } else { + m_logInDialog->setRememberSettings(true); + m_logInDialog->setUserName(userName); + m_logInDialog->setPassword(password); + } + + setStatusBar(new MyStatusBar(this)); +} + +void QtSpotifyMain::initWatchers() +{ + m_authenticationWatcher = new QFutureWatcher<bool>(this); + connect(m_authenticationWatcher, SIGNAL(finished()), this, SLOT(decideLoginResult())); + + m_retrievingPlayListWatcher = new QFutureWatcher<playlist *>(this); + connect(m_retrievingPlayListWatcher, SIGNAL(finished()), this, SLOT(populateSearchBox())); +} + +void QtSpotifyMain::retrievePlayLists() +{ + debug(tr("Retrieving playlists")); + m_ui.searchComboBox->clear(); + m_ui.searchComboBox->clearEditText(); + + if (m_storedPlaylist != 0) + despotify_free_playlist(m_storedPlaylist); + + QFuture<playlist *> retrieving = QtConcurrent::run(despotify_get_stored_playlists, m_session); + m_retrievingPlayListWatcher->setFuture(retrieving); +} + +void QtSpotifyMain::selectPlayList() +{ + QString searchTerm = m_ui.searchComboBox->currentText(); + if (m_searchResult != 0) { + despotify_free_search(m_searchResult); + m_searchResult = 0; + } + + m_ui.playList->clear(); + + int idx = m_ui.searchComboBox->currentIndex(); + if (idx >= 0) { + QVariant data = m_ui.searchComboBox->itemData(idx); + playlist *pl = data.value<playlist *>(); + if (pl != 0) { + debug(tr("Selecting playlist '%1'").arg(QString::fromUtf8(pl->name))); + setPlayList(pl->tracks); + return; + } + } + + m_searchResult = despotify_search(m_session, searchTerm.toUtf8().data(), 50); + if (m_searchResult != 0) { + debug(tr("Searching for '%1'").arg(searchTerm)); + setPlayList(m_searchResult->tracks); + } else { + debug(tr("No results when searching for '%1'").arg(searchTerm)); + } +} + +void QtSpotifyMain::populateSearchBox() +{ + debug(tr("Populating search box")); + m_storedPlaylist = m_retrievingPlayListWatcher->result(); + if (m_storedPlaylist == 0) + debug(tr("Cannot get stored playlists, error==%1").arg(QString::fromUtf8(m_session->last_error))); + + playlist *pl = m_storedPlaylist; + while (pl != 0) { + m_ui.searchComboBox->addItem(QString::fromUtf8(pl->name), QVariant::fromValue(pl)); + debug(tr("Adding '%1'").arg(QString::fromUtf8(pl->name))); + pl = pl->next; + } + + m_ui.searchComboBox->setEditText(QString()); +} + +void QtSpotifyMain::stop() +{ + debug(tr("Stopping")); + despotify_stop(m_session); +} + +void QtSpotifyMain::pause() +{ + debug(tr("Pausing")); + despotify_pause(m_session); +} + +void QtSpotifyMain::resume() +{ + debug(tr("Resuming")); + despotify_resume(m_session); +} + +void QtSpotifyMain::play() +{ + if (m_ui.playList->currentItem() == 0) { + qWarning("Nothing to play"); + return ; + } + + QVariant data = m_ui.playList->currentItem()->data(0, Qt::UserRole); + track *t = data.value<track *>(); + if (t != 0) { + debug(tr("Playing '%1'").arg(t->title)); + if (!despotify_play(m_session, t, false)) { + QMessageBox::information(this, tr("Error when playing track"), + tr("Despotify error: %1").arg(QString::fromUtf8(m_session->last_error))); + } else { + setNewTrack(t); + } + } else { + qWarning("No track connected to current item"); + } +} + +void QtSpotifyMain::initPlayingState(QState *playingState) +{ + QState *notPaused = new QState(playingState); + notPaused->setObjectName("notPaused"); + playingState->setInitialState(notPaused); + + QState *paused = new QState(playingState); + paused->setObjectName("paused"); + connect(paused, SIGNAL(entered()), this, SLOT(pause())); + connect(paused, SIGNAL(exited()), this, SLOT(resume())); + + notPaused->addTransition(m_ui.actionPauseOrResume, SIGNAL(triggered()), paused); + paused->addTransition(m_ui.actionPauseOrResume, SIGNAL(triggered()), notPaused); +} + +void QtSpotifyMain::decideLoginResult() +{ + if (m_authenticationWatcher->result()) { + debug(tr("Login succeeded")); + emit loggedIn(); + } else { + debug(tr("Login failed, error==%1").arg(QString::fromUtf8(m_session->last_error))); + emit loginFailed(); + } +} + +void QtSpotifyMain::initPlayBackHandlingState(QState *playBackHandlingState) +{ + QState *stoppedState = new QState(playBackHandlingState); + stoppedState->assignProperty(m_ui.actionPauseOrResume, "enabled", false); + stoppedState->assignProperty(m_ui.actionPlayOrStop, "enabled", true); + stoppedState->assignProperty(m_ui.albumLabel, "text", QString()); + stoppedState->assignProperty(m_ui.artistLabel, "text", QString()); + stoppedState->assignProperty(m_ui.songLabel, "text", QString()); + stoppedState->setObjectName("stoppedState"); + connect(stoppedState, SIGNAL(entered()), this, SLOT(stop())); + playBackHandlingState->setInitialState(stoppedState); + + QState *playingState = new QState(playBackHandlingState); + playingState->setObjectName("playingState"); + playingState->assignProperty(m_ui.actionPlayOrStop, "enabled", true); + connect(playingState, SIGNAL(entered()), this, SLOT(play())); + stoppedState->assignProperty(m_ui.actionPauseOrResume, "enabled", true); + initPlayingState(playingState); + + stoppedState->addTransition(m_ui.actionPlayOrStop, SIGNAL(triggered()), playingState); + playingState->addTransition(m_ui.actionPlayOrStop, SIGNAL(triggered()), stoppedState); + + + stoppedState->addTransition(m_ui.playList, SIGNAL(doubleClicked(QModelIndex)), + playingState); + playingState->addTransition(m_ui.playList, SIGNAL(doubleClicked(QModelIndex)), + playingState); + +} + +void QtSpotifyMain::initLoggedInState(QState *loggedIn) +{ + QState *playListHandlingState = new QState(loggedIn); + playListHandlingState->setObjectName("playListHandlingState"); + initPlayListHandlingState(playListHandlingState); + + QState *playBackHandlingState = new QState(loggedIn); + playBackHandlingState->setObjectName("playBackHandlingState"); + initPlayBackHandlingState(playBackHandlingState); +} + +void QtSpotifyMain::initPlayListHandlingState(QState *playListHandlingState) +{ + QState *idle = new QState(playListHandlingState); + idle->assignProperty(m_ui.actionSearch, "enabled", true); + idle->assignProperty(m_ui.searchComboBox, "enabled", true); + idle->assignProperty(m_ui.playList, "enabled", true); + idle->assignProperty(m_ui.actionRetrieveStoredPlaylists, "enabled", true); + idle->setObjectName("idle"); + idle->assignProperty(statusBar(), "statusMessage", tr("Go ahead...")); + playListHandlingState->setInitialState(idle); + + QState *requestedRetrieve = new QState(playListHandlingState); + requestedRetrieve->assignProperty(m_ui.actionSearch, "enabled", false); + requestedRetrieve->assignProperty(m_ui.searchComboBox, "enabled", false); + requestedRetrieve->assignProperty(m_ui.playList, "enabled", true); + requestedRetrieve->assignProperty(m_ui.actionRetrieveStoredPlaylists, "enabled", false); + connect(requestedRetrieve, SIGNAL(entered()), this, SLOT(retrievePlayLists())); + requestedRetrieve->setObjectName("requestedRetrieve"); + + QState *playListSelected = new QState(playListHandlingState); + playListSelected->setObjectName("playListSelected"); + connect(playListSelected, SIGNAL(entered()), this, SLOT(selectPlayList())); + + idle->addTransition(m_ui.searchComboBox, SIGNAL(activated(QString)), + playListSelected); + idle->addTransition(m_ui.actionRetrieveStoredPlaylists, SIGNAL(triggered()), + requestedRetrieve); + + playListSelected->addTransition(idle); + + requestedRetrieve->addTransition(m_retrievingPlayListWatcher, SIGNAL(finished()), idle); +} + +void QtSpotifyMain::debug(const QString &text) +{ + if (m_debugging) + qDebug() << text; +} + +void QtSpotifyMain::initLoggingInState(QState *loggingInState) +{ + QState *logInDialogShown = new QState(loggingInState); + connect(logInDialogShown, SIGNAL(entered()), m_logInDialog, SLOT(exec())); + logInDialogShown->assignProperty(statusBar(), "statusMessage", tr("Waiting for input")); + logInDialogShown->setObjectName("logInDialogShown"); + loggingInState->setInitialState(logInDialogShown); + + QState *logInDialogAccepted = new QState(loggingInState); + logInDialogAccepted->assignProperty(statusBar(), "statusMessage", tr("Trying to log in...")); + logInDialogAccepted->setObjectName("logInDialogAccepted"); + connect(logInDialogAccepted, SIGNAL(entered()), this, SLOT(logIn())); + + logInDialogShown->addTransition(m_logInDialog, SIGNAL(accepted()), logInDialogAccepted); +} + +void QtSpotifyMain::initMachine() +{ + QState *notLoggedInState = new QState(m_machine); + notLoggedInState->assignProperty(m_ui.actionLogIn, "enabled", true); + notLoggedInState->assignProperty(m_ui.actionLogOut, "enabled", false); + notLoggedInState->assignProperty(m_ui.actionSearch, "enabled", false); + notLoggedInState->assignProperty(m_ui.centralwidget, "enabled", false); + notLoggedInState->assignProperty(m_ui.actionPauseOrResume, "enabled", false); + notLoggedInState->assignProperty(m_ui.actionPlayOrStop, "enabled", false); + notLoggedInState->assignProperty(m_ui.actionRetrieveStoredPlaylists, "enabled", false); + notLoggedInState->assignProperty(statusBar(), "statusMessage", tr("Not logged in")); + notLoggedInState->assignProperty(this, "debuggingMessage", tr("Entered 'notLoggedInState'")); + notLoggedInState->setObjectName("notLoggedInState"); + m_machine->setInitialState(notLoggedInState); + + QState *loggingInState = new QState(m_machine); + loggingInState->assignProperty(m_ui.actionLogIn, "enabled", false); + loggingInState->assignProperty(m_ui.actionLogOut, "enabled", false); + loggingInState->assignProperty(m_ui.actionSearch, "enabled", false); + loggingInState->assignProperty(m_ui.centralwidget, "enabled", false); + loggingInState->assignProperty(m_ui.actionPauseOrResume, "enabled", false); + loggingInState->assignProperty(m_ui.actionPlayOrStop, "enabled", false); + loggingInState->assignProperty(m_ui.actionRetrieveStoredPlaylists, "enabled", false); + loggingInState->setObjectName("loggingInState"); + loggingInState->assignProperty(this, "debuggingMessage", tr("Entered 'loggingInState'")); + initLoggingInState(loggingInState); + + QState *loggedInState = new QState(QState::ParallelStates, m_machine); + loggedInState->assignProperty(m_ui.actionLogIn, "enabled", false); + loggedInState->assignProperty(m_ui.actionLogOut, "enabled", true); + loggedInState->assignProperty(m_ui.centralwidget, "enabled", true); + loggedInState->setObjectName("loggedInState"); + loggedInState->assignProperty(this, "debuggingMessage", tr("Entered 'loggedInState'")); + initLoggedInState(loggedInState); + + notLoggedInState->addTransition(m_ui.actionLogIn, SIGNAL(triggered()), loggingInState); + loggingInState->addTransition(m_logInDialog, SIGNAL(rejected()), notLoggedInState); + loggingInState->addTransition(this, SIGNAL(loginFailed()), notLoggedInState); + loggingInState->addTransition(this, SIGNAL(loggedIn()), loggedInState); + + m_machine->start(); +} + +void QtSpotifyMain::setPlayList(track *t) +{ + debug(tr("Setting new playlist")); + m_ui.playList->clear(); + while (t != 0) { + QTreeWidgetItem *w = new QTreeWidgetItem(); + + w->setData(0, Qt::DisplayRole, QString::fromUtf8(t->artist->name)); + w->setData(1, Qt::DisplayRole, QString::fromUtf8(t->title)); + w->setData(2, Qt::DisplayRole, QString::fromUtf8(t->album)); + w->setData(0, Qt::UserRole, QVariant::fromValue(t)); + + m_ui.playList->addTopLevelItem(w); + + t = t->next; + } +} + +static void callback(despotify_session *session, int signal, void *data, void *callbackData) +{ + if (callbackData == 0 || data == 0 || session == 0) + return; + + switch (signal) { + case DESPOTIFY_TRACK_CHANGE: + { + track *t = reinterpret_cast<track *>(data); + QtSpotifyMain *qsm = reinterpret_cast<QtSpotifyMain*>(session->client_callback_data); + qsm->setNewTrack(t); + } + }; +} + +void QtSpotifyMain::endSession() +{ + debug("Ending session"); + if (m_storedPlaylist != 0) + despotify_free_playlist(m_storedPlaylist); + + if (m_searchResult != 0) { + despotify_free_search(m_searchResult); + m_searchResult = 0; + } + + m_ui.searchComboBox->clear(); + despotify_exit(m_session); +} + +void QtSpotifyMain::logIn() +{ + if (m_session == 0) { + m_session = despotify_init_client(callback, this); + if (m_session == 0) { + emit loginFailed(); + return; + } + } + + QString userName = m_logInDialog->userName(); + QString password = m_logInDialog->password(); + + QSettings settings("qtspotify", "qtspotify"); + if (m_logInDialog->rememberSettings()) { + debug("Saving settings"); + settings.setValue(QString::fromLatin1("userName"), userName); + settings.setValue(QString::fromLatin1("password"), password); + } else { + debug("Clearing settings"); + settings.remove(QString::fromLatin1("userName")); + settings.remove(QString::fromLatin1("password")); + } + + debug(tr("Logging in as user '%1'").arg(userName)); + QFuture<bool> authentication = QtConcurrent::run(despotify_authenticate, + m_session, + userName.toLocal8Bit(), + password.toLocal8Bit()); + m_authenticationWatcher->setFuture(authentication); +} + +void QtSpotifyMain::setNewTrack(track *t) +{ + debug(tr("Setting new track '%1'").arg(QString::fromUtf8(t->title))); + m_ui.artistLabel->setText(QString::fromUtf8(t->artist->name)); + m_ui.albumLabel->setText(QString::fromUtf8(t->album)); + m_ui.songLabel->setText(QString::fromUtf8(t->title)); +} |