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; }
static gint xmms_faad_read_some (xmms_xform_t *xform, xmms_error_t *err) { xmms_faad_data_t *data; NeAACDecFrameInfo frameInfo; gpointer sample_buffer; guint bytes_read = 0; g_return_val_if_fail (xform, -1); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); while (data->outbuf->len == 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, err); 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) { if (data->samplerate != frameInfo.samplerate || data->channels != frameInfo.channels) { /* We should inform output to change parameters somehow */ xmms_log_error ("Output format changed in the middle of a read!"); data->samplerate = frameInfo.samplerate; data->channels = frameInfo.channels; } g_string_append_len (data->outbuf, sample_buffer, bytes_read); } else if (frameInfo.error > 0) { xmms_log_error ("ERROR %d in faad decoding: %s", frameInfo.error, NeAACDecGetErrorMessage (frameInfo.error)); return -1; } } return data->outbuf->len; }
static gint xmms_replaygain_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *error) { xmms_replaygain_data_t *data; xmms_sample_format_t fmt; gint read; g_return_val_if_fail (xform, -1); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); read = xmms_xform_read (xform, buf, len, error); if (!data->has_replaygain || !data->enabled) { return read; } fmt = xmms_xform_indata_get_int (xform, XMMS_STREAM_TYPE_FMT_FORMAT); len /= xmms_sample_size_get (fmt); data->apply (buf, len, data->gain); return read; }
static guint find_offset (xmms_xform_t *xform) { xmms_error_t err; guint8 buf[BUFFER_SIZE]; gboolean done = FALSE; guint offset = 0; gint read, i; do { xmms_error_reset (&err); read = xmms_xform_peek (xform, buf, BUFFER_SIZE, &err); /* check for failures */ if (read < 1) { return 0; } /* find first non-nul character */ for (i = 0; i < read; i++) { if (buf[i] != '\0') { done = TRUE; break; } } offset += i; /* skip over the NULs */ xmms_error_reset (&err); xmms_xform_read (xform, buf, i, &err); } while (!done); return offset; }
static gint xmms_normalize_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *error) { xmms_normalize_data_t *data; gint read; g_return_val_if_fail (xform, -1); data = xmms_xform_private_data_get (xform); read = xmms_xform_read (xform, buf, len, error); if (read > 0) { if (data->dirty) { compress_reconfigure (data->compress, data->use_anticlip, data->target, data->max_gain, data->smooth, data->buckets); data->dirty = FALSE; } compress_do (data->compress, buf, read); } return read; }
static FLAC__StreamDecoderReadStatus flac_callback_read (const FLAC__StreamDecoder *flacdecoder, FLAC__byte buffer[], read_callback_size_t *bytes, void *client_data) { xmms_xform_t *xform = (xmms_xform_t *) client_data; xmms_error_t error; gint ret; #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 g_return_val_if_fail (xform, FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR); #else g_return_val_if_fail (xform, FLAC__STREAM_DECODER_READ_STATUS_ABORT); #endif ret = xmms_xform_read (xform, (gchar *)buffer, *bytes, &error); *bytes = ret; #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 return (ret <= 0) ? FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR : FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; #else return (ret <= 0) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; #endif }
static uint32_t xmms_mp4_read_callback (void *user_data, void *buffer, uint32_t length) { xmms_xform_t *xform; xmms_mp4_data_t *data; xmms_error_t error; gint ret; g_return_val_if_fail (user_data, 0); g_return_val_if_fail (buffer, 0); xform = user_data; data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, 0); if (data->buffer_length == 0) { guint bytes_read; bytes_read = xmms_xform_read (xform, (gchar *) data->buffer, data->buffer_size, &error); if (bytes_read <= 0 && data->buffer_length == 0) { return bytes_read; } data->buffer_length += bytes_read; } ret = MIN (length, data->buffer_length); g_memmove (buffer, data->buffer, ret); g_memmove (data->buffer, data->buffer + ret, data->buffer_length - ret); data->buffer_length -= ret; return ret; }
static gint xmms_wave_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *error) { xmms_wave_data_t *data; gint ret; g_return_val_if_fail (xform, -1); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); ret = xmms_xform_read (xform, (gchar *) buf, len, error); if (ret <= 0) { return ret; } #if G_BYTE_ORDER == G_BIG_ENDIAN if (data->bits_per_sample == 16) { gint16 *s = (gint16 *) buf; gint i; for (i = 0; i < (ret / 2); i++) { s[i] = GINT16_FROM_LE (s[i]); } } #endif return ret; }
static sf_count_t xmms_sf_virtual_read (void *buffer, sf_count_t count, void *priv) { xmms_xform_t *xform = priv; gint64 ret = 0; /* Return read byte count of 0 in case of failure. */ xmms_error_t err; ret = xmms_xform_read (xform, buffer, count, &err); return ret; }
static mpc_int32_t xmms_mpc_callback_read (READER_OBJ *p_obj, void *buffer, mpc_int32_t size) { xmms_xform_t *xform = READER_DATA (p_obj); xmms_error_t err; g_return_val_if_fail (xform, -1); xmms_error_reset (&err); return xmms_xform_read (xform, (gchar *) buffer, size, &err); }
static gboolean xmms_xspf_browse (xmms_xform_t *xform, const gchar *url, xmms_error_t *error) { int ret; char buf[4096]; xmlParserCtxtPtr ctx; xmlDocPtr doc; g_return_val_if_fail (xform, FALSE); xmms_error_reset (error); ctx = xmlCreatePushParserCtxt (NULL, NULL, buf, 0, NULL); if (!ctx) { xmms_error_set (error, XMMS_ERROR_OOM, "Could not allocate xml parser"); return FALSE; } while ((ret = xmms_xform_read (xform, buf, sizeof (buf), error)) > 0) { if ((xmlParseChunk (ctx, buf, ret, 0)) != 0) { break; } } if (ret < 0) { xmms_error_set (error, XMMS_ERROR_GENERIC, "failed to read data from previous xform"); xmlFreeParserCtxt (ctx); return FALSE; } xmlParseChunk (ctx, buf, 0, 1); if (ctx->lastError.message) { xmms_error_set (error, XMMS_ERROR_INVAL, ctx->lastError.message); xmlFreeParserCtxt (ctx); return FALSE; } doc = ctx->myDoc; if (!xmms_xspf_browse_add_entries (xform, doc, error)) { xmlFreeParserCtxt (ctx); return FALSE; } xmms_error_reset (error); xmlFreeParserCtxt (ctx); return TRUE; }
static gboolean xmms_rss_browse (xmms_xform_t *xform, const gchar *url, xmms_error_t *error) { int ret; char buffer[1024]; xmlSAXHandler handler; xmlParserCtxtPtr ctx; xmms_rss_data_t data; g_return_val_if_fail (xform, FALSE); memset (&handler, 0, sizeof (handler)); memset (&data, 0, sizeof (data)); handler.startElement = (startElementSAXFunc) xmms_rss_start_element; handler.error = (errorSAXFunc) xmms_rss_error; handler.fatalError = (fatalErrorSAXFunc) xmms_rss_error; data.xform = xform; data.error = error; data.parse_failure = FALSE; xmms_error_reset (error); ctx = xmlCreatePushParserCtxt (&handler, &data, buffer, 0, NULL); if (!ctx) { xmms_error_set (error, XMMS_ERROR_OOM, "Could not allocate xml parser"); return FALSE; } while ((ret = xmms_xform_read (xform, buffer, sizeof (buffer), error)) > 0) { xmlParseChunk (ctx, buffer, ret, 0); } if (ret < 0) { xmms_error_set (error, XMMS_ERROR_GENERIC, "xmms_xform_read failed"); return FALSE; } if (data.parse_failure) return FALSE; xmlParseChunk (ctx, buffer, 0, 1); xmms_error_reset (error); xmlFreeParserCtxt (ctx); return TRUE; }
static int opus_callback_read (void *datasource, unsigned char *ptr, int size) { xmms_opus_data_t *data; xmms_xform_t *xform = datasource; xmms_error_t error; size_t ret; g_return_val_if_fail (xform, 0); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, 0); ret = xmms_xform_read (xform, ptr, size, &error); return ret; }
int CSourceAdapter::Read (void * pBuffer, unsigned int nBytesToRead, unsigned int * pBytesRead) { int ret = 0; xmms_error_t error; xmms_error_reset (&error); ret = xmms_xform_read (xform, (gchar *)pBuffer, nBytesToRead, &error); *pBytesRead = ret; return (error.code == XMMS_ERROR_NONE) ? ERROR_SUCCESS : ERROR_IO_READ; }
static size_t vorbis_callback_read (void *ptr, size_t size, size_t nmemb, void *datasource) { xmms_vorbis_data_t *data; xmms_xform_t *xform = datasource; xmms_error_t error; size_t ret; g_return_val_if_fail (xform, 0); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, 0); ret = xmms_xform_read (xform, ptr, size * nmemb, &error); return ret / size; }
gchar * xmms_xform_read_line (xmms_xform_t *xform, gchar *line, xmms_error_t *err) { gchar *p; g_return_val_if_fail (xform, NULL); g_return_val_if_fail (line, NULL); p = strchr (xform->lr.buf, '\n'); if (!p) { gint l, r; l = (XMMS_XFORM_MAX_LINE_SIZE - 1) - (xform->lr.bufend - xform->lr.buf); if (l) { r = xmms_xform_read (xform, xform->lr.bufend, l, err); if (r < 0) { return NULL; } xform->lr.bufend += r; } if (xform->lr.bufend <= xform->lr.buf) return NULL; *(xform->lr.bufend) = '\0'; p = strchr (xform->lr.buf, '\n'); if (!p) { p = xform->lr.bufend; } } if (p > xform->lr.buf && *(p-1) == '\r') { *(p-1) = '\0'; } else { *p = '\0'; } strcpy (line, xform->lr.buf); memmove (xform->lr.buf, p + 1, xform->lr.bufend - p); xform->lr.bufend -= (p - xform->lr.buf) + 1; *xform->lr.bufend = '\0'; return line; }
static gint xmms_id3v1_get_tags (xmms_xform_t *xform) { xmms_config_property_t *config; gint enabled; xmms_error_t err; gint64 res; guchar buf[128]; gint ret = 0; config = xmms_xform_config_lookup (xform, "id3v1_enable"); g_return_val_if_fail (config, -1); enabled = xmms_config_property_get_int (config); if (!enabled) { XMMS_DBG ("ID3v1 tags disabled."); return 0; } xmms_error_reset (&err); res = xmms_xform_seek (xform, -128, XMMS_XFORM_SEEK_END, &err); if (res == -1) { XMMS_DBG ("Couldn't seek - not getting id3v1 tag"); return 0; } if (xmms_xform_read (xform, buf, 128, &err) == 128) { if (xmms_id3v1_parse (xform, buf)) { ret = 128; } } else { XMMS_DBG ("Read of 128 bytes failed?!"); xmms_error_reset (&err); } res = xmms_xform_seek (xform, 0, XMMS_XFORM_SEEK_SET, &err); if (res == -1) { XMMS_DBG ("Couldn't seek after getting id3 tag?!? very bad"); return -1; } return ret; }
static void fill (xmms_xform_t *xform, xmms_ringbuf_priv_t *priv) { xmms_error_t err; char buf[4096]; int res; res = xmms_xform_read (xform, buf, sizeof (buf), &err); if (res > 0) { xmms_ringbuf_write_wait (priv->buffer, buf, res, &priv->buffer_lock); } else if (res == -1) { /* XXX copy error */ g_mutex_lock (&priv->state_lock); priv->state = STATE_WANT_STOP; } else { xmms_ringbuf_set_eos (priv->buffer, TRUE); priv->state = STATE_WANT_STOP; } }
static gint xmms_eq_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *error) { xmms_equalizer_data_t *priv; gint read, chan; g_return_val_if_fail (xform, -1); priv = xmms_xform_private_data_get (xform); g_return_val_if_fail (priv, -1); read = xmms_xform_read (xform, buf, len, error); chan = xmms_xform_indata_get_int (xform, XMMS_STREAM_TYPE_FMT_CHANNELS); if (read > 0 && priv->enabled) { iir (buf, read, chan, priv->extra_filtering); } return read; }
static FLAC__StreamDecoderReadStatus flac_callback_read (const FLAC__StreamDecoder *flacdecoder, FLAC__byte buffer[], size_t *bytes, void *client_data) { xmms_xform_t *xform = (xmms_xform_t *) client_data; xmms_error_t error; gint ret; g_return_val_if_fail (xform, FLAC__STREAM_DECODER_READ_STATUS_ABORT); ret = xmms_xform_read (xform, (gchar *)buffer, *bytes, &error); if (ret == 0) { return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; } else if (ret < 0) { return FLAC__STREAM_DECODER_READ_STATUS_ABORT; } else { *bytes = ret; return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } }
int32_t xmms_asf_read_callback (void *opaque, void *buffer, int32_t size) { xmms_xform_t *xform; xmms_asf_data_t *data; xmms_error_t error; gint ret; g_return_val_if_fail (opaque, 0); g_return_val_if_fail (buffer, 0); xform = opaque; xmms_error_reset (&error); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, 0); ret = xmms_xform_read (xform, buffer, size, &error); return ret; }
static gint xmms_ofa_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *error) { xmms_ofa_data_t *data; gint read; g_return_val_if_fail (xform, -1); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); read = xmms_xform_read (xform, buf, len, error); if (data->run_ofa && read > 0 && data->pos < data->bytes_to_read) { int l = MIN (data->bytes_to_read - data->pos, read); memcpy (data->buf + data->pos, buf, l); data->pos += l; if (data->pos == data->bytes_to_read) { g_mutex_lock (&data->mutex); data->thread_state = XMMS_OFA_CALCULATE; g_cond_signal (&data->cond); g_mutex_unlock (&data->mutex); data->run_ofa = FALSE; } } else if (data->pos == data->bytes_to_read){ if (!data->done) { g_mutex_lock (&data->mutex); if (data->thread_state == XMMS_OFA_DONE) { xmms_xform_metadata_set_str (xform, "ofa_fingerprint", data->fp); data->done = TRUE; } g_mutex_unlock (&data->mutex); } } return read; }
static gint xmms_vis_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *error) { gint read, chan; g_return_val_if_fail (xform, -1); chan = xmms_xform_indata_get_int (xform, XMMS_STREAM_TYPE_FMT_CHANNELS); /* perhaps rework this later */ if (len > XMMSC_VISUALIZATION_WINDOW_SIZE * chan * sizeof (short)) { len = XMMSC_VISUALIZATION_WINDOW_SIZE * chan * sizeof (short); } read = xmms_xform_read (xform, buf, len, error); if (read > 0) { send_data (chan, read / sizeof (short), buf); } return read; }
static int32_t wavpack_read_bytes (void *id, void *buf, int32_t bcount) { xmms_xform_t *xform = id; xmms_wavpack_data_t *data; xmms_error_t error; gint64 ret; gboolean did_pushback = FALSE; g_return_val_if_fail (xform, -1); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); /* if we have pushback data, consume it */ if (data->pushback_set && bcount > 0) { ((guint8 *)buf)[0] = data->pushback_byte; buf++; bcount--; data->pushback_set = FALSE; did_pushback = TRUE; if (bcount == 0) { return 1; } } ret = xmms_xform_read (xform, buf, bcount, &error); if (ret != -1 && did_pushback) { /* adjust return value if we consumed the pushback byte */ ret++; } return ret; }
static gint xmms_converter_plugin_read (xmms_xform_t *xform, void *buffer, gint len, xmms_error_t *error) { xmms_conv_xform_data_t *data; char buf[1024]; data = xmms_xform_private_data_get (xform); if (!data->outlen) { int r = xmms_xform_read (xform, buf, sizeof (buf), error); if (r <= 0) { return r; } xmms_sample_convert (data->conv, buf, r, &data->outbuf, &data->outlen); } len = MIN (len, data->outlen); memcpy (buffer, data->outbuf, len); data->outlen -= len; data->outbuf += len; return len; }
static gint xmms_mad_read (xmms_xform_t *xform, gpointer buf, gint len, xmms_error_t *err) { xmms_mad_data_t *data; xmms_samples16_t *out = (xmms_samples16_t *)buf; gint ret; gint j; gint read = 0; data = xmms_xform_private_data_get (xform); j = 0; while (read < len) { /* use already synthetized frame first */ if (data->synthpos < data->synth.pcm.length) { out[j++] = scale_linear (data->synth.pcm.samples[0][data->synthpos]); if (data->channels == 2) { out[j++] = scale_linear (data->synth.pcm.samples[1][data->synthpos]); read += 2 * xmms_sample_size_get (XMMS_SAMPLE_FORMAT_S16); } else { read += xmms_sample_size_get (XMMS_SAMPLE_FORMAT_S16); } data->synthpos++; continue; } /* then try to decode another frame */ if (mad_frame_decode (&data->frame, &data->stream) != -1) { /* mad_synthpop_frame - go Depeche! */ mad_synth_frame (&data->synth, &data->frame); if (data->frames_to_skip) { data->frames_to_skip--; data->synthpos = 0x7fffffff; } else if (data->samples_to_skip) { if (data->samples_to_skip > data->synth.pcm.length) { data->synthpos = 0x7fffffff; data->samples_to_skip -= data->synth.pcm.length; } else { data->synthpos = data->samples_to_skip; data->samples_to_skip = 0; } } else { if (data->samples_to_play == 0) { return read; } else if (data->samples_to_play > 0) { if (data->synth.pcm.length > data->samples_to_play) { data->synth.pcm.length = data->samples_to_play; } data->samples_to_play -= data->synth.pcm.length; } data->synthpos = 0; } continue; } /* if there is no frame to decode stream more data */ if (data->stream.next_frame) { guchar *buffer = data->buffer; const guchar *nf = data->stream.next_frame; memmove (data->buffer, data->stream.next_frame, data->buffer_length = (&buffer[data->buffer_length] - nf)); } ret = xmms_xform_read (xform, (gchar *)data->buffer + data->buffer_length, 4096 - data->buffer_length, err); if (ret <= 0) { return ret; } data->buffer_length += ret; mad_stream_buffer (&data->stream, data->buffer, data->buffer_length); } return read; }
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; }
static gint xmms_vocoder_read (xmms_xform_t *xform, xmms_sample_t *buffer, gint len, xmms_error_t *error) { xmms_vocoder_data_t *data; guint size; g_return_val_if_fail (xform, -1); data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); size = MIN (data->outbuf->len, len); while (size == 0) { int i, dpos; gint16 *samples = (gint16 *) data->iobuf; if (!data->enabled) { return xmms_xform_read (xform, buffer, len, error); } if (!data->resdata.input_frames) { dpos = pvocoder_get_chunk (data->pvoc, data->procbuf); while (dpos != 0) { int ret, read = 0; memset (data->procbuf, 0, data->bufsize * sizeof (pvocoder_sample_t)); while (read < data->bufsize * sizeof (gint16)) { ret = xmms_xform_read (xform, data->iobuf+read, data->bufsize * sizeof (gint16)-read, error); if (ret <= 0) { if (!ret && !read) { /* end of file */ return 0; } else if (ret < 0) { return ret; } break; } read += ret; } for (i=0; i<data->bufsize; i++) { data->procbuf[i] = (pvocoder_sample_t) samples[i] / 32767; } pvocoder_add_chunk (data->pvoc, data->procbuf); dpos = pvocoder_get_chunk (data->pvoc, data->procbuf); } data->resdata.data_in = data->procbuf; data->resdata.input_frames = data->winsize; } src_process (data->resampler, &data->resdata); data->resdata.data_in += data->resdata.input_frames_used * data->channels; data->resdata.input_frames -= data->resdata.input_frames_used; for (i=0; i<data->resdata.output_frames_gen * data->channels; i++) { samples[i] = data->resbuf[i] * 32767; } g_string_append_len (data->outbuf, data->iobuf, data->resdata.output_frames_gen * data->channels * sizeof (gint16)); size = MIN (data->outbuf->len, len); } memcpy (buffer, data->outbuf->str, size); g_string_erase (data->outbuf, 0, size); return size; }
static gboolean xmms_apetag_read (xmms_xform_t *xform) { guchar buffer[32], *tagdata; xmms_error_t error; guint version, tag_size, items, flags; gint64 tag_position; gint pos, i, ret; g_return_val_if_fail (xform, FALSE); /* Try to find the 32-byte footer from the end of file */ tag_position = xmms_xform_seek (xform, -32, XMMS_XFORM_SEEK_END, &error); if (tag_position < 0) { /* Seeking failed, failed to read tags */ return FALSE; } /* Read footer data if seeking was possible */ ret = xmms_xform_read (xform, buffer, 32, &error); if (ret != 32) { xmms_log_error ("Failed to read APE tag footer"); return FALSE; } /* Check that the footer is valid, if not continue searching */ if (memcmp (buffer, "APETAGEX", 8)) { /* Try to find the 32-byte footer before 128-byte ID3v1 tag */ tag_position = xmms_xform_seek (xform, -160, XMMS_XFORM_SEEK_END, &error); if (tag_position < 0) { /* Seeking failed, failed to read tags */ xmms_log_error ("Failed to seek to APE tag footer"); return FALSE; } /* Read footer data if seeking was possible */ ret = xmms_xform_read (xform, buffer, 32, &error); if (ret != 32) { xmms_log_error ("Failed to read APE tag footer"); return FALSE; } if (memcmp (buffer, "APETAGEX", 8)) { /* Didn't find any APE tag from the file */ return FALSE; } } version = xmms_apetag_get_le32 (buffer + 8); tag_size = xmms_apetag_get_le32 (buffer + 12); items = xmms_apetag_get_le32 (buffer + 16); flags = xmms_apetag_get_le32 (buffer + 20); if (flags & APE_TAG_FLAG_IS_HEADER) { /* We need a footer, not a header... */ return FALSE; } if (version != 1000 && version != 2000) { xmms_log_error ("Invalid tag version, the writer is probably corrupted!"); return FALSE; } /* Seek to the beginning of the actual tag data */ ret = xmms_xform_seek (xform, tag_position - tag_size + 32, XMMS_XFORM_SEEK_SET, &error); if (ret < 0) { xmms_log_error ("Couldn't seek to the tag starting position, returned %d", ret); return FALSE; } tagdata = g_malloc (tag_size); ret = xmms_xform_read (xform, tagdata, tag_size, &error); if (ret != tag_size) { xmms_log_error ("Couldn't read the tag data, returned %d", ret); g_free (tagdata); return FALSE; } pos = 0; for (i = 0; i < items; i++) { gint itemlen, flags; gchar *key, *item; itemlen = xmms_apetag_get_le32 (tagdata + pos); pos += 4; flags = xmms_apetag_get_le32 (tagdata + pos); pos += 4; key = (gchar *) tagdata + pos; pos += strlen (key) + 1; switch (flags & APE_TAG_FLAG_DATA_TYPE) { case APE_TAG_DATA_TYPE_UTF8: item = g_strndup ((gchar *) tagdata + pos, itemlen); break; case APE_TAG_DATA_TYPE_BINARY: item = g_malloc (itemlen); memcpy (item, tagdata + pos, itemlen); break; case APE_TAG_DATA_TYPE_LOCATOR: item = NULL; break; } if (item != NULL && !xmms_xform_metadata_mapper_match (xform, key, item, itemlen)) { if ((flags & APE_TAG_FLAG_DATA_TYPE) == APE_TAG_DATA_TYPE_UTF8) { XMMS_DBG ("Unhandled tag '%s' = '%s'", key, item); } else { XMMS_DBG ("Unhandled tag '%s' = '(binary)'", key); } } g_free (item); pos += itemlen; } g_free (tagdata); return TRUE; }
static gint xmms_mpg123_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *err) { xmms_mpg123_data_t *data; int result = MPG123_OK; size_t read = 0; data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); while (read == 0) { gint ret = 0; if (result == MPG123_NEED_MORE) { ret = xmms_xform_read (xform, data->buf, BUFSIZE, err); if (ret < 0) { return ret; } else if (ret == 0) { data->eof_found = TRUE; } } result = mpg123_decode (data->decoder, data->buf, (size_t) ret, buf, len, &read); if (result == MPG123_NEED_MORE && data->eof_found) { /* We need more data, but there's none available * so libmpg123 apparently missed an EOF */ result = MPG123_DONE; break; } else if (result != MPG123_OK && result != MPG123_NEED_MORE) { /* This is some uncommon result like EOF, handle outside * the loop */ break; } } if (result == MPG123_DONE) { /* This is just normal EOF reported from libmpg123 */ XMMS_DBG ("Got EOF while decoding stream"); return 0; } else if (result == MPG123_NEW_FORMAT) { /* FIXME: When we can handle format changes, modify this */ xmms_error_set (err, XMMS_ERROR_GENERIC, "The output format changed, XMMS2 can't handle that"); return -1; } else if (result == MPG123_ERR) { xmms_error_set (err, XMMS_ERROR_GENERIC, mpg123_strerror (data->decoder)); return -1; } return (gint) read; }