From c392efb4810319fef34b1230185dd0124c4dfb30 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 1 Oct 2012 23:19:15 +0200 Subject: output/shout: make variables more local --- src/output/shout_output_plugin.c | 75 ++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 49 deletions(-) (limited to 'src/output') diff --git a/src/output/shout_output_plugin.c b/src/output/shout_output_plugin.c index 7867ae63..d6805f54 100644 --- a/src/output/shout_output_plugin.c +++ b/src/output/shout_output_plugin.c @@ -114,24 +114,7 @@ static struct audio_output * my_shout_init_driver(const struct config_param *param, GError **error) { - struct shout_data *sd; - char *test; - unsigned port; - char *host; - char *mount; - char *passwd; - const char *encoding; - const struct encoder_plugin *encoder_plugin; - unsigned shout_format; - unsigned protocol; - const char *user; - char *name; - const char *value; - const struct block_param *block_param; - int public; - - sd = new_shout_data(); - + struct shout_data *sd = new_shout_data(); if (!ao_base_init(&sd->base, &shout_output_plugin, param, error)) { free_shout_data(sd); return NULL; @@ -152,13 +135,14 @@ my_shout_init_driver(const struct config_param *param, shout_init_count++; + const struct block_param *block_param; check_block_param("host"); - host = block_param->value; + char *host = block_param->value; check_block_param("mount"); - mount = block_param->value; + char *mount = block_param->value; - port = config_get_block_unsigned(param, "port", 0); + unsigned port = config_get_block_unsigned(param, "port", 0); if (port == 0) { g_set_error(error, shout_output_quark(), 0, "shout port must be configured"); @@ -166,17 +150,18 @@ my_shout_init_driver(const struct config_param *param, } check_block_param("password"); - passwd = block_param->value; + const char *passwd = block_param->value; check_block_param("name"); - name = block_param->value; + const char *name = block_param->value; - public = config_get_block_bool(param, "public", false); + bool public = config_get_block_bool(param, "public", false); - user = config_get_block_string(param, "user", "source"); + const char *user = config_get_block_string(param, "user", "source"); - value = config_get_block_string(param, "quality", NULL); + const char *value = config_get_block_string(param, "quality", NULL); if (value != NULL) { + char *test; sd->quality = strtod(value, &test); if (*test != '\0' || sd->quality < -1.0 || sd->quality > 10.0) { @@ -201,6 +186,7 @@ my_shout_init_driver(const struct config_param *param, goto failure; } + char *test; sd->bitrate = strtol(value, &test, 10); if (*test != '\0' || sd->bitrate <= 0) { @@ -210,8 +196,10 @@ my_shout_init_driver(const struct config_param *param, } } - encoding = config_get_block_string(param, "encoding", "ogg"); - encoder_plugin = shout_encoder_plugin_get(encoding); + const char *encoding = config_get_block_string(param, "encoding", + "ogg"); + const struct encoder_plugin *encoder_plugin = + shout_encoder_plugin_get(encoding); if (encoder_plugin == NULL) { g_set_error(error, shout_output_quark(), 0, "couldn't find shout encoder plugin \"%s\"", @@ -223,11 +211,13 @@ my_shout_init_driver(const struct config_param *param, if (sd->encoder == NULL) goto failure; + unsigned shout_format; if (strcmp(encoding, "mp3") == 0 || strcmp(encoding, "lame") == 0) shout_format = SHOUT_FORMAT_MP3; else shout_format = SHOUT_FORMAT_OGG; + unsigned protocol; value = config_get_block_string(param, "protocol", NULL); if (value != NULL) { if (0 == strcmp(value, "shoutcast") && @@ -355,8 +345,6 @@ handle_shout_error(struct shout_data *sd, int err, GError **error) static bool write_page(struct shout_data *sd, GError **error) { - int err; - assert(sd->encoder != NULL); sd->buf.len = encoder_read(sd->encoder, @@ -364,7 +352,7 @@ write_page(struct shout_data *sd, GError **error) if (sd->buf.len == 0) return true; - err = shout_send(sd->shout_conn, sd->buf.data, sd->buf.len); + int err = shout_send(sd->shout_conn, sd->buf.data, sd->buf.len); if (!handle_shout_error(sd, err, error)) return false; @@ -425,10 +413,7 @@ my_shout_close_device(struct audio_output *ao) static bool shout_connect(struct shout_data *sd, GError **error) { - int state; - - state = shout_open(sd->shout_conn); - switch (state) { + switch (shout_open(sd->shout_conn)) { case SHOUTERR_SUCCESS: case SHOUTERR_CONNECTED: return true; @@ -448,17 +433,14 @@ my_shout_open_device(struct audio_output *ao, struct audio_format *audio_format, GError **error) { struct shout_data *sd = (struct shout_data *)ao; - bool ret; - ret = shout_connect(sd, error); - if (!ret) + if (!shout_connect(sd, error)) return false; sd->buf.len = 0; - ret = encoder_open(sd->encoder, audio_format, error) && - write_page(sd, error); - if (!ret) { + if (!encoder_open(sd->encoder, audio_format, error) || + !write_page(sd, error)) { shout_close(sd->shout_conn); return false; } @@ -528,32 +510,27 @@ static void my_shout_set_tag(struct audio_output *ao, const struct tag *tag) { struct shout_data *sd = (struct shout_data *)ao; - bool ret; GError *error = NULL; if (sd->encoder->plugin->tag != NULL) { /* encoder plugin supports stream tags */ - ret = encoder_pre_tag(sd->encoder, &error); - if (!ret) { + if (!encoder_pre_tag(sd->encoder, &error)) { g_warning("%s", error->message); g_error_free(error); return; } - ret = write_page(sd, NULL); - if (!ret) + if (!write_page(sd, NULL)) return; - ret = encoder_tag(sd->encoder, tag, &error); - if (!ret) { + if (!encoder_tag(sd->encoder, tag, &error)) { g_warning("%s", error->message); g_error_free(error); } } else { /* no stream tag support: fall back to icy-metadata */ char song[1024]; - shout_tag_to_metadata(tag, song, sizeof(song)); shout_metadata_add(sd->shout_meta, "song", song); -- cgit v1.2.3 From c7748fedab96da650c81f8a9fad7ec61a3bd96df Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 1 Oct 2012 23:18:33 +0200 Subject: output/shout: fix memory leak in error handler --- NEWS | 3 ++- src/output/shout_output_plugin.c | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src/output') diff --git a/NEWS b/NEWS index 5ff83109..46963f30 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,6 @@ ver 0.17.3 (2012/??/??) - +* output: + - shout: fix memory leak in error handler ver 0.17.2 (2012/09/30) * protocol: diff --git a/src/output/shout_output_plugin.c b/src/output/shout_output_plugin.c index d6805f54..bebc5e5d 100644 --- a/src/output/shout_output_plugin.c +++ b/src/output/shout_output_plugin.c @@ -439,8 +439,13 @@ my_shout_open_device(struct audio_output *ao, struct audio_format *audio_format, sd->buf.len = 0; - if (!encoder_open(sd->encoder, audio_format, error) || - !write_page(sd, error)) { + if (!encoder_open(sd->encoder, audio_format, error)) { + shout_close(sd->shout_conn); + return false; + } + + if (!write_page(sd, error)) { + encoder_close(sd->encoder); shout_close(sd->shout_conn); return false; } -- cgit v1.2.3 From fe8fc1081a9b9f5a086ee3f88230542c968ccc49 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 2 Oct 2012 00:07:06 +0200 Subject: output/shout: remove shout_buffer.len Make it a local variable instead. --- src/output/shout_output_plugin.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'src/output') diff --git a/src/output/shout_output_plugin.c b/src/output/shout_output_plugin.c index bebc5e5d..1b5922e9 100644 --- a/src/output/shout_output_plugin.c +++ b/src/output/shout_output_plugin.c @@ -38,7 +38,6 @@ struct shout_buffer { unsigned char data[32768]; - size_t len; }; struct shout_data { @@ -347,12 +346,12 @@ write_page(struct shout_data *sd, GError **error) { assert(sd->encoder != NULL); - sd->buf.len = encoder_read(sd->encoder, - sd->buf.data, sizeof(sd->buf.data)); - if (sd->buf.len == 0) + size_t nbytes = encoder_read(sd->encoder, + sd->buf.data, sizeof(sd->buf.data)); + if (nbytes == 0) return true; - int err = shout_send(sd->shout_conn, sd->buf.data, sd->buf.len); + int err = shout_send(sd->shout_conn, sd->buf.data, nbytes); if (!handle_shout_error(sd, err, error)) return false; @@ -361,8 +360,6 @@ write_page(struct shout_data *sd, GError **error) static void close_shout_conn(struct shout_data * sd) { - sd->buf.len = 0; - if (sd->encoder != NULL) { if (encoder_end(sd->encoder, NULL)) write_page(sd, NULL); @@ -437,8 +434,6 @@ my_shout_open_device(struct audio_output *ao, struct audio_format *audio_format, if (!shout_connect(sd, error)) return false; - sd->buf.len = 0; - if (!encoder_open(sd->encoder, audio_format, error)) { shout_close(sd->shout_conn); return false; -- cgit v1.2.3 From 674b4ab64735dac3b8113e09db4cdb9072ddacb7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 2 Oct 2012 00:08:06 +0200 Subject: output/shout: eliminate struct shout_buffer Move the raw buffer to struct shout_data. --- src/output/shout_output_plugin.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src/output') diff --git a/src/output/shout_output_plugin.c b/src/output/shout_output_plugin.c index 1b5922e9..63f1001b 100644 --- a/src/output/shout_output_plugin.c +++ b/src/output/shout_output_plugin.c @@ -36,10 +36,6 @@ #define DEFAULT_CONN_TIMEOUT 2 -struct shout_buffer { - unsigned char data[32768]; -}; - struct shout_data { struct audio_output base; @@ -53,7 +49,7 @@ struct shout_data { int timeout; - struct shout_buffer buf; + uint8_t buffer[32768]; }; static int shout_init_count; @@ -347,11 +343,11 @@ write_page(struct shout_data *sd, GError **error) assert(sd->encoder != NULL); size_t nbytes = encoder_read(sd->encoder, - sd->buf.data, sizeof(sd->buf.data)); + sd->buffer, sizeof(sd->buffer)); if (nbytes == 0) return true; - int err = shout_send(sd->shout_conn, sd->buf.data, nbytes); + int err = shout_send(sd->shout_conn, sd->buffer, nbytes); if (!handle_shout_error(sd, err, error)) return false; -- cgit v1.2.3 From 43d82520502bc0c76fbd11d6e949739235166021 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 1 Oct 2012 23:17:13 +0200 Subject: output/recorder, test/*: invoke encoder_read() after _open() Make sure the file header gets written at the beginning, before _write() gets called. --- src/encoder_plugin.h | 4 ++++ src/output/recorder_output_plugin.c | 7 +++++++ test/run_encoder.c | 2 ++ test/test_vorbis_encoder.c | 2 ++ 4 files changed, 15 insertions(+) (limited to 'src/output') diff --git a/src/encoder_plugin.h b/src/encoder_plugin.h index 33a37911..cae0c804 100644 --- a/src/encoder_plugin.h +++ b/src/encoder_plugin.h @@ -119,6 +119,10 @@ encoder_finish(struct encoder *encoder) * Before you free it, you must call encoder_close(). You may open * and close (reuse) one encoder any number of times. * + * After this function returns successfully and before the first + * encoder_write() call, you should invoke encoder_read() to obtain + * the file header. + * * @param encoder the encoder * @param audio_format the encoder's input audio format; the plugin * may modify the struct to adapt it to its abilities diff --git a/src/output/recorder_output_plugin.c b/src/output/recorder_output_plugin.c index ea299468..ad2d961d 100644 --- a/src/output/recorder_output_plugin.c +++ b/src/output/recorder_output_plugin.c @@ -192,6 +192,13 @@ recorder_output_open(struct audio_output *ao, return false; } + if (!recorder_output_encoder_to_file(recorder, error_r)) { + encoder_close(recorder->encoder); + close(recorder->fd); + unlink(recorder->path); + return false; + } + return true; } diff --git a/test/run_encoder.c b/test/run_encoder.c index 397dd857..db4d3af9 100644 --- a/test/run_encoder.c +++ b/test/run_encoder.c @@ -106,6 +106,8 @@ int main(int argc, char **argv) return 1; } + encoder_to_stdout(encoder); + /* do it */ while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { diff --git a/test/test_vorbis_encoder.c b/test/test_vorbis_encoder.c index 048d26f0..61939915 100644 --- a/test/test_vorbis_encoder.c +++ b/test/test_vorbis_encoder.c @@ -67,6 +67,8 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) success = encoder_open(encoder, &audio_format, NULL); assert(success); + encoder_to_stdout(encoder); + /* write a block of data */ success = encoder_write(encoder, zero, sizeof(zero), NULL); -- cgit v1.2.3 From 4227a325a51b8c230aa4f19848fea2de65ad70c9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 1 Oct 2012 23:52:40 +0200 Subject: output/httpd: make variables more local --- src/output/httpd_output_plugin.c | 47 ++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) (limited to 'src/output') diff --git a/src/output/httpd_output_plugin.c b/src/output/httpd_output_plugin.c index abef826b..1d730df7 100644 --- a/src/output/httpd_output_plugin.c +++ b/src/output/httpd_output_plugin.c @@ -114,10 +114,6 @@ httpd_output_init(const struct config_param *param, return NULL; } - const char *encoder_name, *bind_to_address; - const struct encoder_plugin *encoder_plugin; - guint port; - /* read configuration */ httpd->name = config_get_block_string(param, "name", "Set name in config"); @@ -126,10 +122,12 @@ httpd_output_init(const struct config_param *param, httpd->website = config_get_block_string(param, "website", "Set website in config"); - port = config_get_block_unsigned(param, "port", 8000); + guint port = config_get_block_unsigned(param, "port", 8000); - encoder_name = config_get_block_string(param, "encoder", "vorbis"); - encoder_plugin = encoder_plugin_get(encoder_name); + const char *encoder_name = + config_get_block_string(param, "encoder", "vorbis"); + const struct encoder_plugin *encoder_plugin = + encoder_plugin_get(encoder_name); if (encoder_plugin == NULL) { g_set_error(error, httpd_output_quark(), 0, "No such encoder: %s", encoder_name); @@ -144,7 +142,7 @@ httpd_output_init(const struct config_param *param, httpd->server_socket = server_socket_new(httpd_listen_in_event, httpd); - bind_to_address = + const char *bind_to_address = config_get_block_string(param, "bind_to_address", NULL); bool success = bind_to_address != NULL && strcmp(bind_to_address, "any") != 0 @@ -275,8 +273,6 @@ httpd_listen_in_event(int fd, const struct sockaddr *address, static struct page * httpd_output_read_page(struct httpd_output *httpd) { - size_t size = 0, nbytes; - if (httpd->unflushed_input >= 65536) { /* we have fed a lot of input into the encoder, but it didn't give anything back yet - flush now to avoid @@ -285,9 +281,11 @@ httpd_output_read_page(struct httpd_output *httpd) httpd->unflushed_input = 0; } + size_t size = 0; do { - nbytes = encoder_read(httpd->encoder, httpd->buffer + size, - sizeof(httpd->buffer) - size); + size_t nbytes = encoder_read(httpd->encoder, + httpd->buffer + size, + sizeof(httpd->buffer) - size); if (nbytes == 0) break; @@ -307,10 +305,7 @@ httpd_output_encoder_open(struct httpd_output *httpd, struct audio_format *audio_format, GError **error) { - bool success; - - success = encoder_open(httpd->encoder, audio_format, error); - if (!success) + if (!encoder_open(httpd->encoder, audio_format, error)) return false; /* we have to remember the encoder header, i.e. the first @@ -344,14 +339,12 @@ httpd_output_open(struct audio_output *ao, struct audio_format *audio_format, GError **error) { struct httpd_output *httpd = (struct httpd_output *)ao; - bool success; g_mutex_lock(httpd->mutex); /* open the encoder */ - success = httpd_output_encoder_open(httpd, audio_format, error); - if (!success) { + if (!httpd_output_encoder_open(httpd, audio_format, error)) { g_mutex_unlock(httpd->mutex); return false; } @@ -495,10 +488,7 @@ static bool httpd_output_encode_and_play(struct httpd_output *httpd, const void *chunk, size_t size, GError **error) { - bool success; - - success = encoder_write(httpd->encoder, chunk, size, error); - if (!success) + if (!encoder_write(httpd->encoder, chunk, size, error)) return false; httpd->unflushed_input += size; @@ -510,16 +500,12 @@ httpd_output_encode_and_play(struct httpd_output *httpd, static size_t httpd_output_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error) + GError **error_r) { struct httpd_output *httpd = (struct httpd_output *)ao; if (httpd_output_lock_has_clients(httpd)) { - bool success; - - success = httpd_output_encode_and_play(httpd, chunk, size, - error); - if (!success) + if (!httpd_output_encode_and_play(httpd, chunk, size, error_r)) return 0; } @@ -562,7 +548,6 @@ httpd_output_tag(struct audio_output *ao, const struct tag *tag) if (httpd->encoder->plugin->tag != NULL) { /* embed encoder tags */ - struct page *page; /* flush the current stream, and end it */ @@ -578,7 +563,7 @@ httpd_output_tag(struct audio_output *ao, const struct tag *tag) used as the new "header" page, which is sent to all new clients */ - page = httpd_output_read_page(httpd); + struct page *page = httpd_output_read_page(httpd); if (page != NULL) { if (httpd->header != NULL) page_unref(httpd->header); -- cgit v1.2.3 From fbcbcdc0011949339666b2567c987156d47197e8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 1 Oct 2012 23:56:10 +0200 Subject: output/recorder: make variables more local --- src/output/recorder_output_plugin.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'src/output') diff --git a/src/output/recorder_output_plugin.c b/src/output/recorder_output_plugin.c index ad2d961d..5d098f08 100644 --- a/src/output/recorder_output_plugin.c +++ b/src/output/recorder_output_plugin.c @@ -77,13 +77,12 @@ recorder_output_init(const struct config_param *param, GError **error_r) return NULL; } - const char *encoder_name; - const struct encoder_plugin *encoder_plugin; - /* read configuration */ - encoder_name = config_get_block_string(param, "encoder", "vorbis"); - encoder_plugin = encoder_plugin_get(encoder_name); + const char *encoder_name = + config_get_block_string(param, "encoder", "vorbis"); + const struct encoder_plugin *encoder_plugin = + encoder_plugin_get(encoder_name); if (encoder_plugin == NULL) { g_set_error(error_r, recorder_output_quark(), 0, "No such encoder: %s", encoder_name); @@ -126,25 +125,24 @@ recorder_output_finish(struct audio_output *ao) */ static bool recorder_output_encoder_to_file(struct recorder_output *recorder, - GError **error_r) + GError **error_r) { - size_t size = 0, position, nbytes; - assert(recorder->fd >= 0); /* read from the encoder */ - size = encoder_read(recorder->encoder, recorder->buffer, - sizeof(recorder->buffer)); + size_t size = encoder_read(recorder->encoder, recorder->buffer, + sizeof(recorder->buffer)); if (size == 0) return true; /* write everything into the file */ - position = 0; + size_t position = 0; while (true) { - nbytes = write(recorder->fd, recorder->buffer + position, - size - position); + size_t nbytes = write(recorder->fd, + recorder->buffer + position, + size - position); if (nbytes > 0) { position += (size_t)nbytes; if (position >= size) @@ -169,7 +167,6 @@ recorder_output_open(struct audio_output *ao, GError **error_r) { struct recorder_output *recorder = (struct recorder_output *)ao; - bool success; /* create the output file */ @@ -185,8 +182,7 @@ recorder_output_open(struct audio_output *ao, /* open the encoder */ - success = encoder_open(recorder->encoder, audio_format, error_r); - if (!success) { + if (!encoder_open(recorder->encoder, audio_format, error_r)) { close(recorder->fd); unlink(recorder->path); return false; -- cgit v1.2.3 From d34e55c370db54ace2543d9801d360dae8e7c494 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 2 Oct 2012 00:00:56 +0200 Subject: output/recorder: fix write() error check We can only check for negative values if the variable is signed. --- NEWS | 1 + src/output/recorder_output_plugin.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/output') diff --git a/NEWS b/NEWS index 46963f30..a78002e9 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,6 @@ ver 0.17.3 (2012/??/??) * output: + - recorder: fix I/O error check - shout: fix memory leak in error handler ver 0.17.2 (2012/09/30) diff --git a/src/output/recorder_output_plugin.c b/src/output/recorder_output_plugin.c index 5d098f08..e2366bf9 100644 --- a/src/output/recorder_output_plugin.c +++ b/src/output/recorder_output_plugin.c @@ -140,9 +140,9 @@ recorder_output_encoder_to_file(struct recorder_output *recorder, size_t position = 0; while (true) { - size_t nbytes = write(recorder->fd, - recorder->buffer + position, - size - position); + ssize_t nbytes = write(recorder->fd, + recorder->buffer + position, + size - position); if (nbytes > 0) { position += (size_t)nbytes; if (position >= size) -- cgit v1.2.3 From 58e600f408bed5cfdc9b3cebded108a8593e5b7b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 1 Oct 2012 23:59:50 +0200 Subject: output/recorder: move code to _write_to_file() --- src/output/recorder_output_plugin.c | 50 +++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'src/output') diff --git a/src/output/recorder_output_plugin.c b/src/output/recorder_output_plugin.c index e2366bf9..ac4a5210 100644 --- a/src/output/recorder_output_plugin.c +++ b/src/output/recorder_output_plugin.c @@ -120,32 +120,22 @@ recorder_output_finish(struct audio_output *ao) g_free(recorder); } -/** - * Writes pending data from the encoder to the output file. - */ static bool -recorder_output_encoder_to_file(struct recorder_output *recorder, - GError **error_r) +recorder_write_to_file(struct recorder_output *recorder, + const void *_data, size_t length, + GError **error_r) { - assert(recorder->fd >= 0); + assert(length > 0); - /* read from the encoder */ + const int fd = recorder->fd; - size_t size = encoder_read(recorder->encoder, recorder->buffer, - sizeof(recorder->buffer)); - if (size == 0) - return true; - - /* write everything into the file */ + const uint8_t *data = (const uint8_t *)_data, *end = data + length; - size_t position = 0; while (true) { - ssize_t nbytes = write(recorder->fd, - recorder->buffer + position, - size - position); + ssize_t nbytes = write(fd, data, end - data); if (nbytes > 0) { - position += (size_t)nbytes; - if (position >= size) + data += nbytes; + if (data == end) return true; } else if (nbytes == 0) { /* shouldn't happen for files */ @@ -161,6 +151,28 @@ recorder_output_encoder_to_file(struct recorder_output *recorder, } } +/** + * Writes pending data from the encoder to the output file. + */ +static bool +recorder_output_encoder_to_file(struct recorder_output *recorder, + GError **error_r) +{ + assert(recorder->fd >= 0); + + /* read from the encoder */ + + size_t size = encoder_read(recorder->encoder, recorder->buffer, + sizeof(recorder->buffer)); + if (size == 0) + return true; + + /* write everything into the file */ + + return recorder_write_to_file(recorder, recorder->buffer, size, + error_r); +} + static bool recorder_output_open(struct audio_output *ao, struct audio_format *audio_format, -- cgit v1.2.3 From adbe8c409a17b85ec10eb131fb81e3da9036dcef Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 1 Oct 2012 23:50:50 +0200 Subject: output/{recorder,shout}: call encoder_read() in a loop This is necessary for Ogg packets that span more than one page. --- NEWS | 1 + src/encoder_plugin.h | 2 ++ src/output/recorder_output_plugin.c | 19 +++++++++++-------- src/output/shout_output_plugin.c | 18 ++++++++++-------- 4 files changed, 24 insertions(+), 16 deletions(-) (limited to 'src/output') diff --git a/NEWS b/NEWS index a78002e9..c08a779e 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ ver 0.17.3 (2012/??/??) * output: - recorder: fix I/O error check - shout: fix memory leak in error handler + - recorder, shout: support Ogg packets that span more than one page ver 0.17.2 (2012/09/30) * protocol: diff --git a/src/encoder_plugin.h b/src/encoder_plugin.h index cae0c804..3a42d79f 100644 --- a/src/encoder_plugin.h +++ b/src/encoder_plugin.h @@ -295,6 +295,8 @@ encoder_write(struct encoder *encoder, const void *data, size_t length, /** * Reads encoded data from the encoder. * + * Call this repeatedly until no more data is returned. + * * @param encoder the encoder * @param dest the destination buffer to copy to * @param length the maximum length of the destination buffer diff --git a/src/output/recorder_output_plugin.c b/src/output/recorder_output_plugin.c index ac4a5210..b84cb244 100644 --- a/src/output/recorder_output_plugin.c +++ b/src/output/recorder_output_plugin.c @@ -160,17 +160,20 @@ recorder_output_encoder_to_file(struct recorder_output *recorder, { assert(recorder->fd >= 0); - /* read from the encoder */ + while (true) { + /* read from the encoder */ - size_t size = encoder_read(recorder->encoder, recorder->buffer, - sizeof(recorder->buffer)); - if (size == 0) - return true; + size_t size = encoder_read(recorder->encoder, recorder->buffer, + sizeof(recorder->buffer)); + if (size == 0) + return true; - /* write everything into the file */ + /* write everything into the file */ - return recorder_write_to_file(recorder, recorder->buffer, size, - error_r); + if (!recorder_write_to_file(recorder, recorder->buffer, size, + error_r)) + return false; + } } static bool diff --git a/src/output/shout_output_plugin.c b/src/output/shout_output_plugin.c index 63f1001b..56456a0e 100644 --- a/src/output/shout_output_plugin.c +++ b/src/output/shout_output_plugin.c @@ -342,14 +342,16 @@ write_page(struct shout_data *sd, GError **error) { assert(sd->encoder != NULL); - size_t nbytes = encoder_read(sd->encoder, - sd->buffer, sizeof(sd->buffer)); - if (nbytes == 0) - return true; - - int err = shout_send(sd->shout_conn, sd->buffer, nbytes); - if (!handle_shout_error(sd, err, error)) - return false; + while (true) { + size_t nbytes = encoder_read(sd->encoder, + sd->buffer, sizeof(sd->buffer)); + if (nbytes == 0) + return true; + + int err = shout_send(sd->shout_conn, sd->buffer, nbytes); + if (!handle_shout_error(sd, err, error)) + return false; + } return true; } -- cgit v1.2.3