Merge branch 'v0.16.x'
Conflicts: NEWS configure.ac
This commit is contained in:
		
							
								
								
									
										9
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								NEWS
									
									
									
									
									
								
							| @@ -19,7 +19,14 @@ ver 0.17 (2011/??/??) | ||||
| * cue: show CUE track numbers | ||||
|  | ||||
|  | ||||
| ver 0.16.3 (2011/??/??) | ||||
| ver 0.16.4 (2011/??/??) | ||||
| * fix memory leaks | ||||
| * decoder: | ||||
|   - ffmpeg: workaround for semantic API change in recent ffmpeg versions | ||||
|   - flac: validate the sample rate when scanning the tag | ||||
|  | ||||
|  | ||||
| ver 0.16.3 (2011/06/04) | ||||
| * fix assertion failure in audio format mask parser | ||||
| * fix NULL pointer dereference in playlist parser | ||||
| * fix playlist files in base music directory | ||||
|   | ||||
							
								
								
									
										14
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -557,15 +557,16 @@ no|avahi|bonjour) | ||||
| 	;; | ||||
| esac | ||||
|  | ||||
| enable_avahi=no | ||||
| enable_bounjour=no | ||||
| if test x$with_zeroconf != xno; then | ||||
| 	if test x$with_zeroconf = xavahi || test x$with_zeroconf = xauto; then | ||||
| 		PKG_CHECK_MODULES([AVAHI], [avahi-client avahi-glib], | ||||
| 			 [found_avahi=1;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])] | ||||
| 			 MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS", | ||||
| 			 [found_avahi=0]) | ||||
| 			 [enable_avahi=yes;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])] | ||||
| 			 MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS") | ||||
| 	fi | ||||
|  | ||||
| 	if test x$found_avahi = x1; then | ||||
| 	if test x$enable_avahi = xyes; then | ||||
| 		with_zeroconf=avahi | ||||
| 	elif test x$with_zeroconf = xavahi; then | ||||
| 		AC_MSG_ERROR([Avahi support requested but not found]) | ||||
| @@ -573,13 +574,12 @@ if test x$with_zeroconf != xno; then | ||||
|  | ||||
| 	if test x$with_zeroconf = xbonjour || test x$with_zeroconf = xauto; then | ||||
| 		AC_CHECK_HEADER(dns_sd.h, | ||||
| 			[found_bonjour=1;AC_DEFINE([HAVE_BONJOUR], 1, [Define to enable Bonjour Zeroconf support])], | ||||
| 			[found_bonjour=0]) | ||||
| 			[enable_bonjour=yes;AC_DEFINE([HAVE_BONJOUR], 1, [Define to enable Bonjour Zeroconf support])]) | ||||
| 		AC_CHECK_LIB(dns_sd, DNSServiceRegister, | ||||
| 			MPD_LIBS="$MPD_LIBS -ldns_sd") | ||||
| 	fi | ||||
|  | ||||
| 	if test x$found_bonjour = x1; then | ||||
| 	if test x$enable_bonjour = xyes; then | ||||
| 		with_zeroconf=bonjour | ||||
| 	elif test x$with_zeroconf = xbonjour; then | ||||
| 		AC_MSG_ERROR([Bonjour support requested but not found]) | ||||
|   | ||||
							
								
								
									
										134
									
								
								doc/protocol.xml
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								doc/protocol.xml
									
									
									
									
									
								
							| @@ -8,18 +8,54 @@ | ||||
|     <title>General protocol syntax</title> | ||||
|  | ||||
|     <section> | ||||
|       <title>Requests</title> | ||||
|       <title>Protocol overview</title> | ||||
|  | ||||
|       <para> | ||||
|         If arguments contain spaces, they should be surrounded by double quotation | ||||
|         marks. | ||||
|         The MPD command protocol exchanges line-based text records | ||||
|         between client and server over TCP.  Once the client is | ||||
|         connected to the server, they conduct a conversation until the | ||||
|         client closes the connection. The conversation flow is always | ||||
|         initiated by the client. | ||||
|       </para> | ||||
|  | ||||
|       <para> | ||||
|         The client transmits a command sequence, terminated by the | ||||
|         newline character <constant>\n</constant>.  The server will | ||||
|         respond with one or more lines, the last of which will be a | ||||
|         completion code. | ||||
|       </para> | ||||
|  | ||||
|       <para> | ||||
|         When the client connects to the server, the server will answer | ||||
|         with the following line: | ||||
|  | ||||
|         <synopsis>OK MPD version</synopsis> | ||||
|  | ||||
|         where <varname>version</varname> is a version identifier such as | ||||
|         0.12.2.  This version identifier is the version of the protocol | ||||
|         spoken, not the real version of the daemon.  (There is no way to | ||||
|         retrieve this real version identifier from the connection.) | ||||
|       </para> | ||||
|     </section> | ||||
|  | ||||
|     <section> | ||||
|       <title>Requests</title> | ||||
|  | ||||
|       <cmdsynopsis> | ||||
|         <command>COMMAND</command> | ||||
|         <arg rep="repeat"><replaceable>ARG</replaceable></arg> | ||||
|       </cmdsynopsis> | ||||
|  | ||||
|       <para> | ||||
|         If arguments contain spaces, they should be surrounded by double | ||||
|         quotation marks. | ||||
|       </para> | ||||
|  | ||||
|       <para> | ||||
|         Argument strings are separated from the command and any other | ||||
|         arguments by linear white-space (' ' or '\t'). | ||||
|       </para> | ||||
|  | ||||
|       <para> | ||||
|         All data between the client and the server is encoded in | ||||
|         UTF-8. (Note: In UTF-8 all standard ansi characters, 0-127 are | ||||
| @@ -38,13 +74,97 @@ | ||||
|       <title>Responses</title> | ||||
|  | ||||
|       <para> | ||||
|         A command returns <returnvalue>OK</returnvalue> on completion | ||||
|         or <returnvalue>ACK some error</returnvalue> on failure. | ||||
|         These denote the end of command execution. | ||||
|         A command returns <returnvalue>OK</returnvalue> on completion or | ||||
|         <returnvalue>ACK some error</returnvalue> on failure.  These | ||||
|         denote the end of command execution. | ||||
|       </para> | ||||
|  | ||||
|       <section> | ||||
|         <title>Failure responses</title> | ||||
|  | ||||
|         <para> | ||||
|           The nature of the error can be gleaned from the information | ||||
|           that follows the <returnvalue>ACK</returnvalue>. | ||||
|           <returnvalue>ACK</returnvalue> lines are of the form: | ||||
|  | ||||
|           <synopsis>ACK [error@command_listNum] {current_command} message_text\n</synopsis> | ||||
|  | ||||
|           These responses are generated by a call to | ||||
|           <function>commandError</function>. They contain four separate | ||||
|           terms. Let's look at each of them: | ||||
|  | ||||
|           <itemizedlist> | ||||
|             <listitem> | ||||
|               <para> | ||||
|                 <returnvalue>error</returnvalue>: numeric value of one | ||||
|                 of the <constant>ACK_ERROR</constant> constants defined | ||||
|                 in <filename>ack.h</filename>. | ||||
|               </para> | ||||
|             </listitem> | ||||
|             <listitem> | ||||
|               <para> | ||||
|                 <returnvalue>command_listNum</returnvalue>: | ||||
|                 offset of the command that caused the error in a <link | ||||
|                   linkend="command_lists">Command List</link>. | ||||
|                 An error will always cause a command list to terminate | ||||
|                 at the command that causes the error. | ||||
|               </para> | ||||
|             </listitem> | ||||
|             <listitem> | ||||
|               <para> | ||||
|                 <returnvalue>current_command</returnvalue>: | ||||
|                 name of the command, in a <link | ||||
|                   linkend="command_lists">Command List</link>, | ||||
|                 that was executing when the error occurred. | ||||
|               </para> | ||||
|             </listitem> | ||||
|             <listitem> | ||||
|               <para> | ||||
|                 <returnvalue>message_text</returnvalue>: | ||||
|                 some (hopefully) informative text that describes the | ||||
|                 nature of the error. | ||||
|               </para> | ||||
|             </listitem> | ||||
|           </itemizedlist> | ||||
|         </para> | ||||
|  | ||||
|         <example> | ||||
|           <title>foo</title> | ||||
|           <para> | ||||
|             An example might help. Consider the following sequence | ||||
|             sent from the client to the server. | ||||
|  | ||||
|             <synopsis> | ||||
|               command_list_begin | ||||
|               volume 86 | ||||
|               play 10240 | ||||
|               status | ||||
|               command_list_end | ||||
|             </synopsis> | ||||
|           </para> | ||||
|  | ||||
|           <para> | ||||
|             The server responds with: | ||||
|  | ||||
|             <returnvalue> | ||||
|               ACK [50@1] {play} song doesn't exist: "10240" | ||||
|             </returnvalue> | ||||
|           </para> | ||||
|  | ||||
|           <para> | ||||
|             This tells us that the play command, which was the | ||||
|             second in the list (the first or only command is | ||||
|             numbered 0), failed with error 50.  The number 50 | ||||
|             translates to <constant>ACK_ERROR_NO_EXIST</constant>--the | ||||
|             song doesn't exist.  This is reiterated by the message text | ||||
|             which also tells us which song doesn't exist. | ||||
|           </para> | ||||
|  | ||||
|         </example> | ||||
|       </section> | ||||
|     </section> | ||||
|  | ||||
|     <section> | ||||
|     <section id="command_lists"> | ||||
|       <title>Command lists</title> | ||||
|  | ||||
|       <para> | ||||
|   | ||||
| @@ -456,7 +456,7 @@ cd mpd-version</programlisting> | ||||
|       </para> | ||||
|  | ||||
|       <para> | ||||
|         To configure a filter, add a | ||||
|         To configure a playlist plugin, add a | ||||
|         <varname>playlist_plugin</varname> block to | ||||
|         <filename>mpd.conf</filename>: | ||||
|       </para> | ||||
|   | ||||
| @@ -60,8 +60,10 @@ ape_scan_internal(FILE *fp, tag_ape_callback_t callback, void *ctx) | ||||
| 	assert(remaining > 10); | ||||
|  | ||||
| 	char *buffer = g_malloc(remaining); | ||||
| 	if (fread(buffer, 1, remaining, fp) != remaining) | ||||
| 	if (fread(buffer, 1, remaining, fp) != remaining) { | ||||
| 		g_free(buffer); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/* read tags */ | ||||
| 	unsigned n = GUINT32_FROM_LE(footer.count); | ||||
|   | ||||
							
								
								
									
										11
									
								
								src/conf.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/conf.c
									
									
									
									
									
								
							| @@ -372,6 +372,7 @@ config_read_file(const char *file, GError **error_r) | ||||
| 			assert(*line != 0); | ||||
| 			g_propagate_prefixed_error(error_r, error, | ||||
| 						   "line %i: ", count); | ||||
| 			fclose(fp); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| @@ -383,6 +384,7 @@ config_read_file(const char *file, GError **error_r) | ||||
| 			g_set_error(error_r, config_quark(), 0, | ||||
| 				    "unrecognized parameter in config file at " | ||||
| 				    "line %i: %s\n", count, name); | ||||
| 			fclose(fp); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| @@ -392,6 +394,7 @@ config_read_file(const char *file, GError **error_r) | ||||
| 				    "config parameter \"%s\" is first defined " | ||||
| 				    "on line %i and redefined on line %i\n", | ||||
| 				    name, param->line, count); | ||||
| 			fclose(fp); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| @@ -403,6 +406,7 @@ config_read_file(const char *file, GError **error_r) | ||||
| 			if (*line != '{') { | ||||
| 				g_set_error(error_r, config_quark(), 0, | ||||
| 					    "line %i: '{' expected", count); | ||||
| 				fclose(fp); | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
| @@ -411,12 +415,15 @@ config_read_file(const char *file, GError **error_r) | ||||
| 				g_set_error(error_r, config_quark(), 0, | ||||
| 					    "line %i: Unknown tokens after '{'", | ||||
| 					    count); | ||||
| 				fclose(fp); | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
| 			param = config_read_block(fp, &count, string, error_r); | ||||
| 			if (param == NULL) | ||||
| 			if (param == NULL) { | ||||
| 				fclose(fp); | ||||
| 				return false; | ||||
| 			} | ||||
| 		} else { | ||||
| 			/* a string value */ | ||||
|  | ||||
| @@ -433,6 +440,7 @@ config_read_file(const char *file, GError **error_r) | ||||
| 					g_error_free(error); | ||||
| 				} | ||||
|  | ||||
| 				fclose(fp); | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
| @@ -440,6 +448,7 @@ config_read_file(const char *file, GError **error_r) | ||||
| 				g_set_error(error_r, config_quark(), 0, | ||||
| 					    "line %i: Unknown tokens after value", | ||||
| 					    count); | ||||
| 				fclose(fp); | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
|   | ||||
| @@ -180,7 +180,7 @@ db_check(void) | ||||
| 		} | ||||
|  | ||||
| 		/* Check if we can write to the directory */ | ||||
| 		if (access(dirPath, R_OK | W_OK)) { | ||||
| 		if (access(dirPath, X_OK | W_OK)) { | ||||
| 			g_warning("Can't create db file in \"%s\": %s", | ||||
| 				  dirPath, strerror(errno)); | ||||
| 			g_free(dirPath); | ||||
|   | ||||
| @@ -138,6 +138,33 @@ mpd_ffmpeg_stream_open(struct decoder *decoder, struct input_stream *input) | ||||
| 	return stream; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * API compatibility wrapper for av_open_input_stream() and | ||||
|  * avformat_open_input(). | ||||
|  */ | ||||
| static int | ||||
| mpd_ffmpeg_open_input(AVFormatContext **ic_ptr, | ||||
| #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,101,0) | ||||
| 		      AVIOContext *pb, | ||||
| #else | ||||
| 		      ByteIOContext *pb, | ||||
| #endif | ||||
| 		      const char *filename, | ||||
| 		      AVInputFormat *fmt) | ||||
| { | ||||
| #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,1,3) | ||||
| 	AVFormatContext *context = avformat_alloc_context(); | ||||
| 	if (context == NULL) | ||||
| 		return AVERROR(ENOMEM); | ||||
|  | ||||
| 	context->pb = pb; | ||||
| 	*ic_ptr = context; | ||||
| 	return avformat_open_input(ic_ptr, filename, fmt, NULL); | ||||
| #else | ||||
| 	return av_open_input_stream(ic_ptr, pb, filename, fmt, NULL); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static void | ||||
| mpd_ffmpeg_stream_close(struct mpd_ffmpeg_stream *stream) | ||||
| { | ||||
| @@ -317,9 +344,9 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) | ||||
| 	} | ||||
|  | ||||
| 	//ffmpeg works with ours "fileops" helper | ||||
| 	AVFormatContext *format_context; | ||||
| 	if (av_open_input_stream(&format_context, stream->io, input->uri, | ||||
| 				 input_format, NULL) != 0) { | ||||
| 	AVFormatContext *format_context = NULL; | ||||
| 	if (mpd_ffmpeg_open_input(&format_context, stream->io, input->uri, | ||||
| 				  input_format) != 0) { | ||||
| 		g_warning("Open failed\n"); | ||||
| 		mpd_ffmpeg_stream_close(stream); | ||||
| 		return; | ||||
| @@ -441,13 +468,26 @@ static const ffmpeg_tag_map ffmpeg_tag_maps[] = { | ||||
| }; | ||||
|  | ||||
| static bool | ||||
| ffmpeg_copy_metadata(struct tag *tag, AVMetadata *m, | ||||
| ffmpeg_copy_metadata(struct tag *tag, | ||||
| #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,1,0) | ||||
| 		     AVDictionary *m, | ||||
| #else | ||||
| 		     AVMetadata *m, | ||||
| #endif | ||||
| 		     const ffmpeg_tag_map tag_map) | ||||
| { | ||||
| #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,1,0) | ||||
| 	AVDictionaryEntry *mt = NULL; | ||||
|  | ||||
| 	while ((mt = av_dict_get(m, tag_map.name, mt, 0)) != NULL) | ||||
| 		tag_add_item(tag, tag_map.type, mt->value); | ||||
| #else | ||||
| 	AVMetadataTag *mt = NULL; | ||||
|  | ||||
| 	while ((mt = av_metadata_get(m, tag_map.name, mt, 0)) != NULL) | ||||
| 		tag_add_item(tag, tag_map.type, mt->value); | ||||
| #endif | ||||
|  | ||||
| 	return mt != NULL; | ||||
| } | ||||
|  | ||||
| @@ -463,9 +503,9 @@ ffmpeg_stream_tag(struct input_stream *is) | ||||
| 	if (stream == NULL) | ||||
| 		return NULL; | ||||
|  | ||||
| 	AVFormatContext *f; | ||||
| 	if (av_open_input_stream(&f, stream->io, is->uri, | ||||
| 				 input_format, NULL) != 0) { | ||||
| 	AVFormatContext *f = NULL; | ||||
| 	if (mpd_ffmpeg_open_input(&f, stream->io, is->uri, | ||||
| 				  input_format) != 0) { | ||||
| 		mpd_ffmpeg_stream_close(stream); | ||||
| 		return NULL; | ||||
| 	} | ||||
|   | ||||
| @@ -224,7 +224,8 @@ flac_tag_apply_metadata(struct tag *tag, const char *track, | ||||
| 		break; | ||||
|  | ||||
| 	case FLAC__METADATA_TYPE_STREAMINFO: | ||||
| 		tag->time = flac_duration(&block->data.stream_info); | ||||
| 		if (block->data.stream_info.sample_rate > 0) | ||||
| 			tag->time = flac_duration(&block->data.stream_info); | ||||
| 		break; | ||||
|  | ||||
| 	default: | ||||
|   | ||||
| @@ -20,6 +20,7 @@ | ||||
| #ifndef MPD_FLAC_METADATA_H | ||||
| #define MPD_FLAC_METADATA_H | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <stdbool.h> | ||||
| #include <FLAC/metadata.h> | ||||
|  | ||||
| @@ -29,6 +30,8 @@ struct replay_gain_info; | ||||
| static inline unsigned | ||||
| flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info) | ||||
| { | ||||
| 	assert(stream_info->sample_rate > 0); | ||||
|  | ||||
| 	return (stream_info->total_samples + stream_info->sample_rate - 1) / | ||||
| 		stream_info->sample_rate; | ||||
| } | ||||
|   | ||||
| @@ -106,12 +106,14 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, | ||||
| 		g_set_error(error, ao_output_quark(), 0, | ||||
| 			    "\"%s\" is not a valid ao driver", | ||||
| 			    value); | ||||
| 		g_free(ad); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if ((ai = ao_driver_info(ad->driver)) == NULL) { | ||||
| 		g_set_error(error, ao_output_quark(), 0, | ||||
| 			    "problems getting driver info"); | ||||
| 		g_free(ad); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| @@ -129,6 +131,7 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, | ||||
| 				g_set_error(error, ao_output_quark(), 0, | ||||
| 					    "problems parsing options \"%s\"", | ||||
| 					    options[i]); | ||||
| 				g_free(ad); | ||||
| 				return NULL; | ||||
| 			} | ||||
|  | ||||
|   | ||||
| @@ -103,6 +103,7 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, | ||||
| 	if (encoder_plugin == NULL) { | ||||
| 		g_set_error(error, httpd_output_quark(), 0, | ||||
| 			    "No such encoder: %s", encoder_name); | ||||
| 		g_free(httpd); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -79,23 +79,27 @@ recorder_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, | ||||
| 	if (encoder_plugin == NULL) { | ||||
| 		g_set_error(error_r, recorder_output_quark(), 0, | ||||
| 			    "No such encoder: %s", encoder_name); | ||||
| 		return NULL; | ||||
| 		goto failure; | ||||
| 	} | ||||
|  | ||||
| 	recorder->path = config_get_block_string(param, "path", NULL); | ||||
| 	if (recorder->path == NULL) { | ||||
| 		g_set_error(error_r, recorder_output_quark(), 0, | ||||
| 			    "'path' not configured"); | ||||
| 		return NULL; | ||||
| 		goto failure; | ||||
| 	} | ||||
|  | ||||
| 	/* initialize encoder */ | ||||
|  | ||||
| 	recorder->encoder = encoder_init(encoder_plugin, param, error_r); | ||||
| 	if (recorder->encoder == NULL) | ||||
| 		return NULL; | ||||
| 		goto failure; | ||||
|  | ||||
| 	return recorder; | ||||
|  | ||||
| failure: | ||||
| 	g_free(recorder); | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
| @@ -152,7 +152,7 @@ my_shout_init_driver(const struct audio_format *audio_format, | ||||
| 	if (port == 0) { | ||||
| 		g_set_error(error, shout_output_quark(), 0, | ||||
| 			    "shout port must be configured"); | ||||
| 		return NULL; | ||||
| 		goto failure; | ||||
| 	} | ||||
|  | ||||
| 	check_block_param("password"); | ||||
| @@ -174,21 +174,21 @@ my_shout_init_driver(const struct audio_format *audio_format, | ||||
| 				    "shout quality \"%s\" is not a number in the " | ||||
| 				    "range -1 to 10, line %i", | ||||
| 				    value, param->line); | ||||
| 			return NULL; | ||||
| 			goto failure; | ||||
| 		} | ||||
|  | ||||
| 		if (config_get_block_string(param, "bitrate", NULL) != NULL) { | ||||
| 			g_set_error(error, shout_output_quark(), 0, | ||||
| 				    "quality and bitrate are " | ||||
| 				    "both defined"); | ||||
| 			return NULL; | ||||
| 			goto failure; | ||||
| 		} | ||||
| 	} else { | ||||
| 		value = config_get_block_string(param, "bitrate", NULL); | ||||
| 		if (value == NULL) { | ||||
| 			g_set_error(error, shout_output_quark(), 0, | ||||
| 				    "neither bitrate nor quality defined"); | ||||
| 			return NULL; | ||||
| 			goto failure; | ||||
| 		} | ||||
|  | ||||
| 		sd->bitrate = strtol(value, &test, 10); | ||||
| @@ -196,7 +196,7 @@ my_shout_init_driver(const struct audio_format *audio_format, | ||||
| 		if (*test != '\0' || sd->bitrate <= 0) { | ||||
| 			g_set_error(error, shout_output_quark(), 0, | ||||
| 				    "bitrate must be a positive integer"); | ||||
| 			return NULL; | ||||
| 			goto failure; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -206,12 +206,12 @@ my_shout_init_driver(const struct audio_format *audio_format, | ||||
| 		g_set_error(error, shout_output_quark(), 0, | ||||
| 			    "couldn't find shout encoder plugin \"%s\"", | ||||
| 			    encoding); | ||||
| 		return NULL; | ||||
| 		goto failure; | ||||
| 	} | ||||
|  | ||||
| 	sd->encoder = encoder_init(encoder_plugin, param, error); | ||||
| 	if (sd->encoder == NULL) | ||||
| 		return NULL; | ||||
| 		goto failure; | ||||
|  | ||||
| 	if (strcmp(encoding, "mp3") == 0 || strcmp(encoding, "lame") == 0) | ||||
| 		shout_format = SHOUT_FORMAT_MP3; | ||||
| @@ -225,7 +225,7 @@ my_shout_init_driver(const struct audio_format *audio_format, | ||||
| 			g_set_error(error, shout_output_quark(), 0, | ||||
| 				    "you cannot stream \"%s\" to shoutcast, use mp3", | ||||
| 				    encoding); | ||||
| 			return NULL; | ||||
| 			goto failure; | ||||
| 		} else if (0 == strcmp(value, "shoutcast")) | ||||
| 			protocol = SHOUT_PROTOCOL_ICY; | ||||
| 		else if (0 == strcmp(value, "icecast1")) | ||||
| @@ -237,7 +237,7 @@ my_shout_init_driver(const struct audio_format *audio_format, | ||||
| 				    "shout protocol \"%s\" is not \"shoutcast\" or " | ||||
| 				    "\"icecast1\"or \"icecast2\"", | ||||
| 				    value); | ||||
| 			return NULL; | ||||
| 			goto failure; | ||||
| 		} | ||||
| 	} else { | ||||
| 		protocol = SHOUT_PROTOCOL_HTTP; | ||||
| @@ -256,7 +256,7 @@ my_shout_init_driver(const struct audio_format *audio_format, | ||||
| 	    shout_set_agent(sd->shout_conn, "MPD") != SHOUTERR_SUCCESS) { | ||||
| 		g_set_error(error, shout_output_quark(), 0, | ||||
| 			    "%s", shout_get_error(sd->shout_conn)); | ||||
| 		return NULL; | ||||
| 		goto failure; | ||||
| 	} | ||||
|  | ||||
| 	/* optional paramters */ | ||||
| @@ -267,14 +267,14 @@ my_shout_init_driver(const struct audio_format *audio_format, | ||||
| 	if (value != NULL && shout_set_genre(sd->shout_conn, value)) { | ||||
| 		g_set_error(error, shout_output_quark(), 0, | ||||
| 			    "%s", shout_get_error(sd->shout_conn)); | ||||
| 		return NULL; | ||||
| 		goto failure; | ||||
| 	} | ||||
|  | ||||
| 	value = config_get_block_string(param, "description", NULL); | ||||
| 	if (value != NULL && shout_set_description(sd->shout_conn, value)) { | ||||
| 		g_set_error(error, shout_output_quark(), 0, | ||||
| 			    "%s", shout_get_error(sd->shout_conn)); | ||||
| 		return NULL; | ||||
| 		goto failure; | ||||
| 	} | ||||
|  | ||||
| 	value = config_get_block_string(param, "url", NULL); | ||||
| @@ -307,6 +307,10 @@ my_shout_init_driver(const struct audio_format *audio_format, | ||||
| 	} | ||||
|  | ||||
| 	return sd; | ||||
|  | ||||
| failure: | ||||
| 	free_shout_data(sd); | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static bool | ||||
|   | ||||
| @@ -579,8 +579,10 @@ sticker_load(const char *type, const char *uri) | ||||
| 	bool success; | ||||
|  | ||||
| 	success = sticker_list_values(sticker->table, type, uri); | ||||
| 	if (!success) | ||||
| 	if (!success) { | ||||
| 		sticker_free(sticker); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (g_hash_table_size(sticker->table) == 0) { | ||||
| 		/* don't return empty sticker objects */ | ||||
|   | ||||
| @@ -37,30 +37,28 @@ my_log_func(G_GNUC_UNUSED const gchar *log_domain, | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	const char *path, *name, *value; | ||||
| 	GError *error = NULL; | ||||
| 	bool success; | ||||
| 	int ret; | ||||
|  | ||||
| 	if (argc != 3) { | ||||
| 		g_printerr("Usage: read_conf FILE SETTING\n"); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	path = argv[1]; | ||||
| 	name = argv[2]; | ||||
| 	const char *path = argv[1]; | ||||
| 	const char *name = argv[2]; | ||||
|  | ||||
| 	g_log_set_default_handler(my_log_func, NULL); | ||||
|  | ||||
| 	config_global_init(); | ||||
| 	success = config_read_file(path, &error); | ||||
|  | ||||
| 	GError *error = NULL; | ||||
| 	bool success = config_read_file(path, &error); | ||||
| 	if (!success) { | ||||
| 		g_printerr("%s:", error->message); | ||||
| 		g_error_free(error); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	value = config_get_string(name, NULL); | ||||
| 	const char *value = config_get_string(name, NULL); | ||||
| 	int ret; | ||||
| 	if (value != NULL) { | ||||
| 		g_print("%s\n", value); | ||||
| 		ret = 0; | ||||
| @@ -70,5 +68,5 @@ int main(int argc, char **argv) | ||||
| 	} | ||||
|  | ||||
| 	config_global_finish(); | ||||
| 	return 0; | ||||
| 	return ret; | ||||
| } | ||||
|   | ||||
| @@ -106,7 +106,6 @@ int main(int argc, char **argv) | ||||
| 	struct filter *filter; | ||||
| 	const struct audio_format *out_audio_format; | ||||
| 	char buffer[4096]; | ||||
| 	size_t frame_size; | ||||
|  | ||||
| 	if (argc < 3 || argc > 4) { | ||||
| 		g_printerr("Usage: run_filter CONFIG NAME [FORMAT] <IN\n"); | ||||
| @@ -162,8 +161,6 @@ int main(int argc, char **argv) | ||||
| 	g_printerr("audio_format=%s\n", | ||||
| 		   audio_format_to_string(out_audio_format, &af_string)); | ||||
|  | ||||
| 	frame_size = audio_format_frame_size(&audio_format); | ||||
|  | ||||
| 	/* play */ | ||||
|  | ||||
| 	while (true) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann