/src/libtomahawk/database/DatabaseCommand_LogPlayback.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 134 lines · 85 code · 28 blank · 21 comment · 23 complexity · 8b2c71aacf920e2892c79b7f0115a2a1 MD5 · raw file

  1. /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2. *
  3. * Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  4. * Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
  5. *
  6. * Tomahawk 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 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Tomahawk 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.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "DatabaseCommand_LogPlayback.h"
  20. #include "collection/Collection.h"
  21. #include "database/Database.h"
  22. #include "network/Servent.h"
  23. #include "utils/Logger.h"
  24. #include "DatabaseImpl.h"
  25. #include "PlaylistEntry.h"
  26. #include <QDateTime>
  27. #include <QSqlQuery>
  28. #define STARTED_THRESHOLD 600 // Don't advertise tracks older than X seconds as currently playing
  29. #define FINISHED_THRESHOLD 10 // Don't store tracks played less than X seconds in the playback log
  30. #define SUBMISSION_THRESHOLD 20 // Don't broadcast playback logs when a track was played less than X seconds
  31. using namespace Tomahawk;
  32. void
  33. DatabaseCommand_LogPlayback::postCommitHook()
  34. {
  35. connect( this, SIGNAL( trackPlaying( Tomahawk::track_ptr, unsigned int ) ),
  36. source().data(), SLOT( onPlaybackStarted( Tomahawk::track_ptr, unsigned int ) ), Qt::QueuedConnection );
  37. connect( this, SIGNAL( trackPlayed( Tomahawk::track_ptr, Tomahawk::PlaybackLog ) ),
  38. source().data(), SLOT( onPlaybackFinished( Tomahawk::track_ptr, Tomahawk::PlaybackLog ) ), Qt::QueuedConnection );
  39. track_ptr track = Track::get( m_artist, m_track, QString() );
  40. if ( !track )
  41. return;
  42. if ( m_action == Finished )
  43. {
  44. PlaybackLog log;
  45. log.source = source();
  46. log.timestamp = m_playtime;
  47. log.secsPlayed = m_secsPlayed;
  48. emit trackPlayed( track, log );
  49. }
  50. // if the play time is more than 10 minutes in the past, ignore
  51. else if ( m_action == Started && QDateTime::fromTime_t( playtime() ).secsTo( QDateTime::currentDateTime() ) < STARTED_THRESHOLD )
  52. {
  53. emit trackPlaying( track, m_trackDuration );
  54. }
  55. if ( source()->isLocal() )
  56. {
  57. Servent::instance()->triggerDBSync();
  58. }
  59. }
  60. void
  61. DatabaseCommand_LogPlayback::exec( DatabaseImpl* dbi )
  62. {
  63. Q_ASSERT( !source().isNull() );
  64. unsigned int pt = m_playtime;
  65. if ( m_playtime == 0 )
  66. m_playtime = QDateTime::currentDateTimeUtc().toTime_t();
  67. if ( m_action != Finished )
  68. return;
  69. if ( m_secsPlayed < FINISHED_THRESHOLD && m_trackDuration > 0 )
  70. return;
  71. if ( m_artist.isEmpty() || m_track.isEmpty() )
  72. return;
  73. QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
  74. TomahawkSqlQuery query = dbi->newquery();
  75. if ( pt > 0 && source()->isLocal() )
  76. {
  77. query.prepare( QString( "SELECT * FROM playback_log WHERE source %1 AND playtime = %2" ).arg( srcid.isNull() ? "IS NULL" : srcid.toString() ).arg( m_playtime ) );
  78. query.exec();
  79. if ( query.next() )
  80. {
  81. tDebug() << "Ignoring dupe playback log for source" << srcid << "with timestamp" << m_playtime;
  82. return;
  83. }
  84. }
  85. // tDebug() << "Logging playback of" << m_artist << "-" << m_track << "for source" << srcid << "- timestamp:" << m_playtime;
  86. query.prepare( "INSERT INTO playback_log(source, track, playtime, secs_played) VALUES (?, ?, ?, ?)" );
  87. query.bindValue( 0, srcid );
  88. // If there's no artist, because it's a resolver result with bad metadata for example, don't save it
  89. int artid = dbi->artistId( m_artist, true );
  90. if( artid < 1 )
  91. return;
  92. int trkid = dbi->trackId( artid, m_track, true );
  93. if( trkid < 1 )
  94. return;
  95. query.bindValue( 1, trkid );
  96. query.bindValue( 2, m_playtime );
  97. query.bindValue( 3, m_secsPlayed );
  98. query.exec();
  99. }
  100. bool
  101. DatabaseCommand_LogPlayback::localOnly() const
  102. {
  103. if ( m_action == Finished )
  104. return m_secsPlayed < SUBMISSION_THRESHOLD;
  105. return false;
  106. }