diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.c | 31 | ||||
| -rw-r--r-- | src/player.c | 64 | ||||
| -rw-r--r-- | src/player.h | 10 | 
3 files changed, 79 insertions, 26 deletions
| @@ -45,11 +45,6 @@ THE SOFTWARE.  #include "config.h"  #include "ui.h" -inline float BarSamplesToSeconds (float samplerate, float channels, -		float samples) { -	return channels * 1000.0 * samples / samplerate; -} -  int main (int argc, char **argv) {  	PianoHandle_t ph;  	static struct audioPlayer player; @@ -128,13 +123,11 @@ int main (int argc, char **argv) {  	while (!doQuit) {  		/* already played a song, clean up things/scrobble song */  		if (player.mode == PLAYER_FINISHED_PLAYBACK) { -			scrobbleSong.length = BarSamplesToSeconds (player.samplerate, -					player.channels, player.sampleSizeN); -			/* scrobble when >= nn% are played */ -			if (BarSamplesToSeconds (player.samplerate, -					player.channels, player.sampleSizeCurr) * 100 / -					scrobbleSong.length >= -					settings.lastfmScrobblePercent && +			scrobbleSong.length = player.songDuration / BAR_PLAYER_MS_TO_S_FACTOR; +			/* scrobble when >= nn% are played; use seconds, not +			 * milliseconds */ +			if (player.songPlayed / BAR_PLAYER_MS_TO_S_FACTOR * 100 / +					scrobbleSong.length >= settings.lastfmScrobblePercent &&  					settings.enableScrobbling) {  				WardrobeReturn_t wRet; @@ -224,14 +217,12 @@ int main (int argc, char **argv) {  		/* show time */  		if (player.mode >= PLAYER_SAMPLESIZE_INITIALIZED &&  				player.mode < PLAYER_FINISHED_PLAYBACK) { -			float songLength = BarSamplesToSeconds (player.samplerate, -					player.channels, player.sampleSizeN); -			float songRemaining = songLength - -					BarSamplesToSeconds (player.samplerate, -							player.channels, player.sampleSizeCurr); -			printf ("-%02i:%02i/%02i:%02i\r", (int) songRemaining/60, -					(int) songRemaining%60, (int) songLength/60, -					(int) songLength%60); +			long int songRemaining = player.songDuration - player.songPlayed; +			printf ("-%02i:%02i/%02i:%02i\r", +					(int) songRemaining / BAR_PLAYER_MS_TO_S_FACTOR / 60, +					(int) songRemaining / BAR_PLAYER_MS_TO_S_FACTOR % 60, +					(int) player.songDuration / BAR_PLAYER_MS_TO_S_FACTOR / 60, +					(int) player.songDuration / BAR_PLAYER_MS_TO_S_FACTOR % 60);  			fflush (stdout);  		}  	} diff --git a/src/player.c b/src/player.c index 4266e44..e6edf2e 100644 --- a/src/player.c +++ b/src/player.c @@ -137,6 +137,10 @@ size_t BarPlayerAACCurlCb (void *ptr, size_t size, size_t nmemb, void *stream) {  			/* ao_play needs bytes: 1 sample = 16 bits = 2 bytes */  			ao_play (player->audioOutDevice, (char *) aacDecoded,  					frameInfo.samples * 2); +			/* add played frame length to played time, explained below */ +			player->songPlayed += (float) frameInfo.samples * +					(float) BAR_PLAYER_MS_TO_S_FACTOR / +					(float) player->samplerate / (float) player->channels;  			player->bufferRead += frameInfo.bytesconsumed;  			player->sampleSizeCurr++;  			/* going through this loop can take up to a few seconds => @@ -214,6 +218,16 @@ size_t BarPlayerAACCurlCb (void *ptr, size_t size, size_t nmemb, void *stream) {  							sizeof (player->sampleSizeN));  					player->bufferRead += 4;  					player->sampleSizeCurr = 0; +					/* set up song duration (assuming one frame always contains +					 * the same number of samples); numbers are too huge => use +					 * float +					 * calculation: channels * number of frames * samples per +					 * frame / samplerate */ +					/* FIXME: Hard-coded number of samples per frame */ +					player->songDuration = (float) player->sampleSizeN * +							4096.0 * (float) BAR_PLAYER_MS_TO_S_FACTOR / +							(float) player->samplerate / +							(float) player->channels;  					break;  				} else {  					player->sampleSize[player->sampleSizeCurr] = @@ -297,7 +311,6 @@ size_t BarPlayerMp3CurlCb (void *ptr, size_t size, size_t nmemb, void *stream) {  				break;  			}  		} -		mad_timer_add (&player->mp3Timer, player->mp3Frame.header.duration);  		mad_synth_frame (&player->mp3Synth, &player->mp3Frame);  		for (i = 0; i < player->mp3Synth.pcm.length; i++) {  			/* left channel */ @@ -321,12 +334,20 @@ size_t BarPlayerMp3CurlCb (void *ptr, size_t size, size_t nmemb, void *stream) {  			format.byte_format = AO_FMT_LITTLE;  			player->audioOutDevice = ao_open_live (audioOutDriver,  					&format, NULL); -			player->mode = PLAYER_AUDIO_INITIALIZED; +			/* must be > PLAYER_SAMPLESIZE_INITIALIZED, otherwise time won't +			 * be visible to user (ugly, but mp3 decoding != aac decoding) */ +			player->mode = PLAYER_RECV_DATA;  		}  		/* samples * length * channels */  		ao_play (player->audioOutDevice, (char *) madDecoded,  				player->mp3Synth.pcm.length * 2 * 2); +		/* same calculation as in aac player; don't need to divide by channels, +		 * length is number of samples for _one_ channel */ +		player->songPlayed += (float) player->mp3Synth.pcm.length * +				(float) BAR_PLAYER_MS_TO_S_FACTOR / +				(float) player->samplerate; +  		QUIT_PAUSE_CHECK;  	} while (player->mp3Stream.error != MAD_ERROR_BUFLEN); @@ -336,6 +357,40 @@ size_t BarPlayerMp3CurlCb (void *ptr, size_t size, size_t nmemb, void *stream) {  	return size*nmemb;  } + +/*	get file length; needed for mp3 only atm + *	@param header line + *	@param size of _one_ element + *	@param number of elements + *	@param optional data (player in this case) + *	@return read data size or -1 + */ +size_t BarPlayerParseHeader (void *ptr, size_t size, size_t nmemb, +		void *stream) { +	char *data = ptr; +	struct audioPlayer *player = stream; +	char lengthBuffer[20]; +	const char identString[] = "Content-Length: "; +	size_t identStringLength = strlen (identString); +	size_t contentLength = 0; + +	/* avoid buffer overflow */ +	if (size*nmemb > identStringLength && +			size*nmemb - identStringLength < sizeof (lengthBuffer) - 1) { +		if (memcmp (data, identString, identStringLength) == 0) { +			memset (lengthBuffer, 0, sizeof (lengthBuffer)); +			memcpy (lengthBuffer, data+identStringLength, size*nmemb - +					identStringLength); +			contentLength = atol (lengthBuffer); +			/* force floating point division to avoid overflows; +			 * calculation: file size / (kbit/s * kilo / bits per byte) */ +			/* FIXME: hardcoded kbits/s */ +			player->songDuration = (float) contentLength / (128.0 * 1000.0 / +					(float) BAR_PLAYER_MS_TO_S_FACTOR / 8.0); +		} +	} +	return size*nmemb; +}  #endif /* ENABLE_MAD */  /*	player thread; for every song a new thread is started @@ -373,10 +428,13 @@ void *BarPlayerThread (void *data) {  			mad_stream_init (&player->mp3Stream);  			mad_frame_init (&player->mp3Frame);  			mad_synth_init (&player->mp3Synth); -			mad_timer_reset (&player->mp3Timer);  			curl_easy_setopt (player->audioFd, CURLOPT_WRITEFUNCTION,  					BarPlayerMp3CurlCb); +			curl_easy_setopt (player->audioFd, CURLOPT_HEADERFUNCTION, +					BarPlayerParseHeader); +			curl_easy_setopt (player->audioFd, CURLOPT_WRITEHEADER, +					(void *) player);  			break;  		#endif /* ENABLE_MAD */ diff --git a/src/player.h b/src/player.h index eab03a9..ec77f16 100644 --- a/src/player.h +++ b/src/player.h @@ -40,6 +40,8 @@ THE SOFTWARE.  #include <pthread.h>  #include <piano.h> +#define BAR_PLAYER_MS_TO_S_FACTOR 1000 +  struct audioPlayer {  	/* buffer; should be large enough */  	unsigned char buffer[CURL_MAX_WRITE_SIZE*2]; @@ -54,14 +56,17 @@ struct audioPlayer {  	PianoAudioFormat_t audioFormat; -	size_t sampleSizeN; -	size_t sampleSizeCurr; +	/* duration and already played time; measured in milliseconds */ +	unsigned long int songDuration; +	unsigned long int songPlayed;  	/* aac */  	#ifdef ENABLE_FAAD  	NeAACDecHandle aacHandle;  	/* stsz atom: sample sizes */  	unsigned int *sampleSize; +	size_t sampleSizeN; +	size_t sampleSizeCurr;  	#endif  	/* mp3 */ @@ -69,7 +74,6 @@ struct audioPlayer {  	struct mad_stream mp3Stream;  	struct mad_frame mp3Frame;  	struct mad_synth mp3Synth; -	mad_timer_t mp3Timer;  	#endif  	unsigned long samplerate; | 
