diff options
Diffstat (limited to 'src/output/shout_ogg.c')
-rw-r--r-- | src/output/shout_ogg.c | 293 |
1 files changed, 0 insertions, 293 deletions
diff --git a/src/output/shout_ogg.c b/src/output/shout_ogg.c deleted file mode 100644 index 8b769e8c0..000000000 --- a/src/output/shout_ogg.c +++ /dev/null @@ -1,293 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "shout_plugin.h" - -#include <vorbis/vorbisenc.h> -#include <stdlib.h> - -struct ogg_vorbis_data { - ogg_stream_state os; - ogg_page og; - ogg_packet op; - ogg_packet header_main; - ogg_packet header_comments; - ogg_packet header_codebooks; - - vorbis_dsp_state vd; - vorbis_block vb; - vorbis_info vi; - vorbis_comment vc; -}; - -static void add_tag(struct ogg_vorbis_data *od, const char *name, char *value) -{ - if (value) { - union { - const char *in; - char *out; - } u = { .in = name }; - vorbis_comment_add_tag(&od->vc, u.out, value); - } -} - -static void copy_tag_to_vorbis_comment(struct shout_data *sd) -{ - struct ogg_vorbis_data *od = (struct ogg_vorbis_data *)sd->encoder_data; - - if (sd->tag) { - int i; - - for (i = 0; i < sd->tag->numOfItems; i++) { - switch (sd->tag->items[i]->type) { - case TAG_ITEM_ARTIST: - add_tag(od, "ARTIST", sd->tag->items[i]->value); - break; - case TAG_ITEM_ALBUM: - add_tag(od, "ALBUM", sd->tag->items[i]->value); - break; - case TAG_ITEM_TITLE: - add_tag(od, "TITLE", sd->tag->items[i]->value); - break; - - default: - break; - } - } - } -} - -static int copy_ogg_buffer_to_shout_buffer(ogg_page *og, - struct shout_buffer *buf) -{ - if ((size_t)og->header_len + (size_t)og->body_len > sizeof(buf->data)) { - g_warning("%s: not enough buffer space!\n", __func__); - return -1; - } - - memcpy(buf->data, og->header, og->header_len); - memcpy(buf->data + og->header_len, og->body, og->body_len); - buf->len = og->header_len + og->body_len; - - return 0; -} - -static int flush_ogg_buffer(struct shout_data *sd) -{ - struct shout_buffer *buf = &sd->buf; - struct ogg_vorbis_data *od = (struct ogg_vorbis_data *)sd->encoder_data; - int ret = 0; - - if (ogg_stream_flush(&od->os, &od->og)) - ret = copy_ogg_buffer_to_shout_buffer(&od->og, buf); - - return ret; -} - -static int send_ogg_vorbis_header(struct shout_data *sd) -{ - struct ogg_vorbis_data *od = (struct ogg_vorbis_data *)sd->encoder_data; - - vorbis_analysis_headerout(&od->vd, &od->vc, - &od->header_main, - &od->header_comments, - &od->header_codebooks); - - ogg_stream_packetin(&od->os, &od->header_main); - ogg_stream_packetin(&od->os, &od->header_comments); - ogg_stream_packetin(&od->os, &od->header_codebooks); - - return flush_ogg_buffer(sd); -} - -static void finish_encoder(struct ogg_vorbis_data *od) -{ - vorbis_analysis_wrote(&od->vd, 0); - - while (vorbis_analysis_blockout(&od->vd, &od->vb) == 1) { - vorbis_analysis(&od->vb, NULL); - vorbis_bitrate_addblock(&od->vb); - while (vorbis_bitrate_flushpacket(&od->vd, &od->op)) { - ogg_stream_packetin(&od->os, &od->op); - } - } -} - -static int shout_ogg_encoder_clear_encoder(struct shout_data *sd) -{ - struct ogg_vorbis_data *od = (struct ogg_vorbis_data *)sd->encoder_data; - int ret; - - finish_encoder(od); - if ((ret = ogg_stream_pageout(&od->os, &od->og))) - copy_ogg_buffer_to_shout_buffer(&od->og, &sd->buf); - - vorbis_comment_clear(&od->vc); - ogg_stream_clear(&od->os); - vorbis_block_clear(&od->vb); - vorbis_dsp_clear(&od->vd); - vorbis_info_clear(&od->vi); - - return ret; -} - -static void shout_ogg_encoder_finish(struct shout_data *sd) -{ - struct ogg_vorbis_data *od = (struct ogg_vorbis_data *)sd->encoder_data; - - if (od) { - free(od); - sd->encoder_data = NULL; - } -} - -static int shout_ogg_encoder_init(struct shout_data *sd) -{ - struct ogg_vorbis_data *od = g_new(struct ogg_vorbis_data, 1); - - sd->encoder_data = od; - - return 0; -} - -static int reinit_encoder(struct shout_data *sd) -{ - struct ogg_vorbis_data *od = (struct ogg_vorbis_data *)sd->encoder_data; - - vorbis_info_init(&od->vi); - - if (sd->quality >= -1.0) { - if (0 != vorbis_encode_init_vbr(&od->vi, - sd->audio_format.channels, - sd->audio_format.sample_rate, - sd->quality * 0.1)) { - g_warning("error initializing vorbis vbr\n"); - vorbis_info_clear(&od->vi); - return -1; - } - } else { - if (0 != vorbis_encode_init(&od->vi, - sd->audio_format.channels, - sd->audio_format.sample_rate, -1.0, - sd->bitrate * 1000, -1.0)) { - g_warning("error initializing vorbis encoder\n"); - vorbis_info_clear(&od->vi); - return -1; - } - } - - vorbis_analysis_init(&od->vd, &od->vi); - vorbis_block_init(&od->vd, &od->vb); - ogg_stream_init(&od->os, rand()); - vorbis_comment_init(&od->vc); - - return 0; -} - -static int shout_ogg_encoder_init_encoder(struct shout_data *sd) -{ - if (reinit_encoder(sd)) - return -1; - - if (send_ogg_vorbis_header(sd)) { - g_warning("error sending ogg vorbis header for shout\n"); - return -1; - } - - return 0; -} - -static int shout_ogg_encoder_send_metadata(struct shout_data *sd, - G_GNUC_UNUSED char * song, - G_GNUC_UNUSED size_t size) -{ - struct ogg_vorbis_data *od = (struct ogg_vorbis_data *)sd->encoder_data; - - shout_ogg_encoder_clear_encoder(sd); - if (reinit_encoder(sd)) - return 0; - - copy_tag_to_vorbis_comment(sd); - - vorbis_analysis_headerout(&od->vd, &od->vc, - &od->header_main, - &od->header_comments, - &od->header_codebooks); - - ogg_stream_packetin(&od->os, &od->header_main); - ogg_stream_packetin(&od->os, &od->header_comments); - ogg_stream_packetin(&od->os, &od->header_codebooks); - - flush_ogg_buffer(sd); - - return 0; -} - -static void -pcm16_to_ogg_buffer(float **dest, const int16_t *src, - unsigned num_samples, unsigned num_channels) -{ - for (unsigned i = 0; i < num_samples; i++) - for (unsigned j = 0; j < num_channels; j++) - dest[j][i] = *src++ / 32768.0; -} - -static int -shout_ogg_encoder_encode(struct shout_data *sd, - const void *chunk, size_t size) -{ - struct shout_buffer *buf = &sd->buf; - unsigned int samples; - struct ogg_vorbis_data *od = (struct ogg_vorbis_data *)sd->encoder_data; - - samples = size / audio_format_frame_size(&sd->audio_format); - - /* this is for only 16-bit audio */ - - pcm16_to_ogg_buffer(vorbis_analysis_buffer(&od->vd, samples), - (const int16_t *)chunk, - samples, sd->audio_format.channels); - - vorbis_analysis_wrote(&od->vd, samples); - - while (1 == vorbis_analysis_blockout(&od->vd, &od->vb)) { - vorbis_analysis(&od->vb, NULL); - vorbis_bitrate_addblock(&od->vb); - - while (vorbis_bitrate_flushpacket(&od->vd, &od->op)) { - ogg_stream_packetin(&od->os, &od->op); - } - } - - if (ogg_stream_pageout(&od->os, &od->og)) - copy_ogg_buffer_to_shout_buffer(&od->og, buf); - - return 0; -} - -const struct shout_encoder_plugin shout_ogg_encoder = { - "ogg", - SHOUT_FORMAT_VORBIS, - - shout_ogg_encoder_clear_encoder, - shout_ogg_encoder_encode, - shout_ogg_encoder_finish, - shout_ogg_encoder_init, - shout_ogg_encoder_init_encoder, - shout_ogg_encoder_send_metadata, -}; |