2
* Copyright 2011 Kurtis L. Nusbaum
4
* This file is part of UDJ.
6
* UDJ is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 2 of the License, or
9
* (at your option) any later version.
11
* UDJ is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with UDJ. If not, see <http://www.gnu.org/licenses/>.
19
#include "DataStore.hpp"
20
#include "UDJServerConnection.hpp"
25
#include <QDesktopServices>
33
#include <QProgressDialog>
45
const QString& username,
46
const QString& password,
47
const QByteArray& ticket,
48
const user_id_t& userId,
56
serverConnection = new UDJServerConnection(this);
57
serverConnection->setTicket(ticket);
58
serverConnection->setUserId(userId);
59
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
60
if(settings.contains(getPlayerIdSettingName())){
61
serverConnection->setPlayerId(settings.value(getPlayerIdSettingName()).value<player_id_t>());
63
activePlaylistRefreshTimer = new QTimer(this);
64
activePlaylistRefreshTimer->setInterval(5000);
69
SIGNAL(playerPasswordSet(const QString&)),
71
SLOT(onPlayerPasswordSet(const QString&)));
75
SIGNAL(playerPasswordSetError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
77
SLOT(onPlayerPasswordSetError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
82
SIGNAL(playerLocationSet(const QString&, const QString&, const QString&, int)),
84
SLOT(onPlayerLocationSet(const QString&, const QString&, const QString&, int)));
88
SIGNAL(playerLocationSetError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
90
SLOT(onPlayerLocationSetError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
94
SIGNAL(playerPasswordRemoved()),
96
SLOT(onPlayerPasswordRemoved()));
100
SIGNAL(playerPasswordRemoveError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
102
SLOT(onPlayerPasswordRemoveError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
106
SIGNAL(playerNameChanged(const QString&)),
108
SLOT(onPlayerNameChanged(const QString&)));
112
SIGNAL(playerNameChangeError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
114
SLOT(onPlayerNameChangeError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
118
SIGNAL(libSongsSyncedToServer(const QSet<library_song_id_t>&)),
120
SLOT(setLibSongsSynced(const QSet<library_song_id_t>&)));
124
SIGNAL(playerCreated(const player_id_t&)),
126
SLOT(onPlayerCreate(const player_id_t&)));
130
SIGNAL(playerCreationFailed(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
132
SLOT(onPlayerCreationFailed(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
136
SIGNAL(newActivePlaylist(const QVariantMap&)),
138
SLOT(setActivePlaylist(const QVariantMap&)));
142
SIGNAL(getActivePlaylistFail(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
144
SLOT(onGetActivePlaylistFail(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
146
connect(activePlaylistRefreshTimer,
149
SLOT(refreshActivePlaylist()));
153
SIGNAL(currentSongSet()),
155
SLOT(refreshActivePlaylist()));
159
SIGNAL(playerStateSet(const QString&)),
161
SLOT(onPlayerStateChanged(const QString&)));
165
SIGNAL(libModError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
167
SLOT(onLibModError(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
171
SIGNAL(setCurrentSongFailed(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
173
SLOT(onSetCurrentSongFailed(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
177
SIGNAL(activePlaylistModified(const QSet<library_song_id_t>&, const QSet<library_song_id_t>&)),
179
SLOT(onActivePlaylistModified(const QSet<library_song_id_t>&, const QSet<library_song_id_t>&)));
183
SIGNAL(activePlaylistModFailed(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
185
SLOT(onActivePlaylistModFailed(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
189
SIGNAL(setVolumeFailed(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)),
191
SLOT(onSetVolumeFailed(const QString&, int, const QList<QNetworkReply::RawHeaderPair>&)));
196
SIGNAL(authenticated(const QByteArray&, const user_id_t&)),
198
SLOT(onReauth(const QByteArray&, const user_id_t&)));
202
SIGNAL(authFailed(const QString&)),
204
SLOT(onAuthFail(const QString&)));
208
void DataStore::setupDB(){
209
//TODO do all of this stuff in a seperate thread and return right away.
210
QDir dbDir(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
212
Logger::instance()->log("DB dir didn't exists. making it at : " + dbDir.absolutePath());
213
//TODO handle if this fails
214
dbDir.mkpath(dbDir.absolutePath());
216
QString dbFilePath = dbDir.absoluteFilePath(getPlayerDBName());
217
if(!QFile::exists(dbFilePath)){
218
Logger::instance()->log("DB file didn't exist, so creating it at: " + dbFilePath);
219
QFile dbFile(dbFilePath);
220
dbFile.open(QIODevice::WriteOnly);
223
database = QSqlDatabase::addDatabase("QSQLITE", getPlayerDBConnectionName());
224
database.setDatabaseName(dbFilePath);
227
QSqlQuery setupQuery(database);
230
"Error creating library table",
231
setupQuery.exec(getCreateLibraryQuery()),
235
"Error creating activePlaylist table.",
236
setupQuery.exec(getCreateActivePlaylistQuery()),
240
"Error creating activePlaylist view.",
241
setupQuery.exec(getCreateActivePlaylistViewQuery()),
246
void DataStore::removePlayerPassword(){
247
serverConnection->removePlayerPassword();
250
void DataStore::onPlayerPasswordRemoved(){
251
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
252
settings.remove(getPlayerPasswordSettingName());
253
emit playerPasswordRemoved();
256
void DataStore::onPlayerPasswordRemoveError(
257
const QString& errMessage,
259
const QList<QNetworkReply::RawHeaderPair>& /*headers*/)
261
//TODO handle reauth error
262
emit playerPasswordRemoveError(errMessage);
266
void DataStore::setPlayerPassword(const QString& newPassword){
267
serverConnection->setPlayerPassword(newPassword);
270
void DataStore::onPlayerPasswordSet(const QString& password){
271
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
272
settings.setValue(getPlayerPasswordSettingName(), password);
273
emit playerPasswordSet();
276
void DataStore::onPlayerPasswordSetError(
277
const QString& errMessage,
279
const QList<QNetworkReply::RawHeaderPair>& /*headers*/)
281
emit playerPasswordSetError(errMessage);
284
void DataStore::setPlayerLocation(
285
const QString& streetAddress,
287
const QString& state,
291
serverConnection->setPlayerLocation(streetAddress, city, state, zipcode);
294
void DataStore::onPlayerLocationSet(
295
const QString& streetAddress,
297
const QString& state,
301
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
302
settings.setValue(getAddressSettingName(), streetAddress);
303
settings.setValue(getCitySettingName(), city);
304
settings.setValue(getStateSettingName(), state);
305
settings.setValue(getZipCodeSettingName(), zipcode);
306
emit playerLocationSet();
309
void DataStore::onPlayerLocationSetError(
310
const QString& errMessage,
312
const QList<QNetworkReply::RawHeaderPair>& /*headers*/)
314
//TODO handle reauth error
315
emit playerLocationSetError(errMessage);
318
void DataStore::setPlayerName(const QString& newName){
319
serverConnection->setPlayerName(newName);
322
void DataStore::onPlayerNameChanged(const QString& newName){
323
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
324
settings.setValue(getPlayerNameSettingName(), newName);
325
emit playerNameChanged(newName);
328
void DataStore::onPlayerNameChangeError(
329
const QString& /*errMessage*/,
331
const QList<QNetworkReply::RawHeaderPair>& /*headers*/)
333
//TODO if reauth error, should reauth
334
if(errorCode == 409){
335
emit playerNameChangeError(tr(
336
"You already have a player with that name."
340
emit playerNameChangeError(tr(
341
"We seem to be having some techincal difficulties and couldn't change "
342
"the name of your player. Try again in a little bit."
346
void DataStore::pausePlayer(){
347
setPlayerState(getPausedState());
350
void DataStore::playPlayer(){
351
setPlayerState(getPlayingState());
354
void DataStore::setPlayerState(const QString& newState){
355
serverConnection->setPlayerState(newState);
359
void DataStore::addMusicToLibrary(
360
const QList<Phonon::MediaSource>& songs, QProgressDialog* progress)
362
bool isTransacting=database.transaction();
364
Logger::instance()->log("Was able to start transaction");
366
QSqlQuery addQuery(database);
368
"INSERT INTO "+getLibraryTableName()+
370
getLibSongColName() + ","+
371
getLibArtistColName() + ","+
372
getLibAlbumColName() + ","+
373
getLibGenreColName() + "," +
374
getLibTrackColName() + "," +
375
getLibFileColName() + "," +
376
getLibDurationColName() +")" +
377
"VALUES ( :song , :artist , :album , :genre, :track, :file, :duration );"
380
for(int i =0; i<songs.size(); ++i){
381
addSongToLibrary(songs[i], addQuery);
382
if(progress != NULL){
383
progress->setValue(i);
384
if(progress->wasCanceled()){
386
Logger::instance()->log("Rolling back transaction");
387
if(!database.rollback()){
388
Logger::instance()->log("Roll back failed");
396
Logger::instance()->log("Committing add transaction");
401
void DataStore::addSongToLibrary(const Phonon::MediaSource& song, QSqlQuery &addQuery){
402
QString fileName = song.fileName();
409
TagLib::FileRef f(fileName.toStdString().c_str());
410
if(!f.isNull() && f.tag() && f.audioProperties()){
411
TagLib::Tag *tag = f.tag();
412
songName = TStringToQString(tag->title());
413
artistName = TStringToQString(tag->artist());
414
albumName = TStringToQString(tag->album());
415
genre = TStringToQString(tag->genre());
416
duration = f.audioProperties()->length();
417
track = tag->track();
425
songName = unknownSongTitle();
427
if(artistName == ""){
428
artistName = unknownSongArtist();
431
albumName = unknownSongAlbum();
434
genre = unknownGenre();
437
Logger::instance()->log("adding song with title: " + songName + " to database");
439
library_song_id_t hostId =-1;
441
addQuery.bindValue(":song", songName);
442
addQuery.bindValue(":artist", artistName);
443
addQuery.bindValue(":album", albumName);
444
addQuery.bindValue(":genre", genre);
445
addQuery.bindValue(":track", track);
446
addQuery.bindValue(":file", fileName);
447
addQuery.bindValue(":duration", duration);
449
"Failed to add song library" << songName.toStdString(),
455
void DataStore::removeSongsFromLibrary(const QSet<library_song_id_t>& toRemove,
456
QProgressDialog* progress)
458
bool isTransacting = database.transaction();
459
QSqlQuery deleteQuery(database);
460
deleteQuery.prepare("UPDATE " + getLibraryTableName() + " "
461
"SET " + getLibIsDeletedColName() + "=1, "+
462
getLibSyncStatusColName() + "=" +
463
QString::number(getLibNeedsDeleteSyncStatus()) + " "
464
"WHERE " + getLibIdColName() + "= ?");
466
Q_FOREACH(library_song_id_t id, toRemove){
467
deleteQuery.bindValue(0, QVariant::fromValue<library_song_id_t>(id));
469
"Error setting song sync status",
472
if(progress != NULL){
473
progress->setValue(i);
474
if(progress->wasCanceled()){
489
void DataStore::addSongToActivePlaylist(library_song_id_t libraryId){
490
QSet<library_song_id_t> libIds;
491
libIds.insert(libraryId);
492
addSongsToActivePlaylist(libIds);
495
void DataStore::addSongsToActivePlaylist(const QSet<library_song_id_t>& libIds){
496
playlistIdsToAdd.unite(libIds);
497
QSet<library_song_id_t> emptySet;
498
serverConnection->modActivePlaylist(libIds, emptySet);
501
void DataStore::removeSongsFromActivePlaylist(const QSet<library_song_id_t>& libIds){
502
playlistIdsToRemove.unite(libIds);
503
QSet<library_song_id_t> emptySet;
504
serverConnection->modActivePlaylist(emptySet, libIds);
507
QSqlDatabase DataStore::getDatabaseConnection(){
508
QSqlDatabase toReturn = QSqlDatabase::database(getPlayerDBConnectionName());
512
Phonon::MediaSource DataStore::getNextSongToPlay(){
513
QSqlQuery nextSongQuery("SELECT " + getLibFileColName() + " FROM " +
514
getActivePlaylistViewName() + " LIMIT 1;");
516
"Getting next song failed",
517
nextSongQuery.exec(),
519
//TODO handle is this returns false
520
if(nextSongQuery.first()){
521
return Phonon::MediaSource(nextSongQuery.value(0).toString());
524
return Phonon::MediaSource("");
528
DataStore::song_info_t DataStore::takeNextSongToPlay(){
529
QSqlQuery nextSongQuery(
530
"SELECT " + getLibFileColName() + ", " +
531
getLibSongColName() + ", " +
532
getLibArtistColName() + ", " +
533
getActivePlaylistLibIdColName() +" FROM " +
534
getActivePlaylistViewName() + " LIMIT 1;",
537
"Getting next song in take failed",
538
nextSongQuery.exec(),
540
nextSongQuery.next();
541
if(!nextSongQuery.isValid()){
543
song_info_t toReturn = {Phonon::MediaSource(""), "", "" };
547
nextSongQuery.value(3).value<library_song_id_t>();
549
deleteSongFromPlaylist(currentSongId);
551
Logger::instance()->log("Setting current song with id: " + QString::number(currentSongId));
552
serverConnection->setCurrentSong(currentSongId);
554
QString filePath = nextSongQuery.value(0).toString();
555
song_info_t toReturn = {
556
Phonon::MediaSource(filePath),
557
nextSongQuery.value(1).toString(),
558
nextSongQuery.value(2).toString()
565
void DataStore::deleteSongFromPlaylist(library_song_id_t toDelete){
566
QSqlQuery deleteSongQuery(
567
"DELETE FROM " + getActivePlaylistTableName() +
569
getActivePlaylistLibIdColName() + " = " + QString::number(toDelete) + ";",
572
"Deleting song from playlist failed",
573
deleteSongQuery.exec(),
577
void DataStore::setCurrentSong(const library_song_id_t& songToPlay){
578
QSqlQuery getSongQuery(
579
"SELECT " + getLibFileColName() + ", " +
580
getLibSongColName() + ", " +
581
getLibArtistColName() + " FROM " +
582
getActivePlaylistViewName() + " WHERE " +
583
getActivePlaylistLibIdColName() + " = " + QString::number(songToPlay) + ";",
586
"Getting song for manual playlist set failed.",
590
if(getSongQuery.isValid()){
591
Logger::instance()->log("Got file, for manual song set");
592
QString filePath = getSongQuery.value(0).toString();
593
currentSongId = songToPlay;
594
serverConnection->setCurrentSong(songToPlay);
595
Logger::instance()->log("Retrieved Artist " + getSongQuery.value(2).toString());
596
song_info_t toEmit = {
597
Phonon::MediaSource(filePath),
598
getSongQuery.value(1).toString(),
599
getSongQuery.value(2).toString()
601
emit manualSongChange(toEmit);
605
void DataStore::createNewPlayer(
607
const QString& password)
609
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
610
settings.setValue(getPlayerNameSettingName(), name);
611
settings.setValue(getPlayerPasswordSettingName(), password);
612
serverConnection->createPlayer(name, password);
615
void DataStore::createNewPlayer(
617
const QString& password,
618
const QString& streetAddress,
620
const QString& state,
623
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
624
settings.setValue(getPlayerNameSettingName(), name);
625
settings.setValue(getPlayerPasswordSettingName(), password);
626
settings.setValue(getAddressSettingName(), streetAddress);
627
settings.setValue(getCitySettingName(), city);
628
settings.setValue(getStateSettingName(), state);
629
settings.setValue(getZipCodeSettingName(), zipcode);
630
serverConnection->createPlayer(
639
void DataStore::changeVolumeSilently(qreal newVolume){
640
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
641
Logger::instance()->log("Current volume " + QString::number(settings.value(getPlayerVolumeSettingName()).toReal()));
642
Logger::instance()->log("New volume " + QString::number(newVolume));
643
if((int)(settings.value(getPlayerVolumeSettingName()).toReal()*10) != (int)(newVolume*10)){
644
Logger::instance()->log("Volume was different than current volume, now setting");
645
settings.setValue(getPlayerVolumeSettingName(), newVolume);
646
serverConnection->setVolume((int)(newVolume * 10));
655
void DataStore::syncLibrary(){
656
QSqlQuery needAddSongs(database);
657
Logger::instance()->log("batching up sync");
659
"Error querying for song to add",
661
"SELECT * FROM " + getLibraryTableName() + " WHERE " +
662
getLibSyncStatusColName() + "==" +
663
QString::number(getLibNeedsAddSyncStatus()) + " LIMIT 100;"),
666
QVariantList songsToAdd;
667
QSqlRecord currentRecord;
668
while(needAddSongs.next()){
669
currentRecord = needAddSongs.record();
670
QVariantMap songToAdd;
671
songToAdd["id"] = currentRecord.value(getLibIdColName());
672
QString title = currentRecord.value(getLibSongColName()).toString();
674
songToAdd["title"] = title;
675
QString artist = currentRecord.value(getLibArtistColName()).toString();
676
artist.truncate(199);
677
songToAdd["artist"] = artist;
678
QString album = currentRecord.value(getLibAlbumColName()).toString();
680
songToAdd["album"] = album;
681
songToAdd["duration"] = currentRecord.value(getLibDurationColName());
682
songToAdd["track"] = currentRecord.value(getLibTrackColName()).toInt();
683
QString genre = currentRecord.value(getLibGenreColName()).toString();
685
songToAdd["genre"] = genre;
686
songsToAdd.append(songToAdd);
689
QSqlQuery needDeleteSongs(database);
691
"Error querying for songs to delete",
692
needDeleteSongs.exec(
693
"SELECT * FROM " + getLibraryTableName() + " WHERE " +
694
getLibSyncStatusColName() + "==" +
695
QString::number(getLibNeedsDeleteSyncStatus()) + " LIMIT 100;"),
698
QVariantList songsToDelete;
699
while(needDeleteSongs.next()){
700
currentRecord = needDeleteSongs.record();
701
songsToDelete.append(currentRecord.value(getLibIdColName()));
704
Logger::instance()->log("Found " + QString::number(songsToDelete.size()) + " songs which need deleting");
705
Logger::instance()->log("Found " + QString::number(songsToAdd.size()) + " songs which need adding");
706
if(songsToDelete.size() > 0 || songsToAdd.size() > 0){
707
serverConnection->modLibContents(songsToAdd, songsToDelete);
711
void DataStore::setLibSongSynced(library_song_id_t song){
712
QSet<library_song_id_t> songSet;
713
songSet.insert(song);
714
setLibSongsSynced(songSet);
717
void DataStore::setLibSongsSynced(const QSet<library_song_id_t>& songs){
718
setLibSongsSyncStatus(songs, getLibIsSyncedStatus());
721
void DataStore::setLibSongsSyncStatus(
722
const QSet<library_song_id_t>& songs,
723
const lib_sync_status_t syncStatus)
725
Logger::instance()->log("Setting songs to synced");
726
bool isTransacting = database.transaction();
727
QSqlQuery syncQuery(database);
728
syncQuery.prepare("UPDATE " + getLibraryTableName() + " "
729
"SET " + getLibSyncStatusColName() + "=" +
730
QString::number(syncStatus) + " "
731
"WHERE " + getLibIdColName() + "= ?");
732
Q_FOREACH(library_song_id_t id, songs){
733
syncQuery.bindValue(0, QVariant::fromValue<library_song_id_t>(id));
735
"Error setting song sync status",
738
QSet<library_song_id_t> modId;
740
emit libSongsModified(modId);
746
if(hasUnsyncedSongs()){
747
Logger::instance()->log("more stuff to sync");
752
Logger::instance()->log("syncing done");
756
bool DataStore::hasUnsyncedSongs() const{
757
return getTotalUnsynced() != 0;
760
int DataStore::getTotalUnsynced() const{
761
QSqlQuery unsyncedQuery(database);
763
"Error querying for unsynced songs",
765
"SELECT COUNT(*) FROM " + getLibraryTableName() + " WHERE " +
766
getLibSyncStatusColName() + "!=" +
767
QString::number(getLibIsSyncedStatus()) + ";"),
769
if(unsyncedQuery.next()){
770
return unsyncedQuery.record().value(0).toInt();
778
void DataStore::clearActivePlaylist(){
779
QSqlQuery deleteActivePlayilstQuery(database);
781
"Error clearing active playlist table.",
782
deleteActivePlayilstQuery.exec(getClearActivePlaylistQuery()),
783
deleteActivePlayilstQuery)
786
void DataStore::addSong2ActivePlaylistFromQVariant(
787
const QVariantMap &songToAdd, int priority)
790
"INSERT INTO "+getActivePlaylistTableName()+
792
getActivePlaylistLibIdColName() + ","+
793
getDownVoteColName() + ","+
794
getUpVoteColName() + "," +
795
getPriorityColName() + "," +
796
getTimeAddedColName() +"," +
797
getAdderUsernameColName() +"," +
798
getAdderIdColName() + ")" +
799
" VALUES ( :libid , :down , :up, :pri , :time , :username, :adder );",
802
addQuery.bindValue(":libid", songToAdd["song"].toMap()["id"]);
803
addQuery.bindValue(":down", songToAdd["downvoters"].toList().size());
804
addQuery.bindValue(":up", songToAdd["upvoters"].toList().size());
805
addQuery.bindValue(":pri", priority);
806
addQuery.bindValue(":time", songToAdd["time_added"]);
807
addQuery.bindValue(":username", songToAdd["adder"].toMap()["username"]);
808
addQuery.bindValue(":adder", songToAdd["adder"].toMap()["id"]);
812
"Failed to add song library" << songToAdd["song"].toString().toStdString(),
818
void DataStore::setActivePlaylist(const QVariantMap& newPlaylist){
820
int retrievedVolume = newPlaylist["volume"].toInt();
821
if(retrievedVolume != (int)(getPlayerVolume()*10)){
822
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
823
settings.setValue(getPlayerVolumeSettingName(), retrievedVolume/10.0);
824
emit volumeChanged(retrievedVolume/10.0);
827
onPlayerStateChanged(newPlaylist["state"].toString());
829
library_song_id_t retrievedCurrentId =
830
newPlaylist["current_song"].toMap()["song"].toMap()["id"].value<library_song_id_t>();
831
if(retrievedCurrentId != currentSongId){
832
QSqlQuery getSongQuery(
833
"SELECT " + getLibFileColName() + ", " +
834
getLibSongColName() + ", " +
835
getLibArtistColName() + " FROM " +
836
getActivePlaylistViewName() + " WHERE " +
837
getActivePlaylistLibIdColName() + " = " + QString::number(retrievedCurrentId) + ";",
840
"Getting song for manual playlist set failed.",
844
if(getSongQuery.isValid()){
845
Logger::instance()->log("Got file, for manual song set");
846
QString filePath = getSongQuery.value(0).toString();
847
currentSongId = retrievedCurrentId;
848
song_info_t toEmit = {
849
Phonon::MediaSource(filePath),
850
getSongQuery.value(1).toString(),
851
getSongQuery.value(2).toString()
853
emit manualSongChange(toEmit);
856
clearActivePlaylist();
857
QVariantList newSongs = newPlaylist["active_playlist"].toList();
858
for(int i=0; i<newSongs.size(); ++i){
859
addSong2ActivePlaylistFromQVariant(newSongs[i].toMap(), i);
861
emit activePlaylistModified();
865
void DataStore::onGetActivePlaylistFail(
866
const QString& errMessage,
868
const QList<QNetworkReply::RawHeaderPair>& headers)
870
Logger::instance()->log("Playlist error: " + QString::number(errorCode) + " " + errMessage);
871
if(isTicketAuthError(errorCode, headers)){
872
Logger::instance()->log("Got the ticket-hash challenge");
873
reauthActions.insert(GET_ACTIVE_PLAYLIST);
876
//TODO handle other possible errors?
879
void DataStore::onActivePlaylistModified(
880
const QSet<library_song_id_t>& added,
881
const QSet<library_song_id_t>& removed)
883
playlistIdsToAdd.subtract(added);
884
playlistIdsToRemove.subtract(removed);
885
refreshActivePlaylist();
888
void DataStore::onActivePlaylistModFailed(
889
const QString& /*errMessage*/,
891
const QList<QNetworkReply::RawHeaderPair>& headers)
893
Logger::instance()->log("Active playlist mod failed with code " + QString::number(errorCode));
894
if(isTicketAuthError(errorCode, headers)){
895
Logger::instance()->log("Got the ticket-hash challenge");
896
reauthActions.insert(MOD_PLAYLIST);
899
//TODO do stuff on failure
902
void DataStore::refreshActivePlaylist(){
903
serverConnection->getActivePlaylist();
907
void DataStore::onPlayerCreate(const player_id_t& issuedId){
908
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
909
settings.setValue(getPlayerIdSettingName(), QVariant::fromValue(issuedId));
910
serverConnection->setPlayerId(issuedId);
911
setPlayerState(getPlayingState());
912
emit playerCreated();
915
void DataStore::onPlayerCreationFailed(const QString& errMessage, int /*errorCode*/,
916
const QList<QNetworkReply::RawHeaderPair>& /*headers*/)
918
//TODO do other stuff as well. like do reauth
919
emit playerCreationFailed(errMessage);
923
void DataStore::onPlayerStateChanged(const QString& newState){
924
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
925
if(newState != settings.value(getPlayerStateSettingName())){
926
settings.setValue(getPlayerStateSettingName(), newState);
927
emit playerStateChanged(newState);
930
//If this player state change is the result of starting up the player for the first time
931
//we need to do a few things
932
if(!activePlaylistRefreshTimer->isActive()){
933
refreshActivePlaylist();
934
activePlaylistRefreshTimer->start();
939
void DataStore::onLibModError(
940
const QString& errMessage, int errorCode, const QList<QNetworkReply::RawHeaderPair>& headers)
942
Logger::instance()->log("Got bad libmod " + QString::number(errorCode));
943
if(isTicketAuthError(errorCode, headers)){
944
Logger::instance()->log("Got the ticket-hash challenge");
945
reauthActions.insert(SYNC_LIB);
949
Logger::instance()->log("Bad lib mod message " + errMessage);
950
emit libModError(errMessage);
954
void DataStore::onSetCurrentSongFailed(
955
const QString& errMessage, int errorCode, const QList<QNetworkReply::RawHeaderPair>& headers)
957
Logger::instance()->log("Setting current song failed: " + QString::number(errorCode) + " " + errMessage);
958
if(isTicketAuthError(errorCode, headers)){
959
Logger::instance()->log("Got the ticket-hash challenge");
960
reauthActions.insert(SET_CURRENT_SONG);
965
void DataStore::onSetVolumeFailed(
966
const QString& errMessage, int errorCode, const QList<QNetworkReply::RawHeaderPair>& headers)
968
Logger::instance()->log("Setting volume failed " +
969
QString::number(errorCode) + " " + errMessage);
970
if(isTicketAuthError(errorCode, headers)){
971
Logger::instance()->log("Got the ticket-hash challenge");
972
reauthActions.insert(SET_CURRENT_VOLUME);
981
void DataStore::onReauth(const QByteArray& ticketHash, const user_id_t& userId){
982
Logger::instance()->log("in on reauth");
984
serverConnection->setTicket(ticketHash);
985
serverConnection->setUserId(userId);
987
Q_FOREACH(ReauthAction r, reauthActions){
991
reauthActions.clear();
994
void DataStore::doReauthAction(const ReauthAction& action){
999
case GET_ACTIVE_PLAYLIST:
1000
refreshActivePlaylist();
1002
case SET_CURRENT_SONG:
1003
if(currentSongId != -1){
1004
serverConnection->setCurrentSong(currentSongId);
1008
serverConnection->modActivePlaylist(playlistIdsToAdd, playlistIdsToRemove);
1010
case SET_CURRENT_VOLUME:
1011
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
1012
serverConnection->setVolume((int)(getPlayerVolume() * 10));
1017
void DataStore::onAuthFail(const QString& /*errMessage*/){
1019
Logger::instance()->log("BAD STUFF, BAD AUTH CREDS, BAD REAUTH");
1020
//TODO need to do something here
1023
void DataStore::initReauth(){
1026
serverConnection->authenticate(getUsername(), getPassword());
1030
QByteArray DataStore::getHeaderValue(
1031
const QByteArray& headerName,
1032
const QList<QNetworkReply::RawHeaderPair>& headers)
1034
//Yes yes, I know this is an O(n) search. But it's fine.
1035
//This list of headers shouldn't be that long.
1036
Q_FOREACH(const QNetworkReply::RawHeaderPair& pair, headers){
1037
if(headerName == pair.first){
1045
bool DataStore::getDontShowPlaybackErrorSetting(){
1046
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
1047
return settings.value(getDontShowPlaybackErrorSettingName(), false ).toBool();
1050
void DataStore::setDontShowPlaybackError(bool checked){
1051
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
1052
settings.setValue(getDontShowPlaybackErrorSettingName(), checked);
1056
void DataStore::saveCredentials(
1057
const QString& username, const QString& password)
1059
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
1060
SimpleCrypt crypt = Utils::getCryptoObject();
1061
QString cryptUsername = crypt.encryptToString(username);
1062
QString cryptPassword = crypt.encryptToString(password);
1063
settings.setValue(getHasValidCredsSettingName(), true);
1064
settings.setValue(getUsernameSettingName(), cryptUsername);
1065
settings.setValue(getPasswordSettingName(), cryptPassword);
1068
void DataStore::setCredentialsDirty(){
1069
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
1070
settings.setValue(getHasValidCredsSettingName(), false);
1073
bool DataStore::hasValidSavedCredentials(){
1074
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
1075
return settings.value(getHasValidCredsSettingName()).toBool();
1078
void DataStore::getSavedCredentials(QString* username, QString* password){
1079
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
1080
SimpleCrypt crypt = Utils::getCryptoObject();
1081
QString encryptedUsername = settings.value(getUsernameSettingName()).toString();
1082
QString encryptedPassword = settings.value(getPasswordSettingName()).toString();
1083
*username = crypt.decryptToString(encryptedUsername);
1084
*password = crypt.decryptToString(encryptedPassword);
1087
void DataStore::clearSavedCredentials(){
1088
QSettings settings(QSettings::UserScope, getSettingsOrg(), getSettingsApp());
1089
settings.setValue(getHasValidCredsSettingName(), false);
1090
settings.setValue(getUsernameSettingName(), "");
1091
settings.setValue(getPasswordSettingName(), "");