static gboolean xmms_asf_handle_tag_old_tracknr (xmms_xform_t *xform, const gchar *key, const gchar *value, gsize length) { gint ivalue; /* WM/TrackNumber overrides WM/Track value as specified in the Microsoft * documentation at http://msdn2.microsoft.com/en-us/library/aa392014.aspx * so lets check if something else has set the tracknr property before us. */ if (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, &ivalue)) { return FALSE; } /* Ok, nothing set, lets handle "WM/Track" as "WM/TrackNumber" */ if (!xmms_xform_metadata_mapper_match (xform, "WM/TrackNumber", value, length)) { return FALSE; } /* Last quirk, WM/Track is 0-indexed, need to fix that */ xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, &ivalue); xmms_xform_metadata_set_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, ivalue + 1); return TRUE; }
static gboolean xmms_metadata_test_xform_init (xmms_xform_t *xform) { const gchar *musicbrainz_va_id = "89ad4ac3-39f7-470e-963a-56509c546377"; const gchar *title, *rpgain; gint track, compilation; CU_ASSERT_FALSE (xmms_xform_metadata_mapper_match (xform, "missing", "missing", -1)); /* Basic string mapping */ CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "title", "the title", -1)); CU_ASSERT_TRUE (xmms_xform_metadata_get_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TITLE, &title)); CU_ASSERT_STRING_EQUAL ("the title", title); /* Mapping track number, without total tracks */ CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "tracknr", "1", -1)); CU_ASSERT_TRUE (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, &track)); CU_ASSERT_EQUAL (1, track); /* Broken track number */ CU_ASSERT_FALSE (xmms_xform_metadata_mapper_match (xform, "tracknr", "bad", -1)); /* Mapping compilation indicator to boolean compilation */ CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "compilation", "1", -1)); CU_ASSERT_TRUE (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_COMPILATION, &compilation)); CU_ASSERT_EQUAL (TRUE, compilation); /* Mapping compilation indicator to boolean compilation */ CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "compilation", musicbrainz_va_id, -1)); CU_ASSERT_TRUE (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_COMPILATION, &compilation)); CU_ASSERT_EQUAL (TRUE, compilation); /* Mapping replaygain to the format the replaygain xform expects */ CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "replaygain_track_gain", "-14.69", -1)); CU_ASSERT_TRUE (xmms_xform_metadata_get_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK, &rpgain)); CU_ASSERT_STRING_EQUAL ("0.18428", rpgain); CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "replaygain_track_gain", "-14.69 dB", -1)); CU_ASSERT_TRUE (xmms_xform_metadata_get_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK, &rpgain)); CU_ASSERT_STRING_EQUAL ("0.18428", rpgain); CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "coverart", "test", 10)); xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_END); return TRUE; }
static void xmms_wave_get_media_info (xmms_xform_t *xform) { xmms_wave_data_t *data; gdouble playtime; guint samples_total, bitrate; gint filesize; const gchar *metakey; g_return_if_fail (xform); data = xmms_xform_private_data_get (xform); g_return_if_fail (data); samples_total = data->bytes_total / (data->bits_per_sample / 8); playtime = (gdouble) samples_total / data->samplerate / data->channels; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, playtime * 1000); } bitrate = data->bits_per_sample * data->samplerate / data->channels; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, bitrate); }
static void xmms_mpc_cache_streaminfo (xmms_xform_t *xform) { xmms_mpc_data_t *data; gint bitrate, duration, filesize; gchar buf[8]; const gchar *metakey; g_return_if_fail (xform); data = xmms_xform_private_data_get (xform); g_return_if_fail (data); XMMS_DBG ("stream version = %d", data->info.stream_version); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { duration = mpc_streaminfo_get_length (&data->info) * 1000; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, duration); } bitrate = (data->info.bitrate) ? data->info.bitrate : data->info.average_bitrate; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, bitrate); if (data->info.gain_album) { g_snprintf (buf, sizeof (buf), "%f", xmms_mpc_normalize_gain ((gdouble) data->info.gain_album)); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_ALBUM; xmms_xform_metadata_set_str (xform, metakey, buf); } if (data->info.gain_title) { g_snprintf (buf, sizeof (buf), "%f", xmms_mpc_normalize_gain ((gdouble) data->info.gain_title)); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK; xmms_xform_metadata_set_str (xform, metakey, buf); } if (data->info.peak_album) { g_snprintf (buf, sizeof (buf), "%f", xmms_mpc_normalize_peak ((gdouble) data->info.peak_album)); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_PEAK_ALBUM; xmms_xform_metadata_set_str (xform, metakey, buf); } if (data->info.peak_title) { g_snprintf (buf, sizeof (buf), "%f", xmms_mpc_normalize_peak ((gdouble) data->info.peak_title)); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_PEAK_TRACK; xmms_xform_metadata_set_str (xform, metakey, buf); } }
static gboolean xmms_id3v2_init (xmms_xform_t *xform) { xmms_id3v2_data_t *data; xmms_id3v2_header_t head; xmms_error_t err; guchar hbuf[20]; gint filesize; guchar *buf; gint res; const gchar *metakey; xmms_error_reset (&err); if (xmms_xform_read (xform, hbuf, 10, &err) != 10) { XMMS_DBG ("Couldn't read id3v2 header..."); return FALSE; } data = g_new0 (xmms_id3v2_data_t, 1); xmms_xform_private_data_set (xform, data); if (!xmms_id3v2_is_header (hbuf, &head)) { XMMS_DBG ("Couldn't parse id3v2 header!?"); return FALSE; } /* Total data length is the length of header data plus header bytes */ data->len = head.len + 10; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; xmms_xform_metadata_set_int (xform, metakey, filesize - head.len); } buf = g_malloc (head.len); res = xmms_xform_read (xform, buf, head.len, &err); if (res != head.len) { XMMS_DBG ("Couldn't read id3v2 %d bytes of id3-data data (%d)", head.len, res); return FALSE; } xmms_id3v2_parse (xform, buf, &head); g_free (buf); xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "application/octet-stream", XMMS_STREAM_TYPE_END); return TRUE; }
int CSourceAdapter::GetSize () { const gchar *metakey; gint32 size = -1; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; xmms_xform_metadata_get_int (xform, metakey, &size); return size; }
static sf_count_t xmms_sf_virtual_get_filelen (void *priv) { xmms_xform_t *xform = priv; gint filesize = 0; /* Return length 0 in case of failure. */ xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE, &filesize); return filesize; }
static uint32_t wavpack_get_length (void *id) { xmms_xform_t *xform = id; gint filesize; const gchar *metakey; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (!xmms_xform_metadata_get_int (xform, metakey, &filesize)) { filesize = 0; } return filesize; }
static FLAC__StreamDecoderLengthStatus flac_callback_length (const FLAC__StreamDecoder *flacdecoder, FLAC__uint64 *stream_length, void *client_data) { xmms_xform_t *xform = (xmms_xform_t *) client_data; const gchar *metakey; gint val; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &val)) { *stream_length = val; return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; } return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; }
static mpc_int32_t xmms_mpc_callback_get_size (READER_OBJ *p_obj) { xmms_xform_t *xform = READER_DATA (p_obj); const gchar *metakey; gint ret; g_return_val_if_fail (xform, -1); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &ret)) { return ret; } return -1; }
static gint64 xmms_gme_seek (xmms_xform_t *xform, gint64 samples, xmms_xform_seek_mode_t whence, xmms_error_t *err) { xmms_gme_data_t *data; gint64 target_time; gint duration; int samplerate; g_return_val_if_fail (whence == XMMS_XFORM_SEEK_SET, -1); g_return_val_if_fail (xform, -1); data = (xmms_gme_data_t *) xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); samplerate = data->samplerate; if (samples < 0) { xmms_error_set (err, XMMS_ERROR_INVAL, "Trying to seek before start of stream"); return -1; } target_time = (samples / samplerate) * 1000; xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION, &duration); if (target_time > duration) { xmms_error_set (err, XMMS_ERROR_INVAL, "Trying to seek past end of stream"); return -1; } gme_seek (data->emu, target_time); return (gme_tell (data->emu) / 1000) * samplerate; }
static void xmms_faad_get_mediainfo (xmms_xform_t *xform) { xmms_faad_data_t *data; const gchar *metakey; g_return_if_fail (xform); data = xmms_xform_private_data_get (xform); g_return_if_fail (data); if (data->filetype == FAAD_TYPE_ADIF) { guint skip_size, bitrate; gint32 duration; skip_size = (data->buffer[4] & 0x80) ? 9 : 0; bitrate = ((guint) (data->buffer[4 + skip_size] & 0x0F) << 19) | ((guint) data->buffer[5 + skip_size] << 11) | ((guint) data->buffer[6 + skip_size] << 3) | ((guint) data->buffer[7 + skip_size] & 0xE0); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, bitrate); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &duration)) { duration = ((float) duration * 8000.f) / ((float) bitrate) + 0.5f; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, duration); } } else if (data->filetype == FAAD_TYPE_ADTS) { gint32 val = faad_mpeg_samplerates[(data->buffer[2] & 0x3c) >> 2]; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SAMPLERATE; xmms_xform_metadata_set_int (xform, metakey, val); }
static void xmms_sndfile_get_media_info (xmms_xform_t *xform) { xmms_sndfile_data_t *data; gdouble playtime; guint bitrate; gint filesize = 0, bps = -1; const gchar *metakey, *str; g_return_if_fail (xform); data = xmms_xform_private_data_get (xform); g_return_if_fail (data); playtime = (gdouble) data->sf_info.frames / data->sf_info.samplerate; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, playtime * 1000); } switch (data->sf_info.format) { case SF_FORMAT_PCM_S8: bps = 8; break; case SF_FORMAT_PCM_16: bps = 16; break; case SF_FORMAT_PCM_24: bps = 24; break; case SF_FORMAT_PCM_32: bps = 32; break; case SF_FORMAT_PCM_U8: bps = 8; break; case SF_FORMAT_FLOAT: bps = 32; break; case SF_FORMAT_DOUBLE: bps = 64; break; case SF_FORMAT_ULAW: case SF_FORMAT_ALAW: case SF_FORMAT_IMA_ADPCM: case SF_FORMAT_MS_ADPCM: case SF_FORMAT_GSM610: case SF_FORMAT_VOX_ADPCM: case SF_FORMAT_G721_32: case SF_FORMAT_G723_24: case SF_FORMAT_G723_40: case SF_FORMAT_DWVW_12: case SF_FORMAT_DWVW_16: case SF_FORMAT_DWVW_24: case SF_FORMAT_DWVW_N: case SF_FORMAT_DPCM_8: case SF_FORMAT_DPCM_16: case SF_FORMAT_VORBIS: default: break; } if (bps >= 0) { bitrate = bps * data->sf_info.samplerate / data->sf_info.channels; } else { /* Approximate bitrate for compressed formats from the total file * length and sample rate. */ bitrate = filesize / (data->sf_info.frames / data->sf_info.samplerate); } metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, bitrate); SF2XMMS_META_TRANSCODE (str, data->sndfile, xform, SF_STR_ARTIST, XMMS_MEDIALIB_ENTRY_PROPERTY_ARTIST); SF2XMMS_META_TRANSCODE (str, data->sndfile, xform, SF_STR_ALBUM, XMMS_MEDIALIB_ENTRY_PROPERTY_ALBUM); SF2XMMS_META_TRANSCODE (str, data->sndfile, xform, SF_STR_COMMENT, XMMS_MEDIALIB_ENTRY_PROPERTY_COMMENT); SF2XMMS_META_TRANSCODE (str, data->sndfile, xform, SF_STR_COPYRIGHT, XMMS_MEDIALIB_ENTRY_PROPERTY_COPYRIGHT); SF2XMMS_META_TRANSCODE (str, data->sndfile, xform, SF_STR_DATE, XMMS_MEDIALIB_ENTRY_PROPERTY_YEAR); /* Verify! */ /* SF2XMMS_META_TRANSCODE (str, data->sndfile, xform, SF_STR_LICENSE, XMMS_MEDIALIB_ENTRY_PROPERTY_???); */ /* SF2XMMS_META_TRANSCODE (str, data->sndfile, xform, SF_STR_SOFTWARE, XMMS_MEDIALIB_ENTRY_PROPERTY_???); */ SF2XMMS_META_TRANSCODE (str, data->sndfile, xform, SF_STR_TITLE, XMMS_MEDIALIB_ENTRY_PROPERTY_TITLE); /* We could fetch ID3 tags here as soon as libsndfile will support this - * Erik of libsndfile has to provide the generic chunk handling though. */ }
static gboolean xmms_vorbis_init (xmms_xform_t *xform) { xmms_vorbis_data_t *data; vorbis_info *vi; gint ret; guint playtime; const gchar *metakey; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_vorbis_data_t, 1), data->callbacks.read_func = vorbis_callback_read; data->callbacks.close_func = vorbis_callback_close; data->callbacks.tell_func = vorbis_callback_tell; data->callbacks.seek_func = vorbis_callback_seek; data->current = -1; xmms_xform_private_data_set (xform, data); ret = ov_open_callbacks (xform, &data->vorbisfile, NULL, 0, data->callbacks); if (ret) { return FALSE; } vi = ov_info (&data->vorbisfile, -1); playtime = ov_time_total (&data->vorbisfile, -1); if (playtime != OV_EINVAL) { gint filesize; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { xmms_vorbis_set_duration (xform, playtime); } } if (vi && vi->bitrate_nominal) { metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, (gint) vi->bitrate_nominal); } xmms_vorbis_read_metadata (xform, data); xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_S16, XMMS_STREAM_TYPE_FMT_CHANNELS, vi->channels, XMMS_STREAM_TYPE_FMT_SAMPLERATE, vi->rate, XMMS_STREAM_TYPE_END); return TRUE; }
static gboolean xmms_mad_init (xmms_xform_t *xform) { struct mad_frame frame; struct mad_stream stream; xmms_error_t err; guchar buf[40960]; xmms_mad_data_t *data; int len; const gchar *metakey; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_mad_data_t, 1); mad_stream_init (&data->stream); mad_frame_init (&data->frame); mad_synth_init (&data->synth); xmms_xform_private_data_set (xform, data); data->buffer_length = 0; data->synthpos = 0x7fffffff; mad_stream_init (&stream); mad_frame_init (&frame); len = xmms_xform_peek (xform, buf, 40960, &err); mad_stream_buffer (&stream, buf, len); while (mad_frame_decode (&frame, &stream) == -1) { if (!MAD_RECOVERABLE (stream.error)) { XMMS_DBG ("couldn't decode %02x %02x %02x %02x",buf[0],buf[1],buf[2],buf[3]); mad_frame_finish (&frame); mad_stream_finish (&stream); return FALSE; } } data->channels = frame.header.mode == MAD_MODE_SINGLE_CHANNEL ? 1 : 2; data->samplerate = frame.header.samplerate; if (frame.header.flags & MAD_FLAG_PROTECTION) { XMMS_DBG ("Frame has protection enabled"); if (stream.anc_ptr.byte > stream.buffer + 2) { stream.anc_ptr.byte = stream.anc_ptr.byte - 2; } } data->samples_to_play = -1; data->xing = xmms_xing_parse (stream.anc_ptr); if (data->xing) { xmms_xing_lame_t *lame; XMMS_DBG ("File with Xing header!"); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_IS_VBR; xmms_xform_metadata_set_int (xform, metakey, 1); if (xmms_xing_has_flag (data->xing, XMMS_XING_FRAMES)) { guint duration; mad_timer_t timer; timer = frame.header.duration; mad_timer_multiply (&timer, xmms_xing_get_frames (data->xing)); duration = mad_timer_count (timer, MAD_UNITS_MILLISECONDS); XMMS_DBG ("XING duration %d", duration); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, duration); if (xmms_xing_has_flag (data->xing, XMMS_XING_BYTES) && duration) { guint tmp; tmp = xmms_xing_get_bytes (data->xing) * ((guint64)8000) / duration; XMMS_DBG ("XING bitrate %d", tmp); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, tmp); } } lame = xmms_xing_get_lame (data->xing); if (lame) { /* FIXME: add a check for ignore_lame_headers from the medialib */ data->frames_to_skip = 1; data->samples_to_skip = lame->start_delay; data->samples_to_play = ((guint64) xmms_xing_get_frames (data->xing) * 1152ULL) - lame->start_delay - lame->end_padding; XMMS_DBG ("Samples to skip in the beginning: %d, total: %" G_GINT64_FORMAT, data->samples_to_skip, data->samples_to_play); /* metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_ALBUM; xmms_xform_metadata_set_int (xform, metakey, lame->audiophile_gain); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_PEAK_TRACK; xmms_xform_metadata_set_int (xform, metakey, lame->peak_amplitude); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK; xmms_xform_metadata_set_int (xform, metakey, lame->radio_gain); */ } } else { gint filesize; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, frame.header.bitrate); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; if (!xmms_xform_metadata_get_int (xform, metakey, &filesize)) { metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { gint32 val; val = (gint32) (filesize * (gdouble) 8000.0 / frame.header.bitrate); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, val); } } } /* seeking needs bitrate */ data->bitrate = frame.header.bitrate; if (xmms_id3v1_get_tags (xform) < 0) { mad_stream_finish (&data->stream); mad_frame_finish (&data->frame); mad_synth_finish (&data->synth); if (data->xing) { xmms_xing_free (data->xing); } return FALSE; } xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_S16, XMMS_STREAM_TYPE_FMT_CHANNELS, data->channels, XMMS_STREAM_TYPE_FMT_SAMPLERATE, data->samplerate, XMMS_STREAM_TYPE_END); mad_frame_finish (&frame); mad_stream_finish (&stream); return TRUE; }
static gboolean xmms_flac_init (xmms_xform_t *xform) { xmms_flac_data_t *data; xmms_sample_format_t sample_fmt; FLAC__bool retval; #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 FLAC__StreamDecoderState init_status; #else FLAC__StreamDecoderInitStatus init_status; #endif gint filesize; const gchar *metakey; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_flac_data_t, 1); xmms_xform_private_data_set (xform, data); data->flacdecoder = FLAC__stream_decoder_new (); /* we don't need to explicitly tell the decoder to respond to * FLAC__METADATA_TYPE_STREAMINFO here, it always does. */ #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 FLAC__seekable_stream_decoder_set_metadata_respond (data->flacdecoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); FLAC__seekable_stream_decoder_set_eof_callback (data->flacdecoder, flac_callback_eof); FLAC__seekable_stream_decoder_set_read_callback (data->flacdecoder, flac_callback_read); FLAC__seekable_stream_decoder_set_seek_callback (data->flacdecoder, flac_callback_seek); FLAC__seekable_stream_decoder_set_tell_callback (data->flacdecoder, flac_callback_tell); FLAC__seekable_stream_decoder_set_write_callback (data->flacdecoder, flac_callback_write); FLAC__seekable_stream_decoder_set_error_callback (data->flacdecoder, flac_callback_error); FLAC__seekable_stream_decoder_set_length_callback (data->flacdecoder, flac_callback_length); FLAC__seekable_stream_decoder_set_metadata_callback (data->flacdecoder, flac_callback_metadata); FLAC__seekable_stream_decoder_set_client_data (data->flacdecoder, xform); init_status = FLAC__seekable_stream_decoder_init (data->flacdecoder); if (init_status != FLAC__SEEKABLE_STREAM_DECODER_OK) { const gchar *errmsg = FLAC__seekable_stream_decoder_get_resolved_state_string (data->flacdecoder); XMMS_DBG ("FLAC init failed: %s", errmsg); goto err; } #else FLAC__stream_decoder_set_metadata_respond (data->flacdecoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); FLAC__stream_decoder_set_metadata_respond (data->flacdecoder, FLAC__METADATA_TYPE_PICTURE); init_status = FLAC__stream_decoder_init_stream (data->flacdecoder, flac_callback_read, flac_callback_seek, flac_callback_tell, flac_callback_length, flac_callback_eof, flac_callback_write, flac_callback_metadata, flac_callback_error, xform); if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { XMMS_DBG ("FLAC init failed: %s", FLAC__stream_decoder_get_resolved_state_string (data->flacdecoder)); goto err; } #endif retval = FLAC__stream_decoder_process_until_end_of_metadata (data->flacdecoder); if (!retval) goto err; if (data->vorbiscomment) { handle_comments (xform, data); } metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, (gint) data->bit_rate); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { gint32 val = (gint32) data->total_samples / data->sample_rate * 1000; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, val); } if (data->bits_per_sample == 8) { sample_fmt = XMMS_SAMPLE_FORMAT_S8; } else if (data->bits_per_sample == 16) { sample_fmt = XMMS_SAMPLE_FORMAT_S16; } else if (data->bits_per_sample == 24) { sample_fmt = XMMS_SAMPLE_FORMAT_S32; } else if (data->bits_per_sample == 32) { sample_fmt = XMMS_SAMPLE_FORMAT_S32; } else { goto err; } xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, sample_fmt, XMMS_STREAM_TYPE_FMT_CHANNELS, data->channels, XMMS_STREAM_TYPE_FMT_SAMPLERATE, data->sample_rate, XMMS_STREAM_TYPE_END); data->buffer = g_string_new (NULL); return TRUE; err: FLAC__stream_decoder_finish (data->flacdecoder); FLAC__stream_decoder_delete (data->flacdecoder); g_free (data); xmms_xform_private_data_set (xform, NULL); return FALSE; }
static void flac_callback_metadata (const FLAC__StreamDecoder *flacdecoder, const FLAC__StreamMetadata *metadata, void *client_data) { xmms_flac_data_t *data; xmms_xform_t *xform = (xmms_xform_t *) client_data; gint32 filesize; const gchar *metakey; g_return_if_fail (xform); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (!xmms_xform_metadata_get_int (xform, metakey, &filesize)) { filesize = -1; } data = xmms_xform_private_data_get (xform); switch (metadata->type) { case FLAC__METADATA_TYPE_STREAMINFO: /* FLAC__metadata_object_clone ()? */ data->bits_per_sample = metadata->data.stream_info.bits_per_sample; data->sample_rate = metadata->data.stream_info.sample_rate; data->channels = metadata->data.stream_info.channels; data->total_samples = metadata->data.stream_info.total_samples; if (filesize > 0 && data->total_samples) { data->bit_rate = (guint) ((guint64) filesize * 8 * (guint64) data->sample_rate / (guint64) data->total_samples); } XMMS_DBG ("STREAMINFO: BPS %d. Samplerate: %d. Channels: %d.", data->bits_per_sample, data->sample_rate, data->channels); break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: data->vorbiscomment = FLAC__metadata_object_clone (metadata); break; #if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7 case FLAC__METADATA_TYPE_PICTURE: { gchar hash[33]; if (metadata->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER && xmms_bindata_plugin_add (metadata->data.picture.data, metadata->data.picture.data_length, hash)) { const gchar *metakey; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_PICTURE_FRONT; xmms_xform_metadata_set_str (xform, metakey, hash); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_PICTURE_FRONT_MIME; xmms_xform_metadata_set_str (xform, metakey, metadata->data.picture.mime_type); } break; } #endif /* if we want to support more metadata types here, * don't forget to add a call to * FLAC__stream_decoder_set_metadata_respond() below. */ default: break; } }
static gboolean xmms_modplug_init (xmms_xform_t *xform) { xmms_modplug_data_t *data; const gchar *metakey; gint filesize; xmms_config_property_t *cfgv; gint i; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_modplug_data_t, 1); xmms_xform_private_data_set (xform, data); for (i = 0; i < G_N_ELEMENTS (config_params); i++) { cfgv = xmms_xform_config_lookup (xform, config_params[i].key); xmms_config_property_callback_set (cfgv, xmms_modplug_config_changed, data); xmms_modplug_config_changed (XMMS_OBJECT (cfgv), NULL, data); } /* mFrequency and mResamplingMode are set in config_changed */ data->settings.mChannels = 2; data->settings.mBits = 16; ModPlug_SetSettings (&data->settings); xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_S16, XMMS_STREAM_TYPE_FMT_CHANNELS, 2, XMMS_STREAM_TYPE_FMT_SAMPLERATE, data->settings.mFrequency, XMMS_STREAM_TYPE_END); data->buffer = g_string_new (""); for (;;) { xmms_error_t error; gchar buf[4096]; gint ret; ret = xmms_xform_read (xform, buf, sizeof (buf), &error); if (ret == -1) { XMMS_DBG ("Error reading mod"); return FALSE; } if (ret == 0) { break; } g_string_append_len (data->buffer, buf, ret); } data->mod = ModPlug_Load (data->buffer->str, data->buffer->len); if (!data->mod) { XMMS_DBG ("Error loading mod"); return FALSE; } metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, ModPlug_GetLength (data->mod)); } metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_TITLE; xmms_xform_metadata_set_str (xform, metakey, ModPlug_GetName (data->mod)); return TRUE; }
static gboolean xmms_opus_init (xmms_xform_t *xform) { xmms_opus_data_t *data; gint ret; guint playtime; const gchar *metakey; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_opus_data_t, 1), data->callbacks.read = opus_callback_read; data->callbacks.close = opus_callback_close; data->callbacks.tell = opus_callback_tell; data->callbacks.seek = opus_callback_seek; data->current = -1; xmms_xform_private_data_set (xform, data); data->opusfile = op_open_callbacks (xform, &data->callbacks, NULL, 0, &ret); if (ret) { return FALSE; } playtime = op_pcm_total (data->opusfile, -1) / 48000; if (playtime != OP_EINVAL) { gint filesize; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { xmms_opus_set_duration (xform, playtime); } } xmms_opus_read_metadata (xform, data); /* xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_FLOAT, XMMS_STREAM_TYPE_FMT_CHANNELS, data->channels, XMMS_STREAM_TYPE_FMT_SAMPLERATE, 48000, XMMS_STREAM_TYPE_END); */ xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_S16, XMMS_STREAM_TYPE_FMT_CHANNELS, data->channels, XMMS_STREAM_TYPE_FMT_SAMPLERATE, 48000, XMMS_STREAM_TYPE_END); return TRUE; }
static gboolean xmms_mpg123_init (xmms_xform_t *xform) { xmms_mpg123_data_t *data; const long *rates; size_t num_rates; int encoding; off_t length; int i, result; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_mpg123_data_t, 1); xmms_xform_private_data_set (xform, data); /* Get the total size of this stream and store it for later */ if (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE, &result)) { data->filesize = result; } mpg123_rates (&rates, &num_rates); data->param = mpg123_new_pars (&result); g_return_val_if_fail (data->param, FALSE); /* Create a quiet (stderr) decoder with auto choosen optimization. * Stuff set here should be tunable via plugin config properties! * You can also change some things during playback... */ mpg123_par (data->param, MPG123_ADD_FLAGS, MPG123_QUIET, 0); mpg123_par (data->param, MPG123_ADD_FLAGS, MPG123_GAPLESS, 0); /* choose: MPG123_RVA_OFF, MPG123_RVA_MIX, MPG123_RVA_ALBUM * xmms2 has its own ReplayGain plugin to handle the RVA field */ mpg123_par (data->param, MPG123_RVA, MPG123_RVA_OFF, 0); /* You could choose a decoder from the list provided by * mpg123_supported_decoders () and give that as second parameter. */ data->decoder = mpg123_parnew (data->param, NULL, &result); if (data->decoder == NULL) { xmms_log_error ("%s", mpg123_plain_strerror (result)); goto bad; } /* Prepare for buffer input feeding. */ result = mpg123_open_feed (data->decoder); if (result != MPG123_OK) { goto mpg123_bad; } /* Let's always decode to signed 16bit for a start. Any mpg123-supported sample rate is accepted. */ if (MPG123_OK != mpg123_format_none (data->decoder)) { goto mpg123_bad; } for (i = 0; i < num_rates; i++) { result = mpg123_format (data->decoder, rates[i], MPG123_MONO | MPG123_STEREO, MPG123_ENC_SIGNED_16); if (result != MPG123_OK) { goto mpg123_bad; } } /* Fetch ID3v1 data from the end of file if possible */ result = xmms_id3v1_get_tags (xform); if (result < 0) { xmms_log_error ("Seeking error when reading ID3v1 tags"); goto bad; } else if (data->filesize > result) { /* Reduce the size of tag data from the filesize */ data->filesize -= result; } /* Read data from input until decoded data is available from decoder */ do { /* Parse stream and get info. */ gint ret; xmms_error_t err; ret = xmms_xform_read (xform, data->buf, BUFSIZE, &err); if (ret < 0) { xmms_log_error ("Error when trying to find beginning of stream"); goto bad; } else if (ret == 0) { /* EOF reached before format was found, handled after loop */ break; } /* With zero output size nothing is actually outputted */ result = mpg123_decode (data->decoder, data->buf, (size_t) ret, NULL, 0, NULL); } while (result == MPG123_NEED_MORE); /* Keep feeding... */ if (result != MPG123_NEW_FORMAT) { xmms_log_error ("Unable to find beginning of stream (%s)!", result == MPG123_ERR ? mpg123_strerror (data->decoder) : "unexpected EOF"); goto bad; } result = mpg123_getformat (data->decoder, &data->samplerate, &data->channels, &encoding); if (result != MPG123_OK) { goto mpg123_bad; } /* Set the filesize so it can be used for duration estimation */ if (data->filesize > 0) { mpg123_set_filesize (data->decoder, data->filesize); } /* Get duration in samples, convert to ms and save to xmms2 */ length = mpg123_length (data->decoder); if (length > 0 && !xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION, &i)) { length = (off_t) ((gfloat) length / data->samplerate * 1000); xmms_xform_metadata_set_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION, (gint) length); } XMMS_DBG ("mpg123: got stream with %li Hz %i channels, encoding %i", data->samplerate, data->channels, encoding); xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_S16, XMMS_STREAM_TYPE_FMT_CHANNELS, data->channels, XMMS_STREAM_TYPE_FMT_SAMPLERATE, (gint) data->samplerate, XMMS_STREAM_TYPE_END); return TRUE; mpg123_bad: xmms_log_error ("mpg123 error: %s", mpg123_strerror (data->decoder)); bad: mpg123_delete (data->decoder); mpg123_delete_pars (data->param); g_free (data); return FALSE; }