diff -d -c -r last.fm-1.4.1.57486-old/src/AudioController.cpp last.fm-1.4.1.57486/src/AudioController.cpp *** last.fm-1.4.1.57486-old/src/AudioController.cpp Tue Dec 25 15:14:58 2007 --- last.fm-1.4.1.57486/src/AudioController.cpp Tue Dec 25 15:21:09 2007 *************** *** 66,71 **** --- 66,149 ---- // Max number of errors in a row before we abort static const int k_streamerErrorLimit = 5; + + + + + + // ID3V1 tag format + // HINT: this are fixed widths, which are directly read out of the file + struct id3v1_t { + char name[30]; + char interpreter[30]; + char album[30]; + char year[4]; + char comment[30]; + char genre; + }; + + // call it at the end of the writing-process + void fwriteMp3Tags(const id3v1_t& tags, FILE* f) { + fwrite("TAG", 3, 1, f); + fwrite(&tags, sizeof(id3v1_t), 1, f); + } + + + Ripper* Ripper::singleton = NULL; + + int Ripper::onNewEvent( const QString& msg ) { + QString script = MooseUtils::savePath( "onNewEvent" ); + QString cmd = "\"" + script + "\" " + msg; + printf("executing: %s\n", cmd.toUtf8().constData()); + return system(cmd.toUtf8().constData()); + } + + void Ripper::onTrackStarted( const TrackInfo& track ) { + curTrack = &track; + printf("onTrackStarted: %s - %s\n", + track.artist().toUtf8().constData(), track.track().toUtf8().constData()); + onNewEvent("newtrack: \"" + track.artist() + "\" - \"" + track.track() + "\""); + } + + void Ripper::onTrackEndReached( int atPosition ) { + if(!curTrack) return; + + QString filename = MooseUtils::savePath( curTrack->artist() + " - " + curTrack->track() + ".mp3" ); + printf("onTrackEndReached: %s - %s\n", + curTrack->artist().toUtf8().constData(), curTrack->track().toUtf8().constData()); + + if(onNewEvent("endtrack: \"" + curTrack->artist() + "\" - \"" + curTrack->track() + "\"") == 0) { + printf(" saving %s\n", filename.toUtf8().constData()); + + id3v1_t tags; + strncpy(tags.name, curTrack->track().toAscii().constData(), 30); + strncpy(tags.interpreter, curTrack->artist().toAscii().constData(), 30); + strncpy(tags.album, curTrack->album().toAscii().constData(), 30); + strncpy(tags.year, "", 4); + strncpy(tags.comment, "", 30); + tags.genre = 255; + + FILE* f = fopen(filename.toUtf8().constData(), "wb"); + fwrite(buffer.constData(), buffer.length(), 1, f); + fwriteMp3Tags(tags, f); + fclose(f); + } else + printf(" not saving\n"); + + finishCurrent(); + } + + void Ripper::processData( const QByteArray &data ) { + buffer.append(data); + } + + void Ripper::ignoreCurrent() { + finishCurrent(); + printf("ignore current track\n"); + } + + + AudioControllerThread::AudioControllerThread( QObject* parent ) : QThread( parent ), m_input( 0 ), *************** *** 350,355 **** --- 428,434 ---- m_proxyOutput->processData( data ); bool fine = m_transcode->processData( data ); + if(fine && Ripper::singleton) Ripper::singleton->processData( data ); if ( !fine ) { *************** *** 749,757 **** --- 828,838 ---- } + void AudioController::onTrackStarted() { + ripper.onTrackStarted( m_currentTrack ); emit trackStarted( m_currentTrack ); } *************** *** 760,766 **** AudioController::onTrackEndReached( int atPosition ) { LOGL( 4, "AudioController::onTrackEndReached" ); ! emit trackEnded( m_currentTrack, atPosition ); } --- 841,848 ---- AudioController::onTrackEndReached( int atPosition ) { LOGL( 4, "AudioController::onTrackEndReached" ); ! ! ripper.onTrackEndReached( atPosition ); emit trackEnded( m_currentTrack, atPosition ); } *************** *** 768,773 **** --- 850,858 ---- void AudioController::onThreadStateChanged( RadioState newState ) { + if( m_state == State_Stopping || m_state == State_Skipping ) + ripper.ignoreCurrent(); + switch ( m_state ) { // When we're in Skipping or Stopping, all we're interested in is diff -d -c -r last.fm-1.4.1.57486-old/src/AudioController.h last.fm-1.4.1.57486/src/AudioController.h *** last.fm-1.4.1.57486-old/src/AudioController.h Tue Dec 25 15:14:58 2007 --- last.fm-1.4.1.57486/src/AudioController.h Tue Dec 25 15:16:26 2007 *************** *** 253,258 **** --- 253,280 ---- }; + + class Ripper { + protected: + const TrackInfo* curTrack; + QByteArray buffer; + + void finishCurrent() { curTrack = NULL; buffer.clear(); } + int onNewEvent( const QString& msg ); + + public: + static Ripper* singleton; + Ripper() : curTrack(NULL) { singleton = this; } + ~Ripper() { singleton = NULL; } + + void onTrackStarted( const TrackInfo& track ); + void onTrackEndReached( int atPosition ); + void processData( const QByteArray &data ); + void ignoreCurrent(); + }; + + + /*************************************************************************/ /** The AudioController manages playback of audio, it can take individual tracks or a playlist and manage the changing of tracks automatically. *************** *** 376,382 **** QStringList m_devices; QMutex m_mutex; ! private slots: void onTrackStarted(); --- 398,406 ---- QStringList m_devices; QMutex m_mutex; ! ! Ripper ripper; ! private slots: void onTrackStarted();