output_plugin: add method delay()
This method is used to reduce the delay of commands issued to the shout plugin.
This commit is contained in:
		| @@ -100,6 +100,16 @@ struct audio_output_plugin { | ||||
| 	 */ | ||||
| 	void (*close)(void *data); | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns a positive number if the output thread shall delay | ||||
| 	 * the next call to play() or pause().  This should be | ||||
| 	 * implemented instead of doing a sleep inside the plugin, | ||||
| 	 * because this allows MPD to listen to commands meanwhile. | ||||
| 	 * | ||||
| 	 * @return the number of milliseconds to wait | ||||
| 	 */ | ||||
| 	unsigned (*delay)(void *data); | ||||
|  | ||||
| 	/** | ||||
| 	 * Display metadata for the next chunk.  Optional method, | ||||
| 	 * because not all devices can display metadata. | ||||
| @@ -202,6 +212,14 @@ ao_plugin_close(const struct audio_output_plugin *plugin, void *data) | ||||
| 	plugin->close(data); | ||||
| } | ||||
|  | ||||
| static inline unsigned | ||||
| ao_plugin_delay(const struct audio_output_plugin *plugin, void *data) | ||||
| { | ||||
| 	return plugin->delay != NULL | ||||
| 		? plugin->delay(data) | ||||
| 		: 0; | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| ao_plugin_send_tag(const struct audio_output_plugin *plugin, | ||||
| 		   void *data, const struct tag *tag) | ||||
|   | ||||
| @@ -278,6 +278,30 @@ ao_reopen(struct audio_output *ao) | ||||
| 		ao_open(ao); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Wait until the output's delay reaches zero. | ||||
|  * | ||||
|  * @return true if playback should be continued, false if a command | ||||
|  * was issued | ||||
|  */ | ||||
| static bool | ||||
| ao_wait(struct audio_output *ao) | ||||
| { | ||||
| 	while (true) { | ||||
| 		unsigned delay = ao_plugin_delay(ao->plugin, ao->data); | ||||
| 		if (delay == 0) | ||||
| 			return true; | ||||
|  | ||||
| 		GTimeVal tv; | ||||
| 		g_get_current_time(&tv); | ||||
| 		g_time_val_add(&tv, delay * 1000); | ||||
| 		g_cond_timed_wait(ao->cond, ao->mutex, &tv); | ||||
|  | ||||
| 		if (ao->command != AO_COMMAND_NONE) | ||||
| 			return false; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| ao_chunk_data(struct audio_output *ao, const struct music_chunk *chunk, | ||||
| 	      struct filter *replay_gain_filter, | ||||
| @@ -414,6 +438,9 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) | ||||
| 	while (size > 0 && ao->command == AO_COMMAND_NONE) { | ||||
| 		size_t nbytes; | ||||
|  | ||||
| 		if (!ao_wait(ao)) | ||||
| 			break; | ||||
|  | ||||
| 		g_mutex_unlock(ao->mutex); | ||||
| 		nbytes = ao_plugin_play(ao->plugin, ao->data, data, size, | ||||
| 					&error); | ||||
| @@ -511,6 +538,9 @@ static void ao_pause(struct audio_output *ao) | ||||
| 	ao_command_finished(ao); | ||||
|  | ||||
| 	do { | ||||
| 		if (!ao_wait(ao)) | ||||
| 			break; | ||||
|  | ||||
| 		g_mutex_unlock(ao->mutex); | ||||
| 		ret = ao_plugin_pause(ao->plugin, ao->data); | ||||
| 		g_mutex_lock(ao->mutex); | ||||
|   | ||||
| @@ -74,12 +74,12 @@ void timer_add(Timer *timer, int size) | ||||
| unsigned | ||||
| timer_delay(const Timer *timer) | ||||
| { | ||||
| 	int64_t delay = timer->time - now(); | ||||
| 	int64_t delay = (timer->time - now()) / 1000; | ||||
| 	if (delay < 0) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (delay > 1000 * 1000 * 1000) | ||||
| 		return 1000 * 1000; | ||||
| 	if (delay > G_MAXINT) | ||||
| 		delay = G_MAXINT; | ||||
|  | ||||
| 	return delay / 1000; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann