Index: include/musikLibrary.h =================================================================== --- include/musikLibrary.h (revision 17) +++ include/musikLibrary.h (working copy) @@ -39,6 +39,10 @@ /////////////////////////////////////////////////// +#define MUSIK_PREV_SONG 2 + +/////////////////////////////////////////////////// + namespace musikCore { /////////////////////////////////////////////////// @@ -1031,6 +1035,14 @@ */ static int Rand( int min, int max ); + /** + * Get the last played song + * + * \param index current song + * \return previous index + */ + static int GetLastSong( int songid, Library *lib ); + int QuerySongs( const String & query, Playlist & target ); int RawQuerySongs( const String & query, Playlist & target ); int RawQueryStringArray( const String& query, StringArray& target, bool clear = true ); Index: include/musikLibraryCallbacks.h =================================================================== --- include/musikLibraryCallbacks.h (revision 17) +++ include/musikLibraryCallbacks.h (working copy) @@ -150,6 +150,35 @@ p->SetYear ( results[8] ); p->SetRating ( results[9] ); p->SetBitrate ( results[10] ); + //p->SetLastPlayed ( results[11] ); + p->SetNotes ( utf8to16( results[12] ) ); + p->SetTimesPlayed ( results[13] ); + p->SetTimeAdded ( results[14] ); + p->SetFilesize ( results[15] ); + p->SetFilename ( utf8to16( results[16] ) ); + p->SetEqualizer ( results[17] ); + p->SetDirtyFlag ( results[18] ); + + return 0; +} + +/////////////////////////////////////////////////// + +static int sqlite_GetSongInfoFromIDUpdate( void *args, int numCols, char **results, char ** columnNames ) +{ + SongInfo* p = (SongInfo*)args; + + p->SetTrackNum ( results[0] ); + p->SetArtist ( utf8to16( results[1] ) ); + p->SetAlbum ( utf8to16( results[2] ) ); + p->SetGenre ( utf8to16( results[3] ) ); + p->SetTitle ( utf8to16( results[4] ) ); + p->SetDuration ( results[5] ); + p->SetFormat ( results[6] ); + p->SetVBR ( results[7] ); + p->SetYear ( results[8] ); + p->SetRating ( results[9] ); + p->SetBitrate ( results[10] ); p->SetLastPlayed ( results[11] ); p->SetNotes ( utf8to16( results[12] ) ); p->SetTimesPlayed ( results[13] ); Index: include/musikPlayer.h =================================================================== --- include/musikPlayer.h (revision 17) +++ include/musikPlayer.h (working copy) @@ -708,6 +708,11 @@ bool t_Exit; OpenThreads::Mutex m_ThreadMutex; + +public: + bool g_isNext; + bool g_isPrev; + }; /////////////////////////////////////////////////// Index: src/musikLibrary.cpp =================================================================== --- src/musikLibrary.cpp (revision 17) +++ src/musikLibrary.cpp (working copy) @@ -2917,6 +2917,8 @@ info.SetID( id ); + Player *player = GetPlayer(); + // do it int nRet; m_ProtectingLibrary.lock(); @@ -2932,10 +2934,13 @@ SONG_TABLE_NAME, id ); + int (*callback)( void*, int, char**, char** ); + callback = ( player->g_isNext ? &sqlite_GetSongInfoFromIDUpdate : &sqlite_GetSongInfoFromID ); + nRet = sqlite3_exec( m_pDB, utf16to8( query ).c_str(), - &sqlite_GetSongInfoFromID, + callback, &info, NULL ); } @@ -2987,8 +2992,27 @@ StringToInt( info.GetYear() ), q_str( info.GetGenre() ).c_str() ); - query.Format( + //_T( " rating = %d, bitrate = %d, lastplayed = '%ls', notes = '%ls', timesplayed = %d, duration = %d, timeadded = '%ls', filesize = %d, dirty = %d" ) + + //if(g_isNext){ + query.Format( _T( "%ls " ) + _T( " rating = %d, bitrate = %d, notes = '%ls', timesplayed = %d, duration = %d, timeadded = '%ls', filesize = %d, dirty = %d" ) + _T( " WHERE songid = %d; " ), + query.c_str(), + StringToInt( info.GetRating() ), + StringToInt( info.GetBitrate() ), + //info.GetLastPlayed().c_str(), + q_str( info.GetNotes() ).c_str(), + StringToInt( info.GetTimesPlayed() ), + StringToInt( info.GetDuration() ), + info.GetTimeAdded().c_str(), + StringToInt( info.GetFilesize() ), + StringToInt( info.GetDirtyFlag() ), + songid ); + /*}else{ + query.Format( + _T( "%ls " ) _T( " rating = %d, bitrate = %d, lastplayed = '%ls', notes = '%ls', timesplayed = %d, duration = %d, timeadded = '%ls', filesize = %d, dirty = %d" ) _T( " WHERE songid = %d; " ), query.c_str(), @@ -3002,6 +3026,7 @@ StringToInt( info.GetFilesize() ), StringToInt( info.GetDirtyFlag() ), songid ); + }*/ result = sqlite3_exec( m_pDB, @@ -5032,6 +5057,65 @@ /////////////////////////////////////////////////// +int Library::GetLastSong( int songid, Library *lib ) +{ + String query; + query.Format( + _T( " SELECT DISTINCT julianday( lastplayed ) " ) + _T( " FROM %ls " ) + _T( " WHERE lastplayed > 0 " ) + _T( " AND songid = %d " ) + _T( " LIMIT 1 " ), + SONG_TABLE_NAME, + songid); + + String lastplayed; + sqlite3_exec( + lib->m_pDB, + utf16to8( query ).c_str(), + &sqlite_GetStringFromRow, + &lastplayed, + NULL); + + query.clear(); + query.Format( + _T( " SELECT DISTINCT songid " ) + _T( " FROM %ls " ) + _T( " WHERE julianday( lastplayed ) < %ls " ) + _T( " AND julianday( lastplayed ) > 0 " ) + _T( " ORDER BY julianday( lastplayed ) DESC " ) + _T( " LIMIT 1 " ), + SONG_TABLE_NAME, + lastplayed.c_str()); + + int newid; + sqlite3_exec( + lib->m_pDB, + utf16to8( query ).c_str(), + &sqlite_GetIntFromRow, + &newid, + NULL); + + query.clear(); + query.Format( + _T( " UPDATE %ls " ) + _T( " SET lastplayed=0 " ) + _T( " WHERE lastplayed > %ls " ), + SONG_TABLE_NAME, + lastplayed.c_str()); + + sqlite3_exec( + lib->m_pDB, + utf16to8( query ).c_str(), + NULL, + NULL, + NULL); + + return newid; +} + +/////////////////////////////////////////////////// + const String Library::GetRandom( int field, size_t count ) { StringArray target; Index: src/musikPlayer.cpp =================================================================== --- src/musikPlayer.cpp (revision 17) +++ src/musikPlayer.cpp (working copy) @@ -78,6 +78,9 @@ m_State = MUSIK_PLAYER_INIT_UNINITIALIZED; InitEQSettings(); + + g_isNext = false; + g_isPrev = false; } /////////////////////////////////////////////////// @@ -800,7 +803,8 @@ { if ( begin ) { - m_CurrSong.GetLibrary()->UpdateTimesPlayed( m_CurrSong ); + if( g_isNext || !g_isPrev ) + m_CurrSong.GetLibrary()->UpdateTimesPlayed( m_CurrSong ); } else { @@ -817,6 +821,8 @@ if ( !m_Playlist || !IsPlaying() ) return false; + g_isNext = true; + // if repeat single is enabled, and the // stream naturally expired (a "next" button // was not clicked, for example), we want to @@ -892,6 +898,8 @@ } else PlayCD( m_Index ); + + g_isNext = false; return true; } @@ -903,11 +911,31 @@ if ( !m_Playlist || !IsPlaying() ) return false; + g_isPrev = true; + // if the song is under 6000 ms, we want to go // to the previous track if ( GetTimeNow( MUSIK_TIME_MSECS ) < 6000 || !IsPlaying() ) { - m_Index--; + // Intelligent Previous implimentation + // -ObsidianX + if ( m_Playmode & MUSIK_PLAYER_PLAYMODE_RANDOM ) + { + Library *g_Library = GetLibrary(); + int playingID = GetPlaying()->GetID(); + int lastsong = g_Library->GetLastSong( playingID, g_Library ); + int index; + for( size_t i = 0; i < m_Playlist->GetCount(); i++ ) + { + if( m_Playlist->GetSongID( i ) == lastsong ) + { + index = i; + } + } + m_Index = index; + } + else + m_Index--; if ( m_Index < 0 ) { @@ -942,6 +970,8 @@ else PlayCD( m_Index ); + g_isPrev = false; + return true; }