Пример #1
0
static gboolean
xmms_icymetaint_init (xmms_xform_t *xform)
{
	xmms_icymetaint_data_t *data;
	gint32 meta_offset;
	gboolean res;

	g_return_val_if_fail (xform, FALSE);

	res = xmms_xform_auxdata_get_int (xform, "meta_offset", &meta_offset);
	g_return_val_if_fail (res, FALSE);

	XMMS_DBG ("meta_offset = %d", meta_offset);

	data = g_new0 (xmms_icymetaint_data_t, 1);

	data->metabuffer = g_malloc (256 * 16);
	data->meta_offset = meta_offset;

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "application/octet-stream",
	                             XMMS_STREAM_TYPE_END);

	xmms_xform_private_data_set (xform, data);

	return TRUE;
}
Пример #2
0
static gboolean
xmms_normalize_init (xmms_xform_t *xform)
{
	xmms_config_property_t *cfgv;
	xmms_normalize_data_t *data;
	int i;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_normalize_data_t, 1);

	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_normalize_config_changed,
		                                   data);

		xmms_normalize_config_changed (XMMS_OBJECT (cfgv), NULL, data);
	}

	xmms_xform_outdata_type_copy (xform);

	data->dirty = FALSE;

	data->compress = compress_new (data->use_anticlip,
	                               data->target,
	                               data->max_gain,
	                               data->smooth,
	                               data->buckets);

	xmms_xform_private_data_set (xform, data);

	return TRUE;
}
Пример #3
0
static gboolean
xmms_converter_plugin_init (xmms_xform_t *xform)
{
	xmms_conv_xform_data_t *data;
	xmms_sample_converter_t *conv;
	xmms_stream_type_t *intype;
	xmms_stream_type_t *to;
	const GList *goal_hints;

	intype = xmms_xform_intype_get (xform);
	goal_hints = xmms_xform_goal_hints_get (xform);

	to = xmms_stream_type_coerce (intype, goal_hints);
	if (!to) {
		return FALSE;
	}

	conv = xmms_sample_converter_init (intype, to);
	if (!conv) {
		return FALSE;
	}

	xmms_xform_outdata_type_set (xform, to);
	xmms_object_unref (to);

	data = g_new0 (xmms_conv_xform_data_t, 1);
	data->conv = conv;

	xmms_xform_private_data_set (xform, data);

	return TRUE;
}
Пример #4
0
static gboolean
xmms_ringbuf_plugin_init (xmms_xform_t *xform)
{
	xmms_config_property_t *config;
	xmms_ringbuf_priv_t *priv;
	gint buffer_size;

	priv = g_new0 (xmms_ringbuf_priv_t, 1);

	xmms_xform_private_data_set (xform, priv);

	config = xmms_xform_config_lookup (xform, "buffersize");
	buffer_size = xmms_config_property_get_int (config);

	g_cond_init (&priv->state_cond);
	g_mutex_init (&priv->state_lock);
	g_mutex_init (&priv->buffer_lock);

	priv->state = STATE_WANT_BUFFER;
	priv->buffer = xmms_ringbuf_new (MAX (4096, buffer_size));

	priv->thread = g_thread_new ("x2 ringbuf", xmms_ringbuf_xform_thread, xform);

	xmms_xform_outdata_type_copy (xform);

	return TRUE;
}
Пример #5
0
static gboolean
xmms_vocoder_init (xmms_xform_t *xform)
{
	xmms_vocoder_data_t *priv;
	xmms_config_property_t *config;

	g_return_val_if_fail (xform, FALSE);

	priv = g_new0 (xmms_vocoder_data_t, 1);
	priv->winsize = 2048;
	priv->channels = xmms_xform_indata_get_int (xform, XMMS_STREAM_TYPE_FMT_CHANNELS);
	priv->bufsize = priv->winsize * priv->channels;

	priv->iobuf = g_malloc (priv->bufsize * sizeof (gint16));
	priv->procbuf = g_malloc (priv->bufsize * sizeof (pvocoder_sample_t));
	priv->resbuf = g_malloc (priv->bufsize * sizeof (gfloat));
	priv->outbuf = g_string_new (NULL);

	priv->pvoc = pvocoder_init (priv->winsize, priv->channels);
	g_return_val_if_fail (priv->pvoc, FALSE);

	priv->resampler = src_new (SRC_LINEAR, priv->channels, NULL);
	g_return_val_if_fail (priv->resampler, FALSE);

	xmms_xform_private_data_set (xform, priv);

	config = xmms_xform_config_lookup (xform, "enabled");
	g_return_val_if_fail (config, FALSE);
	xmms_config_property_callback_set (config, xmms_vocoder_config_changed, priv);
	priv->enabled = !!xmms_config_property_get_int (config);

	config = xmms_xform_config_lookup (xform, "speed");
	g_return_val_if_fail (config, FALSE);
	xmms_config_property_callback_set (config, xmms_vocoder_config_changed, priv);
	priv->speed = (gfloat) xmms_config_property_get_int (config) / 100.0;

	config = xmms_xform_config_lookup (xform, "pitch");
	g_return_val_if_fail (config, FALSE);
	xmms_config_property_callback_set (config, xmms_vocoder_config_changed, priv);
	priv->pitch = 100.0 / (gfloat) xmms_config_property_get_int (config);

	config = xmms_xform_config_lookup (xform, "attack_detection");
	g_return_val_if_fail (config, FALSE);
	xmms_config_property_callback_set (config, xmms_vocoder_config_changed, priv);
	priv->attack_detection = !!xmms_config_property_get_int (config);

	pvocoder_set_scale (priv->pvoc, priv->speed * priv->pitch);
	pvocoder_set_attack_detection (priv->pvoc, priv->attack_detection);

	priv->resdata.data_in = NULL;
	priv->resdata.input_frames = 0;
	priv->resdata.data_out = priv->resbuf;
	priv->resdata.output_frames = priv->winsize;
	priv->resdata.src_ratio = priv->pitch;
	priv->resdata.end_of_input = 0;

	xmms_xform_outdata_type_copy (xform);

	return TRUE;
}
Пример #6
0
static gboolean
xmms_mpc_init (xmms_xform_t *xform)
{
    xmms_mpc_data_t *data;
    xmms_error_t error;

    data = g_new0 (xmms_mpc_data_t, 1);
    xmms_xform_private_data_set (xform, data);

    if (!xmms_apetag_read (xform)) {
        XMMS_DBG ("Failed to read APEv2 tag");
    }

    /* Reset to start after reading the tags */
    xmms_error_reset (&error);
    xmms_xform_seek (xform, 0, XMMS_XFORM_SEEK_SET, &error);

    data->buffer = g_string_new (NULL);

    data->reader.read = xmms_mpc_callback_read;
    data->reader.seek = xmms_mpc_callback_seek;
    data->reader.tell = xmms_mpc_callback_tell;
    data->reader.canseek = xmms_mpc_callback_canseek;
    data->reader.get_size = xmms_mpc_callback_get_size;

    data->reader.data = xform;

#ifdef HAVE_MPCDEC_OLD
    mpc_streaminfo_init (&data->info);
    if (mpc_streaminfo_read (&data->info, &data->reader) != ERROR_CODE_OK)
        return FALSE;

    mpc_decoder_setup (&data->decoder, &data->reader);

    if (mpc_decoder_initialize (&data->decoder, &data->info) == FALSE)
        return FALSE;
#else
    data->demux = mpc_demux_init (&data->reader);
    if (!data->demux) return FALSE;

    mpc_demux_get_info (data->demux,  &data->info);
#endif

    xmms_mpc_cache_streaminfo (xform);

    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->info.channels,
                                 XMMS_STREAM_TYPE_FMT_SAMPLERATE,
                                 data->info.sample_freq,
                                 XMMS_STREAM_TYPE_END);

    return TRUE;
}
Пример #7
0
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;
}
Пример #8
0
/*
 * Member functions
 */
static gboolean
xmms_samba_init (xmms_xform_t *xform)
{
	xmms_samba_data_t *data;
	const gchar *url;
	const gchar *metakey;
	struct stat st;
	gint fd, err;

	g_return_val_if_fail (xform, FALSE);

	url = xmms_xform_indata_get_str (xform, XMMS_STREAM_TYPE_URL);
	g_return_val_if_fail (url, FALSE);

	G_LOCK (mutex);
	err = smbc_stat (url, &st);
	G_UNLOCK (mutex);

	if (err < 0) {
		xmms_log_error ("%s", strerror (errno));
		return FALSE;
	}

	if (!S_ISREG (st.st_mode)) {
		xmms_log_error ("%s is not a regular file.", url);
		return FALSE;
	}

	G_LOCK (mutex);
	fd = smbc_open (url, O_RDONLY | O_NONBLOCK, 0);
	G_UNLOCK (mutex);

	if (fd == -1) {
		xmms_log_error ("%s", strerror (errno));
		return FALSE;
	}

	data = g_new0 (xmms_samba_data_t, 1);
	data->fd = fd;

	xmms_xform_private_data_set (xform, data);

	xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE,
	                             "application/octet-stream",
	                             XMMS_STREAM_TYPE_END);

	metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE;
	xmms_xform_metadata_set_int (xform, metakey, st.st_size);

	metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_LMOD;
	xmms_xform_metadata_set_int (xform, metakey, st.st_mtime);

	return TRUE;
}
Пример #9
0
static gboolean
xmms_mpc_init (xmms_xform_t *xform)
{
	xmms_mpc_data_t *data;

	data = g_new0 (xmms_mpc_data_t, 1);
	xmms_xform_private_data_set (xform, data);

	xmms_mpc_collect_metadata (xform);


	data->buffer = g_string_new (NULL);

	data->reader.read = xmms_mpc_callback_read;
	data->reader.seek = xmms_mpc_callback_seek;
	data->reader.tell = xmms_mpc_callback_tell;
	data->reader.canseek = xmms_mpc_callback_canseek;
	data->reader.get_size = xmms_mpc_callback_get_size;

	data->reader.data = xform;

#ifdef HAVE_MPCDEC_OLD
	mpc_streaminfo_init (&data->info);
	if (mpc_streaminfo_read (&data->info, &data->reader) != ERROR_CODE_OK)
		return FALSE;

	mpc_decoder_setup (&data->decoder, &data->reader);

	if (mpc_decoder_initialize (&data->decoder, &data->info) == FALSE)
		return FALSE;
#else
	data->demux = mpc_demux_init (&data->reader);
	if (!data->demux) return FALSE;

	mpc_demux_get_info (data->demux,  &data->info);
#endif

	xmms_mpc_cache_streaminfo (xform);

	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->info.channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->info.sample_freq,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
Пример #10
0
static gboolean
xmms_asf_init (xmms_xform_t *xform)
{
    xmms_asf_data_t *data;
    asf_iostream_t stream;
    gint ret;

    g_return_val_if_fail (xform, FALSE);

    data = g_new0 (xmms_asf_data_t, 1);

    stream.read = xmms_asf_read_callback;
    stream.write = NULL;
    stream.seek = xmms_asf_seek_callback;
    stream.opaque = xform;

    data->file = asf_open_cb (&stream);
    if (!data->file) {
        g_free (data);
        return FALSE;
    }
    data->packet = asf_packet_create ();
    data->outbuf = g_string_new (NULL);

    xmms_xform_private_data_set (xform, data);

    ret = asf_init (data->file);
    if (ret < 0) {
        XMMS_DBG ("ASF parser failed to init with error %d", ret);
        asf_packet_destroy (data->packet);
        asf_close (data->file);

        return FALSE;
    }

    data->track = xmms_asf_get_track (xform, data->file);
    if (data->track < 0) {
        XMMS_DBG ("No audio track found");
        asf_packet_destroy (data->packet);
        asf_close (data->file);

        return FALSE;
    }

    xmms_asf_get_mediainfo (xform);

    XMMS_DBG ("ASF demuxer inited successfully!");

    return TRUE;
}
Пример #11
0
static gboolean
xmms_sndfile_init (xmms_xform_t *xform)
{
	xmms_sndfile_data_t *data;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_sndfile_data_t, 1);
	g_return_val_if_fail (data, FALSE);

	xmms_xform_private_data_set (xform, data);

	data->sfvirtual.get_filelen = &xmms_sf_virtual_get_filelen;
	data->sfvirtual.seek = &xmms_sf_virtual_seek;
	data->sfvirtual.read = &xmms_sf_virtual_read;
	data->sfvirtual.write = &xmms_sf_virtual_write;
	data->sfvirtual.tell = &xmms_sf_virtual_tell;

	data->sndfile = sf_open_virtual (&data->sfvirtual, SFM_READ,
	                                 &data->sf_info, xform);
	if (data->sndfile == NULL) {
		char errstr[1024];
		sf_error_str (NULL, errstr, sizeof (errstr));
		xmms_log_error ("libsndfile: sf_open_virtual failed with \"%s\".",
		                errstr);
		g_free (data);
		return FALSE;
	}

	xmms_sndfile_get_media_info (xform);

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             XMMS_SAMPLE_FORMAT_S32,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->sf_info.channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->sf_info.samplerate,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
Пример #12
0
static gboolean
xmms_ofa_init (xmms_xform_t *xform)
{
	xmms_ofa_data_t *data;
	xmms_medialib_entry_t entry;
	char *fp;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_ofa_data_t, 1);
	g_return_val_if_fail (data, FALSE);

	data->thread = g_thread_new ("x2 ofa calc", xmms_ofa_thread, data);
	if (!data->thread) {
		g_free (data);
		return FALSE;
	}

	g_mutex_init (&data->mutex);
	g_cond_init (&data->cond);

	data->bytes_to_read = 44100 * 135 * 4;
	data->buf = g_malloc (data->bytes_to_read);
	entry = xmms_xform_entry_get (xform);

	/* TODO: #2482
	fp = xmms_medialib_entry_property_get_str (entry, "ofa_fingerprint");
	*/
	fp = NULL;
	if (fp) {
		XMMS_DBG ("Entry already has ofa_fingerprint, not recalculating");
		/* keep it! */
		xmms_xform_metadata_set_str (xform, "ofa_fingerprint", fp);
		g_free (fp);
	} else {
		data->run_ofa = TRUE;
	}

	xmms_xform_private_data_set (xform, data);

	xmms_xform_outdata_type_copy (xform);

	return TRUE;
}
Пример #13
0
static gboolean
xmms_nulstripper_init (xmms_xform_t *xform)
{
	xmms_nulstripper_data_t *data;
	guint o;

	o = find_offset (xform);
	if (!o) {
		return FALSE;
	}

	data = g_new (xmms_nulstripper_data_t, 1);
	data->offset = o;

	xmms_xform_private_data_set (xform, data);

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "application/octet-stream",
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
Пример #14
0
static gboolean
xmms_daap_init (xmms_xform_t *xform)
{
	gint dbid;
	GSList *dbid_list = NULL;
	xmms_daap_data_t *data;
	xmms_daap_login_data_t *login_data;
	xmms_error_t err;
	const gchar *url;
	const gchar *metakey;
	gchar *command, *hash;
	guint filesize;

	g_return_val_if_fail (xform, FALSE);

	url = xmms_xform_indata_get_str (xform, XMMS_STREAM_TYPE_URL);

	g_return_val_if_fail (url, FALSE);

	data = g_new0 (xmms_daap_data_t, 1);

	xmms_error_reset (&err);

	if (!get_data_from_url (url, &(data->host), &(data->port), &command, &err)) {
		goto init_error;
	}

	hash = g_strdup_printf ("%s:%u", data->host, data->port);

	login_data = g_hash_table_lookup (login_sessions, hash);
	if (!login_data) {
		XMMS_DBG ("creating login data for %s", hash);
		login_data = g_new0 (xmms_daap_login_data_t, 1);

		login_data->request_id = 1;
		login_data->logged_in = TRUE;

		login_data->session_id = daap_command_login (data->host, data->port,
		                                             login_data->request_id,
		                                             &err);
		if (xmms_error_iserror (&err)) {
			g_free (login_data);
			goto init_error;
		}

		g_hash_table_insert (login_sessions, hash, login_data);
	}

	login_data->revision_id = daap_command_update (data->host, data->port,
	                                               login_data->session_id,
	                                               login_data->request_id);
	dbid_list = daap_command_db_list (data->host, data->port,
	                                  login_data->session_id,
	                                  login_data->revision_id,
	                                  login_data->request_id);
	if (!dbid_list) {
		goto init_error;
	}

	/* XXX: see XXX in the browse function above */
	dbid = ((cc_item_record_t *) dbid_list->data)->dbid;
	/* want to request a stream, but don't read the data yet */
	data->conn = daap_command_init_stream (data->host, data->port,
	                                       login_data->session_id,
	                                       login_data->revision_id,
	                                       login_data->request_id, dbid,
	                                       command, &filesize);

	if (! data->conn) {
		goto init_error;
	}
	login_data->request_id++;

	metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE;
	xmms_xform_metadata_set_int (xform, metakey, filesize);

	xmms_xform_private_data_set (xform, data);

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "application/octet-stream",
	                             XMMS_STREAM_TYPE_END);

	g_slist_foreach (dbid_list, (GFunc) cc_item_record_free, NULL);
	g_slist_free (dbid_list);
	g_free (command);

	return TRUE;

init_error:
	if (data) {
		if (data->host)
			g_free (data->host);
		g_free (data);
	}
	return FALSE;
}
Пример #15
0
static gboolean
xmms_gme_init (xmms_xform_t *xform)
{
	xmms_gme_data_t *data;
	gme_err_t init_error;
	GString *file_contents; /* The raw data from the file. */
	gme_info_t *metadata = NULL;
	xmms_config_property_t *val;
	int loops;
	int maxlength;
	const char *subtune_str;
	int subtune = 0;
	long fadelen = -1;
	int samplerate;
	double stereodepth;


	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_gme_data_t, 1);

	xmms_xform_private_data_set (xform, data);

	val = xmms_xform_config_lookup (xform, "samplerate");
	samplerate = xmms_config_property_get_int (val);
	if (samplerate < 1)
		samplerate = GME_DEFAULT_SAMPLE_RATE;
	data->samplerate = samplerate;

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm", /* PCM samples */
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             XMMS_SAMPLE_FORMAT_S16, /* 16-bit signed */
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             2, /* stereo */
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             samplerate,
	                             XMMS_STREAM_TYPE_END);

	file_contents = 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 emulated music data");
			return FALSE;
		}
		if (ret == 0) {
			break;
		}
		g_string_append_len (file_contents, buf, ret);
	}

	init_error = gme_open_data (file_contents->str, file_contents->len, &data->emu, samplerate);

	g_string_free (file_contents, TRUE);

	if (init_error) {
		XMMS_DBG ("gme_open_data returned an error: %s", init_error);
		return FALSE;
	}

	if (xmms_xform_metadata_get_str (xform, "subtune", &subtune_str)) {
		subtune = strtol (subtune_str, NULL, 10);
		XMMS_DBG ("Setting subtune to %d", subtune);
		if ((subtune < 0 || subtune > gme_track_count (data->emu))) {
			XMMS_DBG ("Invalid subtune index");
			return FALSE;
		}
	} else {
		xmms_xform_metadata_set_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_SUBTUNES, gme_track_count (data->emu));
	}

	/*
	 *  Get metadata here
	 */
	init_error = gme_track_info (data->emu, &metadata, subtune);
	if (init_error) {
		XMMS_DBG ("Couldn't get GME track info: %s", init_error);
		init_error = "";
	} else {
		xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TITLE, metadata->song);
		xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_ARTIST, metadata->author);
		xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_ALBUM, metadata->game);
		xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_COMMENT, metadata->comment);
		xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_YEAR, metadata->copyright);
		xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_GENRE, metadata->system);  /* I mapped genre to the system type */

		val = xmms_xform_config_lookup (xform, "loops");
		loops = xmms_config_property_get_int (val);

		XMMS_DBG ("intro_length = %d, loops = %d, loop_length = %d", metadata->intro_length, loops, metadata->loop_length);

		if (metadata->intro_length > 0) {
			if ((loops > 0) && (metadata->loop_length > 0)) {
				fadelen = metadata->intro_length + loops * metadata->loop_length;
				XMMS_DBG ("fadelen now = %ld", fadelen);
			} else {
				fadelen = metadata->length;
				XMMS_DBG ("fadelen now = %ld", fadelen);
			}
		}
	}

	val = xmms_xform_config_lookup (xform, "maxlength");
	maxlength = xmms_config_property_get_int (val);

	XMMS_DBG ("maxlength = %d seconds", maxlength);

	if (maxlength > 0 && (fadelen < 0 || (maxlength * 1000L < fadelen))) {
		fadelen = maxlength * 1000L;
		XMMS_DBG ("fadelen now = %ld", fadelen);
	}

	XMMS_DBG ("gme.fadelen = %ld", fadelen);

	val = xmms_xform_config_lookup (xform, "stereodepth");
	stereodepth = xmms_config_property_get_float (val);
	if (stereodepth >= 0.0 && stereodepth <= 1.0) {
		XMMS_DBG ("Setting stereo depth to %f.", stereodepth);
		gme_set_stereo_depth (data->emu, stereodepth);
	} else {
		XMMS_DBG ("gme.stereodepth = %f out of range 0.0 - 1.0; not setting.", stereodepth);
	}

	init_error = gme_start_track (data->emu, subtune);
	if (init_error) {
		XMMS_DBG ("gme_start_track returned an error: %s", init_error);
		gme_free_info (metadata);
		return FALSE;
	}

	if (fadelen > 0) {
		XMMS_DBG ("Setting song length and fade length...");
		xmms_xform_metadata_set_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION, fadelen);
		gme_set_fade (data->emu, fadelen);
	}

	gme_free_info (metadata);
	return TRUE;
}
Пример #16
0
static gboolean
xmms_faad_init (xmms_xform_t *xform)
{
	xmms_faad_data_t *data;
	xmms_error_t error;

	NeAACDecConfigurationPtr config;
	gint bytes_read;
	gulong samplerate;
	guchar channels;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_faad_data_t, 1);
	data->outbuf = g_string_new (NULL);
	data->buffer_size = FAAD_BUFFER_SIZE;

	xmms_xform_private_data_set (xform, data);

	data->decoder = NeAACDecOpen ();
	config = NeAACDecGetCurrentConfiguration (data->decoder);
	config->defObjectType = LC;
	config->defSampleRate = 44100;
	config->outputFormat = FAAD_FMT_16BIT;
	config->downMatrix = 0;
	config->dontUpSampleImplicitSBR = 0;
	NeAACDecSetConfiguration (data->decoder, config);

	switch (config->outputFormat) {
	case FAAD_FMT_16BIT:
		data->sampleformat = XMMS_SAMPLE_FORMAT_S16;
		break;
	case FAAD_FMT_24BIT:
		/* we don't have 24-bit format to use in xmms2 */
		data->sampleformat = XMMS_SAMPLE_FORMAT_S32;
		break;
	case FAAD_FMT_32BIT:
		data->sampleformat = XMMS_SAMPLE_FORMAT_S32;
		break;
	case FAAD_FMT_FLOAT:
		data->sampleformat = XMMS_SAMPLE_FORMAT_FLOAT;
		break;
	case FAAD_FMT_DOUBLE:
		data->sampleformat = XMMS_SAMPLE_FORMAT_DOUBLE;
		break;
	}

	while (data->buffer_length < 8) {
		xmms_error_reset (&error);
		bytes_read = xmms_xform_read (xform,
		                              (gchar *) data->buffer + data->buffer_length,
		                              data->buffer_size - data->buffer_length,
		                              &error);
		data->buffer_length += bytes_read;

		if (bytes_read < 0) {
			xmms_log_error ("Error while trying to read data on init");
			goto err;
		} else if (bytes_read == 0) {
			XMMS_DBG ("Not enough bytes to check the AAC header");
			goto err;
		}
	}

	/* which type of file are we dealing with? */
	data->filetype = FAAD_TYPE_UNKNOWN;
	if (xmms_xform_auxdata_has_val (xform, "decoder_config")) {
		data->filetype = FAAD_TYPE_MP4;
	} else if (!strncmp ((char *) data->buffer, "ADIF", 4)) {
		data->filetype = FAAD_TYPE_ADIF;
	} else {
		int i;

		/* ADTS mpeg file can be a stream and start in the middle of a
		 * frame so we need to have extra loop check here */
		for (i=0; i<data->buffer_length-1; i++) {
			if (data->buffer[i] == 0xff && (data->buffer[i+1]&0xf6) == 0xf0) {
				data->filetype = FAAD_TYPE_ADTS;
				g_memmove (data->buffer, data->buffer+i, data->buffer_length-i);
				data->buffer_length -= i;
				break;
			}
		}
	}

	if (data->filetype == FAAD_TYPE_ADTS || data->filetype == FAAD_TYPE_ADIF) {
		bytes_read = NeAACDecInit (data->decoder, data->buffer,
		                          data->buffer_length, &samplerate,
		                          &channels);
	} else if (data->filetype == FAAD_TYPE_MP4) {
		const guchar *tmpbuf;
		gsize tmpbuflen;
		guchar *copy;

		if (!xmms_xform_auxdata_get_bin (xform, "decoder_config", &tmpbuf,
		                                 &tmpbuflen)) {
			XMMS_DBG ("AAC decoder config data found but it's wrong type! (something broken?)");
			goto err;
		}

		copy = g_memdup (tmpbuf, tmpbuflen);
		bytes_read = NeAACDecInit2 (data->decoder, copy, tmpbuflen,
		                           &samplerate, &channels);
		g_free (copy);
	}

	if (bytes_read < 0) {
		XMMS_DBG ("Error initializing decoder library.");
		goto err;
	}

	/* Get mediainfo and skip the possible header */
	xmms_faad_get_mediainfo (xform);
	g_memmove (data->buffer, data->buffer + bytes_read,
	           data->buffer_length - bytes_read);
	data->buffer_length -= bytes_read;

	data->samplerate = samplerate;
	data->channels = channels;

	/* Because for HE AAC files some versions of libfaad return the wrong
	 * samplerate in init, we have to do one read and let it decide the
	 * real parameters. After changing sample parameters and format is
	 * supported, this hack should be removed and handled in read instead. */
	{
		gchar tmpbuf[1024];

		xmms_error_reset (&error);
		bytes_read = xmms_faad_read (xform, tmpbuf, 1024, &error);
		if (bytes_read <= 0) {
			XMMS_DBG ("First read from faad decoder failed!");
			return FALSE;
		}
		g_string_prepend_len (data->outbuf, tmpbuf, bytes_read);
	}

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             data->sampleformat,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->samplerate,
	                             XMMS_STREAM_TYPE_END);

	XMMS_DBG ("AAC decoder inited successfully!");

	return TRUE;

err:
	g_string_free (data->outbuf, TRUE);
	g_free (data);

	return FALSE;
}
Пример #17
0
static gboolean
xmms_speex_init (xmms_xform_t *xform)
{
	gint pe;

	xmms_config_property_t *val;
	xmms_speex_data_t *data;
	xmms_error_t error;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_speex_data_t, 1);
	g_return_val_if_fail (data, FALSE);

	xmms_xform_private_data_set (xform, data);

	ogg_sync_init (&data->sync_state);
	speex_bits_init (&data->speex_bits);

	/* Find the speex header */

	while (42) {
		gint ret;

		data->ogg_data = ogg_sync_buffer (&data->sync_state, 1024);
		ret = xmms_xform_read (xform, data->ogg_data, 1024, &error);
		ogg_sync_wrote (&data->sync_state, ret);

		if (ret <= 0) {
			return FALSE;
		}

		if (ogg_sync_pageout (&data->sync_state, &data->ogg_page) == 1) {
			break;
		}
	}

	ogg_stream_init (&data->stream_state, ogg_page_serialno (&data->ogg_page));

	if (ogg_stream_pagein (&data->stream_state, &data->ogg_page) < 0) {
		return FALSE;
	}

	if (ogg_stream_packetout (&data->stream_state, &data->ogg_packet) != 1) {
		return FALSE;
	}

	data->speexheader = speex_packet_to_header ((char *)data->ogg_packet.packet,
	                                            data->ogg_packet.bytes);
	data->speex_state = speex_decoder_init (speex_mode_list[data->speexheader->mode]);

	val = xmms_xform_config_lookup (xform, "perceptual_enhancer");
	pe = xmms_config_property_get_int (val);
	speex_decoder_ctl (data->speex_state, SPEEX_SET_ENH, &pe);

	ogg_sync_pageout (&data->sync_state, &data->ogg_page);
	ogg_stream_pagein (&data->stream_state, &data->ogg_page);
	ogg_stream_packetout (&data->stream_state, &data->ogg_packet);

	data->samples_buf = g_new (gint16,
	                           data->speexheader->frames_per_packet *
	                           data->speexheader->frame_size *
	                           data->speexheader->nb_channels);
	data->samples_start = data->samples_buf;
	data->samples_count = 0;

	xmms_speex_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,
	                             data->speexheader->nb_channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->speexheader->rate,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
Пример #18
0
static gboolean
xmms_wavpack_init (xmms_xform_t *xform)
{
	xmms_wavpack_data_t *data;
	xmms_sample_format_t sample_format;
	gint samplerate;
	/* the maximum length of error really isn't defined... stupid */
	gchar error[1024];

	g_return_val_if_fail (xform, FALSE);

	if (!xmms_apetag_read (xform)) {
		XMMS_DBG ("Failed to read APEv2 tag");
	}

	data = g_new0 (xmms_wavpack_data_t, 1);
	g_return_val_if_fail (data, FALSE);

	xmms_xform_private_data_set (xform, data);

	data->reader.read_bytes = wavpack_read_bytes;
	data->reader.get_pos = wavpack_get_pos;
	data->reader.set_pos_abs = wavpack_set_pos_abs;
	data->reader.set_pos_rel = wavpack_set_pos_rel;
	data->reader.push_back_byte = wavpack_push_back_byte;
	data->reader.get_length = wavpack_get_length;
	data->reader.can_seek = wavpack_can_seek;

	data->ctx = WavpackOpenFileInputEx (&data->reader,
	                                    xform, xform,
	                                    error, OPEN_TAGS, 0);

	if (!data->ctx) {
		xmms_log_error ("Unable to open wavpack file: %s", error);
		xmms_xform_private_data_set (xform, NULL);
		xmms_wavpack_free_data (data);
		return FALSE;
	}

	data->channels = WavpackGetNumChannels (data->ctx);
	data->bits_per_sample = WavpackGetBitsPerSample (data->ctx);
	data->num_samples = WavpackGetNumSamples (data->ctx);
	samplerate = WavpackGetSampleRate (data->ctx);

	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION,
	                             (int) (1000.0 * data->num_samples / samplerate));
	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_SAMPLERATE,
	                             samplerate);
	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE,
	                             (int) WavpackGetAverageBitrate (data->ctx, FALSE));

	switch (data->bits_per_sample) {
	case 8:
		sample_format = XMMS_SAMPLE_FORMAT_S8;
		break;
	case 12:
	case 16:
		sample_format = XMMS_SAMPLE_FORMAT_S16;
		break;
	case 24:
	case 32:
		sample_format = XMMS_SAMPLE_FORMAT_S32;
		break;
	default:
		xmms_log_error ("Unsupported bits-per-sample in wavpack file: %d",
		                data->bits_per_sample);
		xmms_xform_private_data_set (xform, NULL);
		xmms_wavpack_free_data (data);
		return FALSE;
	}

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             sample_format,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             samplerate,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
static gboolean
xmms_gvfs_init (xmms_xform_t *xform)
{
    xmms_gvfs_data_t *data;
    GFile *file;
    GFileInfo *info;
    GFileInputStream *handle;
    GError *error = NULL;
    const gchar *url;

    url = xmms_xform_indata_get_str (xform, XMMS_STREAM_TYPE_URL);
    g_return_val_if_fail (url, FALSE);

    /* This is an ugly hack to handle files with
       chars needing url encoding */
    if (!g_ascii_strncasecmp (url, "file://", 7)) {
        file = g_file_new_for_path (url+7);
    } else {
        file = g_file_new_for_uri (url);
    }
    handle = g_file_read (file, NULL, &error);
    g_object_unref (file);

    if (!handle) {
        xmms_log_error ("Failed to upen url %s for reading: %s",
                        url, error->message);
        return FALSE;
    }

    data = g_new (xmms_gvfs_data_t, 1);
    data->handle = G_INPUT_STREAM (handle);
    xmms_xform_private_data_set (xform, data);

    info = g_file_input_stream_query_info (handle, (char *)query_attributes,
                                           NULL, &error);

    if (!info) {
        xmms_log_info ("failed to query information for %s", url);
    } else {
        int i;

        for (i = 0; i < G_N_ELEMENTS (attr_map); i++) {
            if (!g_file_info_has_attribute (info, attr_map[i].gvfs)) {
                continue;
            }

            switch (attr_map[i].type) {
            case XMMSV_TYPE_STRING: {
                gchar *attr = g_file_info_get_attribute_as_string (info,
                              attr_map[i].gvfs);
                xmms_xform_metadata_set_str (xform, attr_map[i].mlib, attr);
                g_free (attr);
                break;
            }
            case XMMSV_TYPE_INT32: {
                /* right now the xform metadata api only handles strings
                 * and 32 bit ints. however the gvfs api returns uint64 for
                 * the numeric attributes we're interested in and we just
                 * pass that to the xform and pray that it doesn't overflow
                 * as we know it's unsafe.
                 */

                gint64 attr = g_file_info_get_attribute_uint64 (info,
                              attr_map[i].gvfs);
                xmms_xform_metadata_set_int (xform, attr_map[i].mlib, attr);
                break;
            }
            default:
                g_assert_not_reached ();
            }
        }

        g_object_unref (info);
    }

    xmms_xform_outdata_type_add (xform,
                                 XMMS_STREAM_TYPE_MIMETYPE,
                                 "application/octet-stream",
                                 XMMS_STREAM_TYPE_END);

    return TRUE;
}
Пример #22
0
static gboolean
xmms_midsquash_init (xmms_xform_t *xform)
{
	xmms_error_t error;
	xmms_midsquash_data_t *data;
	gulong track_len, len;
	gint32 ticks_per_quarter_note;
	const gchar *metakey;
	guchar buf[4096];
	gint ret;
	guchar prev_event = 0;
	GArray *events = NULL;
	GArray *track_data = NULL;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_midsquash_data_t, 1);
	xmms_xform_private_data_set (xform, data);

	data->midi0_data = NULL;

	if (!xmms_xform_auxdata_get_int (xform, "tempo", &ticks_per_quarter_note)) {
		XMMS_DBG ("MIDI xform missing 'tempo' auxdata value");
		goto error_cleanup;
	}
	xmms_xform_auxdata_set_int (xform, "tempo", ticks_per_quarter_note);

	/* Load all the tracks */
	events = g_array_new(FALSE, FALSE, sizeof(xmms_midsquash_event_t));
	track_data = g_array_new(FALSE, FALSE, sizeof(GString *));
	while (xmms_xform_read (xform, buf, 4, &error) == 4) {
		track_len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
		GString *t = g_string_sized_new(track_len);

		ret = xmms_xform_read (xform, t->str, track_len, &error);

		g_array_append_val(track_data, t);

		/* Run through the MIDI data in this track, and convert it to a list of
		 * events in absolute ticks (instead of delta ticks.)
		 */
		gulong i = 0;
		gulong abs_ticks = 0;
		while (i < track_len) {
			abs_ticks += xmms_midisquash_read_midi_num(t->str, &i);

			xmms_midsquash_event_t event;
			gboolean ignore_event = FALSE;
			event.time = abs_ticks;
			event.offset = &t->str[i];
			gulong i0 = i;

			/* Read MIDI event */
			guchar midi_event = t->str[i];

			if (!(midi_event & 0x80)) {
				/* This is a running-status byte */
				midi_event = prev_event;
				event.running_status = prev_event;
			} else {
				if ((midi_event & 0xF0) != 0xF0) {
					/* Meta events (0xF0 through 0xFF) can appear in the middle of
					 * running-status data without affecting the running status, so we
					 * only update the 'last event' if this isn't a meta-event.
					 */
					prev_event = midi_event;
				}
				event.running_status = 0;
				i++;
			}

			switch (midi_event & 0xF0) {
				case 0x80:  /* Note off (two bytes) */ i += 2; break;
				case 0x90:  /* Note on (two bytes) */ i += 2; break;
				case 0xA0:  /* Key pressure (two bytes) */ i += 2; break;
				case 0xB0:  /* Controller change (two bytes) */ i += 2; break;
				case 0xC0:  /* Instrument change (one byte) */ i += 1; break;
				case 0xD0:  /* Channel pressure (one byte) */ i += 1; break;
				case 0xE0:  /* Pitch bend (two bytes) */ i += 2; break;
				case 0xF0: {
					if (midi_event == 0xFF) { /* Meta-event */
						if (t->str[i] == 0x2F) {
							/* This is an end-of-track event, so we need to ignore it
							 * otherwise the song will end as soon as we encounter the end
							 * of the shortest track (which could be quite early on.)
							 */
							ignore_event = TRUE;
						}
						i++; /* event type */
					} /* else sysex */
					len = xmms_midisquash_read_midi_num(t->str, &i);
					i += len;
					break;
				}
				default:
					XMMS_DBG ("Corrupted MIDI file (invalid event 0x%02X)", midi_event);
					goto error_cleanup;
			}
			event.length = i - i0;
			if (!ignore_event)
				g_array_append_val(events, event);
		} /* end loop: run through all the track's events */
	}

	/* Now that all the events have been read in, in absolute time, sorting them
	 * will put them all in playable order.
	 */
	g_array_sort(events, xmms_midsquash_sort_events);

	/* Now copy all the sorted events into a big array, which will be used as
	 * the output data.
	 */
	data->midi0_data = g_string_new("");
	gulong last_time = 0;
	guint64 playtime_us = 0;
	gulong us_per_quarter_note = 500000;
	gulong i, j;
	guchar val;
	for (i = 0; i < events->len; i++) {
		xmms_midsquash_event_t *e;
		e = &g_array_index(events, xmms_midsquash_event_t, i);

		/* Calculate the delta time and write it out in MIDI style */
		gulong delta_ticks = e->time - last_time;
		if (delta_ticks & (0x7F << 21)) {
			val = ((delta_ticks >> 21) & 0x7F) | 0x80;
			g_string_append_len(data->midi0_data, (gchar *)&val, 1);
		}
		if (delta_ticks & ((0x7F << 21) | (0x7F << 14))) {
			val = ((delta_ticks >> 14) & 0x7F) | 0x80;
			g_string_append_len(data->midi0_data, (gchar *)&val, 1);
		}
Пример #23
0
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;

}
Пример #24
0
static gboolean
xmms_eq_init (xmms_xform_t *xform)
{
	xmms_equalizer_data_t *priv;
	xmms_config_property_t *config;
	gint i, j, srate;
	gfloat gain;

	g_return_val_if_fail (xform, FALSE);

	priv = g_new0 (xmms_equalizer_data_t, 1);
	g_return_val_if_fail (priv, FALSE);

	xmms_xform_private_data_set (xform, priv);

	config = xmms_xform_config_lookup (xform, "enabled");
	g_return_val_if_fail (config, FALSE);
	xmms_config_property_callback_set (config, xmms_eq_config_changed, priv);
	priv->enabled = !!xmms_config_property_get_int (config);

	config = xmms_xform_config_lookup (xform, "bands");
	g_return_val_if_fail (config, FALSE);
	xmms_config_property_callback_set (config, xmms_eq_config_changed, priv);
	priv->bands = xmms_config_property_get_int (config);

	config = xmms_xform_config_lookup (xform, "extra_filtering");
	g_return_val_if_fail (config, FALSE);
	xmms_config_property_callback_set (config, xmms_eq_config_changed, priv);
	priv->extra_filtering = xmms_config_property_get_int (config);

	config = xmms_xform_config_lookup (xform, "use_legacy");
	g_return_val_if_fail (config, FALSE);
	xmms_config_property_callback_set (config, xmms_eq_config_changed, priv);
	priv->use_legacy = xmms_config_property_get_int (config);

	config = xmms_xform_config_lookup (xform, "preamp");
	g_return_val_if_fail (config, FALSE);
	xmms_config_property_callback_set (config, xmms_eq_gain_changed, priv);
	gain = xmms_config_property_get_float (config);

	for (i=0; i<EQ_CHANNELS; i++) {
		set_preamp (i, xmms_eq_gain_scale (gain, TRUE));
	}

	for (i=0; i<EQ_BANDS_LEGACY; i++) {
		gchar buf[16];

		g_snprintf (buf, sizeof (buf), "legacy%d", i);
		config = xmms_xform_config_lookup (xform, buf);
		g_return_val_if_fail (config, FALSE);

		priv->legacy[i] = config;
		xmms_config_property_callback_set (config, xmms_eq_gain_changed, priv);

		gain = xmms_config_property_get_float (config);
		if (priv->use_legacy) {
			for (j = 0; j < EQ_CHANNELS; j++) {
				set_gain (i, j, xmms_eq_gain_scale (gain, FALSE));
			}
		}
	}

	for (i=0; i<EQ_MAX_BANDS; i++) {
		gchar buf[16];

		g_snprintf (buf, sizeof (buf), "gain%02d", i);
		config = xmms_xform_config_lookup (xform, buf);
		g_return_val_if_fail (config, FALSE);

		priv->gain[i] = config;
		xmms_config_property_callback_set (config, xmms_eq_gain_changed, priv);

		gain = xmms_config_property_get_float (config);
		if (!priv->use_legacy) {
			for (j = 0; j < EQ_CHANNELS; j++) {
				set_gain (i, j, xmms_eq_gain_scale (gain, FALSE));
			}
		}
	}

	init_iir ();
	srate = xmms_xform_indata_get_int (xform, XMMS_STREAM_TYPE_FMT_SAMPLERATE);
	if (priv->use_legacy) {
		config_iir (srate, EQ_BANDS_LEGACY, 1);
	} else {
		config_iir (srate, priv->bands, 0);
	}

	xmms_xform_outdata_type_copy (xform);

	XMMS_DBG ("Equalizer initialized successfully!");

	return TRUE;
}
Пример #25
0
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;
}
Пример #26
0
static gboolean
xmms_mid1_init (xmms_xform_t *xform)
{
	xmms_error_t error;
	xmms_mid1_data_t *data;
	guchar buf[4096];
	gulong len;
	gint ret;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_mid1_data_t, 1);
	g_return_val_if_fail (data, FALSE);
	xmms_xform_private_data_set (xform, data);

	ret = xmms_xform_read (xform, buf, 4, &error);
	if (strncmp ((char *)buf, "RIFF", 4) == 0) {
		/* This is an .rmi file, find the data chunk */
		gboolean is_rmid = FALSE;

		/* Skip the RIFF length and RMID type (we wouldn't be here if it wasn't
		 * RMID thanks to xmms_magic_add above.)
		 */
		xmms_xform_read (xform, buf, 8, &error); /* skip RIFF length */
		for (;;) {
			/* Get chunk type and length */
			xmms_xform_read (xform, buf, 8, &error);
			if (strncmp ((char *)buf, "data", 4) == 0) {
				/* We found the data chunk, the rest is just a normal MIDI file.  We
				 * chew up the "MThd" signature though, as the code below expects it
				 * to be gone (as it would in a normal MIDI file when we eat it to
				 * check the RIFF header above.) */
				is_rmid = TRUE;
				ret = xmms_xform_read (xform, buf, 4, &error);
				break;
			}

			/* If we're here, this isn't the "data" chunk, so skip over it */
			len = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
			while (len > 0) {
				ret = xmms_xform_read (xform, buf, MIN (len, sizeof (buf)), &error);
				if (ret < 1) break;
				len -= ret;
			}
		}

		if (!is_rmid) {
			xmms_log_error ("RMID file has no 'data' chunk!");
			goto cleanup;
		}
	}

	/* Once we get here we're just after the MThd signature */
	ret = xmms_xform_read (xform, buf, 10, &error);
	gint header_len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
	if (header_len != 6) {
		xmms_log_error ("Unexpected MThd header length");
		goto cleanup;
	}

	/* Don't need to check it's a type-0 or 1 as the magic matching did it */

	guint track_count = (buf[6] << 8) | buf[7];
	if (track_count == 0) {
		xmms_log_error ("MIDI file has no tracks?!");
		goto cleanup;
	}

	guint ticks_per_quarter_note = (buf[8] << 8) | buf[9];
	if (ticks_per_quarter_note & 0x8000) {
		/* TODO */
		xmms_log_error ("SMPTE timing not implemented");
		goto cleanup;
	}
	xmms_xform_auxdata_set_int (xform, "tempo", ticks_per_quarter_note);

	data->chunked_data = g_string_sized_new (1024);

	/* Load all the tracks */
	while (xmms_xform_read (xform, buf, 8, &error) == 8) {
		len = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
		XMMS_DBG ("%.4s len is %lu", buf, len);

		if (strncmp ((char *)buf, "MTrk", 4) != 0) {
			XMMS_DBG ("Ignoring unknown chunk: %.4s", buf);
			/* Skip over the chunk - we don't use seek as it's not always implemented
			 * by the parent xform.
			 */
			while (len > 0) {
				ret = xmms_xform_read (xform, buf, MIN (len, sizeof (buf)), &error);
				if (ret < 1) break;
				len -= ret;
			}
		} else {
			/* Append the big-endian length */
			g_string_append_len (data->chunked_data, (gchar *)&buf[4], 4);

			for (;;) {
				gulong amt = MIN (len, sizeof (buf));
				if (amt == 0) break;
				ret = xmms_xform_read (xform, (gchar *)buf, amt, &error);
				if (ret != amt) {
					/* Short read */
					XMMS_DBG ("Short read");
					goto cleanup;
				}
				g_string_append_len (data->chunked_data, (gchar *)buf, amt);
				len -= amt;
			}
		}
	}

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/miditracks",
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             16,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;

cleanup:
	if (data->chunked_data)
		g_string_free (data->chunked_data, TRUE);

	g_free (data);

	return FALSE;
}
Пример #27
0
static gboolean
xmms_mp4_init (xmms_xform_t *xform)
{
	xmms_mp4_data_t *data;
	xmms_error_t error;

	gint bytes_read;

	guchar *tmpbuf;
	guint tmpbuflen;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_mp4_data_t, 1);
	data->outbuf = g_string_new (NULL);
	data->buffer_size = MP4_BUFFER_SIZE;

	xmms_xform_private_data_set (xform, data);

	data->sampleid = 1;
	data->numsamples = 0;

	bytes_read = xmms_xform_read (xform,
	                              (gchar *) data->buffer + data->buffer_length,
	                              data->buffer_size - data->buffer_length,
	                              &error);

	data->buffer_length += bytes_read;

	if (bytes_read < 8) {
		XMMS_DBG ("Not enough bytes to check the MP4 header");
		goto err;
	}

	/*
	 * MP4 not supported (yet) on non-seekable transport
	 * this needs little tweaking in mp4ff at least
	 */
	if (xmms_xform_seek (xform, 0, XMMS_XFORM_SEEK_CUR, &error) < 0) {
		XMMS_DBG ("Non-seekable transport on MP4 not yet supported");
		goto err;
	}

	data->mp4ff_cb = g_new0 (mp4ff_callback_t, 1);
	data->mp4ff_cb->read = xmms_mp4_read_callback;
	data->mp4ff_cb->seek = xmms_mp4_seek_callback;
	data->mp4ff_cb->user_data = xform;

	data->mp4ff = mp4ff_open_read (data->mp4ff_cb);
	if (!data->mp4ff) {
		XMMS_DBG ("Error opening mp4 demuxer\n");
		goto err;;
	}

	data->track = xmms_mp4_get_track (xform, data->mp4ff);
	if (data->track < 0) {
		XMMS_DBG ("Can't find suitable audio track from MP4 file\n");
		goto err;
	}
	data->numsamples = mp4ff_num_samples (data->mp4ff, data->track);

	mp4ff_get_decoder_config (data->mp4ff, data->track, &tmpbuf,
	                          &tmpbuflen);
	xmms_xform_auxdata_set_bin (xform, "decoder_config", tmpbuf, tmpbuflen);
	g_free (tmpbuf);

	xmms_mp4_get_mediainfo (xform);

	XMMS_DBG ("MP4 demuxer inited successfully!");

	return TRUE;

err:
	g_free (data->mp4ff_cb);
	g_string_free (data->outbuf, TRUE);
	g_free (data);

	return FALSE;
}
Пример #28
0
static gboolean
xmms_sid_init (xmms_xform_t *xform)
{
	xmms_sid_data_t *data;
	const char *subtune;
	gint ret;

	data = g_new0 (xmms_sid_data_t, 1);

	data->wrapper = sidplay_wrapper_init ();

	xmms_xform_private_data_set (xform, data);

	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 sid file");
			return FALSE;
		}
		if (ret == 0) {
			break;
		}
		g_string_append_len (data->buffer, buf, ret);
	}

	ret = sidplay_wrapper_load (data->wrapper, data->buffer->str,
	                            data->buffer->len);

	if (ret < 0) {
		XMMS_DBG ("Couldn't load sid file");
		return FALSE;
	}

	if (xmms_xform_metadata_get_str (xform, "subtune", &subtune)) {
		int num;
		num = atoi (subtune);
		if (num < 1 || num > sidplay_wrapper_subtunes (data->wrapper)) {
			XMMS_DBG ("Invalid subtune index");
			return FALSE;
		}
		sidplay_wrapper_set_subtune (data->wrapper, num);
	}

	xmms_sid_get_media_info (xform);

	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,
	                             44100,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
Пример #29
0
static gboolean
xmms_cdda_init (xmms_xform_t *xform)
{
	CdIo_t *cdio = NULL;
	cdrom_drive_t *drive = NULL;
	const gchar *url;
	gchar **url_data = NULL;
	gchar *url_end;
	xmms_cdda_data_t *data;
	guint playtime;
	lsn_t first_lsn;
	track_t track;
	gchar *disc_id = NULL;
	gchar *cddb_id = NULL;
	xmms_config_property_t *val;
	const gchar *device;
	const gchar *metakey;
	gboolean ret = TRUE;

	g_return_val_if_fail (xform, FALSE);
	url = xmms_xform_indata_get_str (xform, XMMS_STREAM_TYPE_URL);

	if (g_ascii_strcasecmp (url, "cdda://") == 0) {
		xmms_xform_outdata_type_add (xform,
		                             XMMS_STREAM_TYPE_MIMETYPE,
		                             "application/x-xmms2-playlist-entries",
		                             XMMS_STREAM_TYPE_END);
		return TRUE;
	}

	val = xmms_xform_config_lookup (xform, "device");
	device = xmms_config_property_get_string (val);

	if (!get_disc_ids (device, &disc_id, &cddb_id, 0)) {
		return FALSE;
	}

	url += 7;
	url_data = g_strsplit (url, "/", 2);

	if (g_ascii_strcasecmp (url_data[0], disc_id)) {
		xmms_log_error ("Wrong disc inserted.");
		ret = FALSE;
		goto end;
	}

	if (url_data[1] == NULL) {
		xmms_log_error ("Missing track number.");
		ret = FALSE;
		goto end;
	}

	track = strtol (url_data[1], &url_end, 10);
	if (url_data[1] == url_end) {
		xmms_log_error ("Invalid track, need a number.");
		ret = FALSE;
		goto end;
	}

	cdio = open_cd (xform);
	if (!cdio) {
		ret = FALSE;
		goto end;
	}

	drive = cdio_cddap_identify_cdio (cdio, 1, NULL);
	if (!drive) {
		xmms_log_error ("Failed to identify drive.");
		ret = FALSE;
		goto end;
	}

	if (cdio_cddap_open (drive)) {
		xmms_log_error ("Unable to open disc.");
		ret = FALSE;
		goto end;
	}

	first_lsn = cdio_cddap_track_firstsector (drive, track);
	if (first_lsn == -1) {
		xmms_log_error ("No such track.");
		ret = FALSE;
		goto end;
	}

	data = g_new (xmms_cdda_data_t, 1);
	data->cdio = cdio;
	data->drive = drive;
	data->track = track;
	data->first_lsn = first_lsn;
	data->last_lsn = cdio_cddap_track_lastsector (drive, data->track);
	data->current_lsn = first_lsn;
	data->buf_used = CDIO_CD_FRAMESIZE_RAW;

	playtime = (data->last_lsn - data->first_lsn) *
	           1000.0 / CDIO_CD_FRAMES_PER_SEC;

	metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION;
	xmms_xform_metadata_set_int (xform, metakey, playtime);

	metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE;
	xmms_xform_metadata_set_int (xform, metakey, 141120);

	xmms_xform_metadata_set_str (xform, "disc_id", url_data[0]);
	xmms_xform_metadata_set_str (xform, "cddb_id", cddb_id);

	metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR;
	xmms_xform_metadata_set_int (xform, metakey, track);

	xmms_xform_private_data_set (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,
	                             2,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             44100,
	                             XMMS_STREAM_TYPE_END);

end:
	/* These are to be destroyed in every cases... */
	g_free (cddb_id);
	g_free (disc_id);
	g_strfreev (url_data);

	/* destroy cdio/drive in case of failure */
	if (!ret) {
		if (drive) {
			cdio_cddap_close_no_free_cdio (drive);
		}
		if (cdio) {
			cdio_destroy (cdio);
		}
	}

	return ret;
}
Пример #30
0
static gboolean
xmms_replaygain_init (xmms_xform_t *xform)
{
    xmms_replaygain_data_t *data;
    xmms_config_property_t *cfgv;
    xmms_sample_format_t fmt;

    g_return_val_if_fail (xform, FALSE);

    data = g_new0 (xmms_replaygain_data_t, 1);
    g_return_val_if_fail (data, FALSE);

    xmms_xform_private_data_set (xform, data);

    cfgv = xmms_xform_config_lookup (xform, "mode");
    xmms_config_property_callback_set (cfgv,
                                       xmms_replaygain_config_changed,
                                       xform);

    data->mode = parse_mode (xmms_config_property_get_string (cfgv));

    cfgv = xmms_xform_config_lookup (xform, "use_anticlip");
    xmms_config_property_callback_set (cfgv,
                                       xmms_replaygain_config_changed,
                                       xform);

    data->use_anticlip = !!xmms_config_property_get_int (cfgv);

    cfgv = xmms_xform_config_lookup (xform, "preamp");
    xmms_config_property_callback_set (cfgv,
                                       xmms_replaygain_config_changed,
                                       xform);

    data->preamp = pow (10.0, atof (xmms_config_property_get_string (cfgv)) / 20.0);

    cfgv = xmms_xform_config_lookup (xform, "enabled");
    xmms_config_property_callback_set (cfgv,
                                       xmms_replaygain_config_changed,
                                       xform);

    data->enabled = !!xmms_config_property_get_int (cfgv);

    xmms_xform_outdata_type_copy (xform);

    compute_gain (xform, data);

    fmt = xmms_xform_indata_get_int (xform, XMMS_STREAM_TYPE_FMT_FORMAT);

    switch (fmt) {
    case XMMS_SAMPLE_FORMAT_S8:
        data->apply = apply_s8;
        break;
    case XMMS_SAMPLE_FORMAT_U8:
        data->apply = apply_u8;
        break;
    case XMMS_SAMPLE_FORMAT_S16:
        data->apply = apply_s16;
        break;
    case XMMS_SAMPLE_FORMAT_U16:
        data->apply = apply_u16;
        break;
    case XMMS_SAMPLE_FORMAT_S32:
        data->apply = apply_s32;
        break;
    case XMMS_SAMPLE_FORMAT_U32:
        data->apply = apply_u32;
        break;
    case XMMS_SAMPLE_FORMAT_FLOAT:
        data->apply = apply_float;
        break;
    case XMMS_SAMPLE_FORMAT_DOUBLE:
        data->apply = apply_double;
        break;
    default:
        /* we shouldn't ever get here, since we told the daemon
         * earlier about this list of supported formats.
         */
        g_assert_not_reached ();
        break;
    }

    return TRUE;
}