/* Fetch string. Beware! This overwrites your waith->data pointer * @param waitress handle * @param result buffer, malloced (don't forget to free it yourself) */ WaitressReturn_t WaitressFetchBuf (WaitressHandle_t *waith, char **buf) { WaitressFetchBufCbBuffer_t buffer; WaitressReturn_t wRet; memset (&buffer, 0, sizeof (buffer)); waith->data = &buffer; waith->callback = WaitressFetchBufCb; wRet = WaitressFetchCall (waith); *buf = buffer.buf; return wRet; }
void *BarPlayerMacOSXThread(void *data){ struct audioPlayer *player = data; char extraHeaders[25]; void *ret = PLAYER_RET_OK; WaitressReturn_t wRet = WAITRESS_RET_ERR; /* init handles */ player->waith.data = (void *) player; /* extraHeaders will be initialized later */ player->waith.extraHeaders = extraHeaders; player->songPlayed = 0; switch (player->audioFormat) { case PIANO_AF_AACPLUS: { OSStatus err = AudioFileStreamOpen(player, StreamPropertyListenerProc, StreamPacketsProc, kAudioFileAAC_ADTSType, &player->audioFileStream); if (err) PRINTERROR ("Error opening stream!\n"); player->waith.callback = BarPlayerAACCb; } break; case PIANO_AF_MP3: case PIANO_AF_MP3_HI: { OSStatus err = AudioFileStreamOpen(player, StreamPropertyListenerProc, StreamPacketsProc, kAudioFileMP3Type, &player->audioFileStream); if (err) PRINTERROR ("Error opening stream!\n"); player->waith.callback = BarPlayerAACCb; } break; default: PRINTERROR ("Unsupported audio format!\n"); return PLAYER_RET_OK; break; } player->mode = PLAYER_INITIALIZED; /* This loop should work around song abortions by requesting the * missing part of the song */ do { snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n", player->bytesReceived); wRet = WaitressFetchCall (&player->waith); } while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT || wRet == WAITRESS_RET_READ_ERR); switch (player->audioFormat) { case PIANO_AF_AACPLUS: case PIANO_AF_MP3: case PIANO_AF_MP3_HI: AudioQueueStop(player->audioQueue, false); AudioFileStreamClose(player->streamID); AudioQueueDispose(player->audioQueue, false); break; default: /* this should never happen: thread is aborted above */ break; } WaitressFree (&player->waith); pthread_mutex_lock(&player->mutex); player->mode = PLAYER_FINISHED_PLAYBACK; pthread_cond_broadcast(&player->cond); pthread_mutex_unlock(&player->mutex); return ret; }
/* player thread; for every song a new thread is started * @param audioPlayer structure * @return PLAYER_RET_* */ void *BarPlayerThread (void *data) { struct audioPlayer *player = data; char extraHeaders[32]; void *ret = PLAYER_RET_OK; #ifdef ENABLE_FAAD NeAACDecConfigurationPtr conf; #endif WaitressReturn_t wRet = WAITRESS_RET_ERR; /* init handles */ player->waith.data = (void *) player; /* extraHeaders will be initialized later */ player->waith.extraHeaders = extraHeaders; player->buffer = malloc (BAR_PLAYER_BUFSIZE); switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: player->aacHandle = NeAACDecOpen(); /* set aac conf */ conf = NeAACDecGetCurrentConfiguration(player->aacHandle); conf->outputFormat = FAAD_FMT_16BIT; conf->downMatrix = 1; NeAACDecSetConfiguration(player->aacHandle, conf); player->waith.callback = BarPlayerAACCb; break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: mad_stream_init (&player->mp3Stream); mad_frame_init (&player->mp3Frame); mad_synth_init (&player->mp3Synth); player->waith.callback = BarPlayerMp3Cb; break; #endif /* ENABLE_MAD */ default: /* FIXME: leaks memory */ BarUiMsg (player->settings, MSG_ERR, "Unsupported audio format!\n"); return PLAYER_RET_OK; break; } player->mode = PLAYER_INITIALIZED; /* This loop should work around song abortions by requesting the * missing part of the song */ do { snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n", player->bytesReceived); wRet = WaitressFetchCall (&player->waith); } while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT || wRet == WAITRESS_RET_READ_ERR); /* If the song was played all the way through tag it. */ if (wRet == WAITRESS_RET_OK) { BarFlyTag(&player->fly, player->settings); } switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: NeAACDecClose(player->aacHandle); free (player->sampleSize); break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: mad_synth_finish (&player->mp3Synth); mad_frame_finish (&player->mp3Frame); mad_stream_finish (&player->mp3Stream); break; #endif /* ENABLE_MAD */ default: /* this should never happen: thread is aborted above */ break; } if (player->aoError) { ret = (void *) PLAYER_RET_ERR; } ao_close(player->audioOutDevice); WaitressFree (&player->waith); free (player->buffer); player->mode = PLAYER_FINISHED_PLAYBACK; return ret; }
/* player thread; for every song a new thread is started * @param aacPlayer structure * @return NULL NULL NULL ... */ void *BarPlayerThread (void *data) { struct audioPlayer *player = data; char extraHeaders[25]; void *ret = PLAYER_RET_OK; #ifdef ENABLE_FAAD NeAACDecConfigurationPtr conf; #endif WaitressReturn_t wRet = WAITRESS_RET_ERR; /* init handles */ pthread_mutex_init (&player->pauseMutex, NULL); player->scale = computeReplayGainScale (player->gain); player->waith.data = (void *) player; /* extraHeaders will be initialized later */ player->waith.extraHeaders = extraHeaders; switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: player->aacHandle = NeAACDecOpen(); /* set aac conf */ conf = NeAACDecGetCurrentConfiguration(player->aacHandle); conf->outputFormat = FAAD_FMT_16BIT; conf->downMatrix = 1; NeAACDecSetConfiguration(player->aacHandle, conf); player->waith.callback = BarPlayerAACCb; break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: case PIANO_AF_MP3_HI: mad_stream_init (&player->mp3Stream); mad_frame_init (&player->mp3Frame); mad_synth_init (&player->mp3Synth); player->waith.callback = BarPlayerMp3Cb; break; #endif /* ENABLE_MAD */ default: printf("Unsupported audio format!\n"); return PLAYER_RET_OK; break; } player->mode = PLAYER_INITIALIZED; /* This loop should work around song abortions by requesting the * missing part of the song */ do { snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n", player->bytesReceived); wRet = WaitressFetchCall (&player->waith); } while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT || wRet == WAITRESS_RET_READ_ERR); switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: NeAACDecClose(player->aacHandle); break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: case PIANO_AF_MP3_HI: mad_synth_finish (&player->mp3Synth); mad_frame_finish (&player->mp3Frame); mad_stream_finish (&player->mp3Stream); break; #endif /* ENABLE_MAD */ default: /* this should never happen: thread is aborted above */ break; } if (player->aoError) { ret = (void *) PLAYER_RET_ERR; } if (player->audioOutDevice) ao_close(player->audioOutDevice); WaitressFree (&player->waith); #ifdef ENABLE_FAAD if (player->sampleSize != NULL) { free (player->sampleSize); } #endif /* ENABLE_FAAD */ pthread_mutex_destroy (&player->pauseMutex); player->mode = PLAYER_FINISHED_PLAYBACK; return ret; }
/* player thread; for every song a new thread is started * @param audioPlayer structure * @return PLAYER_RET_* */ void *BarPlayerThread (void *data) { struct audioPlayer *player = data; char extraHeaders[32]; void *ret = PLAYER_RET_OK; #ifdef ENABLE_FAAD NeAACDecConfigurationPtr conf; #endif WaitressReturn_t wRet = WAITRESS_RET_ERR; /* init handles */ pthread_mutex_init (&player->pauseMutex, NULL); player->waith.data = (void *) player; /* extraHeaders will be initialized later */ player->waith.extraHeaders = extraHeaders; player->buffer = malloc (BAR_PLAYER_BUFSIZE); switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: player->aacHandle = NeAACDecOpen(); /* set aac conf */ conf = NeAACDecGetCurrentConfiguration(player->aacHandle); conf->outputFormat = FAAD_FMT_16BIT; conf->downMatrix = 1; NeAACDecSetConfiguration(player->aacHandle, conf); player->waith.callback = BarPlayerAACCb; break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: mad_stream_init (&player->mp3Stream); mad_frame_init (&player->mp3Frame); mad_synth_init (&player->mp3Synth); player->waith.callback = BarPlayerMp3Cb; break; #endif /* ENABLE_MAD */ default: BarUiMsg (player->settings, MSG_ERR, "Unsupported audio format!\n"); ret = (void *) PLAYER_RET_HARDFAIL; goto cleanup; break; } player->mode = PLAYER_INITIALIZED; /* This loop should work around song abortions by requesting the * missing part of the song */ do { snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n", player->bytesReceived); wRet = WaitressFetchCall (&player->waith); } while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT || wRet == WAITRESS_RET_READ_ERR); switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: NeAACDecClose(player->aacHandle); free (player->sampleSize); break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: mad_synth_finish (&player->mp3Synth); mad_frame_finish (&player->mp3Frame); mad_stream_finish (&player->mp3Stream); break; #endif /* ENABLE_MAD */ default: /* this should never happen */ assert (0); break; } if (player->aoError) { ret = (void *) PLAYER_RET_HARDFAIL; } /* Pandora sends broken audio url’s sometimes (“bad request”). ignore them. */ if (wRet != WAITRESS_RET_OK && wRet != WAITRESS_RET_CB_ABORT) { BarUiMsg (player->settings, MSG_ERR, "Cannot access audio file: %s\n", WaitressErrorToStr (wRet)); ret = (void *) PLAYER_RET_SOFTFAIL; } cleanup: ao_close (player->audioOutDevice); WaitressFree (&player->waith); free (player->buffer); player->mode = PLAYER_FINISHED_PLAYBACK; return ret; }