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; }
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; }
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); }