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 gint
xmms_faad_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *err)
{
	xmms_faad_data_t *data;
	xmms_error_t error;

	NeAACDecFrameInfo frameInfo;
	gpointer sample_buffer;
	guint size, bytes_read = 0;

	data = xmms_xform_private_data_get (xform);
	g_return_val_if_fail (data, -1);

	size = MIN (data->outbuf->len, len);
	while (size == 0) {
		gboolean need_read;

		/* MP4 demuxer always gives full packets so we need different handling */
		if (data->filetype == FAAD_TYPE_MP4)
			need_read = (data->buffer_length == 0);
		else
			need_read = (data->buffer_length < data->buffer_size);

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

			if (bytes_read <= 0 && data->buffer_length == 0) {
				XMMS_DBG ("EOF");
				return 0;
			}

			data->buffer_length += bytes_read;
		}

		sample_buffer = NeAACDecDecode (data->decoder, &frameInfo, data->buffer,
		                               data->buffer_length);

		g_memmove (data->buffer, data->buffer + frameInfo.bytesconsumed,
		           data->buffer_length - frameInfo.bytesconsumed);
		data->buffer_length -= frameInfo.bytesconsumed;
		bytes_read = frameInfo.samples * xmms_sample_size_get (data->sampleformat);

		if (bytes_read > 0 && frameInfo.error == 0) {
			gint32 temp, toskip = 0;

			if (data->samplerate != frameInfo.samplerate ||
			    data->channels != frameInfo.channels) {
				/* We should inform output to change parameters somehow */
				XMMS_DBG ("Output format changed in the middle of a read!");
				data->samplerate = frameInfo.samplerate;
				data->channels = frameInfo.channels;
			}

			if (xmms_xform_auxdata_get_int (xform, "frame_offset", &temp)) {
				toskip = (temp * frameInfo.channels *
				          xmms_sample_size_get (data->sampleformat));
			}

			if (xmms_xform_auxdata_get_int (xform, "frame_duration", &temp)) {
				bytes_read = (temp * frameInfo.channels *
				              xmms_sample_size_get (data->sampleformat));
			}

			g_string_append_len (data->outbuf, sample_buffer + toskip,
			                     bytes_read - toskip);
		} else if (frameInfo.error > 0) {
			XMMS_DBG ("ERROR %d in faad decoding: %s", frameInfo.error,
			          NeAACDecGetErrorMessage (frameInfo.error));
			return -1;
		}

		size = MIN (data->outbuf->len, len);
	}

	memcpy (buf, data->outbuf->str, size);
	g_string_erase (data->outbuf, 0, size);
	return size;
}
示例#3
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);
		}