static struct playlist_provider * playlist_list_open_stream_suffix(struct input_stream *is, const char *suffix) { struct playlist_provider *playlist; assert(is != NULL); assert(suffix != NULL); for (unsigned i = 0; playlist_plugins[i] != NULL; ++i) { const struct playlist_plugin *plugin = playlist_plugins[i]; if (playlist_plugins_enabled[i] && plugin->open_stream != NULL && plugin->suffixes != NULL && string_array_contains(plugin->suffixes, suffix)) { /* rewind the stream, so each plugin gets a fresh start */ input_stream_seek(is, 0, SEEK_SET, NULL); playlist = playlist_plugin_open_stream(plugin, is); if (playlist != NULL) return playlist; } } return NULL; }
static bool decoder_stream_decode(const struct decoder_plugin *plugin, struct decoder *decoder, struct input_stream *input_stream) { assert(plugin != NULL); assert(plugin->stream_decode != NULL); assert(decoder != NULL); assert(decoder->stream_tag == NULL); assert(decoder->decoder_tag == NULL); assert(input_stream != NULL); assert(input_stream->ready); assert(decoder->dc->state == DECODE_STATE_START); g_debug("probing plugin %s", plugin->name); if (decoder->dc->command == DECODE_COMMAND_STOP) return true; /* rewind the stream, so each plugin gets a fresh start */ input_stream_seek(input_stream, 0, SEEK_SET, NULL); decoder_unlock(decoder->dc); decoder_plugin_stream_decode(plugin, decoder, input_stream); decoder_lock(decoder->dc); assert(decoder->dc->state == DECODE_STATE_START || decoder->dc->state == DECODE_STATE_DECODE); return decoder->dc->state != DECODE_STATE_START; }
/** * Skip some bytes from the #input_stream. */ static bool dsdiff_skip(struct decoder *decoder, struct input_stream *is, goffset delta) { assert(delta >= 0); if (delta == 0) return true; if (is->seekable) return input_stream_seek(is, delta, SEEK_CUR, NULL); char buffer[8192]; while (delta > 0) { size_t length = sizeof(buffer); if ((goffset)length > delta) length = delta; size_t nbytes = decoder_read(decoder, is, buffer, length); if (nbytes == 0) return false; delta -= nbytes; } return true; }
static void pcm_stream_decode(struct decoder *decoder, struct input_stream *is) { static const struct audio_format audio_format = { .sample_rate = 44100, .format = SAMPLE_FORMAT_S16, .channels = 2, }; GError *error = NULL; enum decoder_command cmd; double time_to_size = audio_format_time_to_size(&audio_format); float total_time = -1; if (is->size >= 0) total_time = is->size / time_to_size; decoder_initialized(decoder, &audio_format, is->seekable, total_time); do { char buffer[4096]; size_t nbytes = decoder_read(decoder, is, buffer, sizeof(buffer)); if (nbytes == 0 && input_stream_eof(is)) break; cmd = nbytes > 0 ? decoder_data(decoder, is, buffer, nbytes, 0) : decoder_get_command(decoder); if (cmd == DECODE_COMMAND_SEEK) { goffset offset = (goffset)(time_to_size * decoder_seek_where(decoder)); if (input_stream_seek(is, offset, SEEK_SET, &error)) { decoder_command_finished(decoder); } else { g_warning("seeking failed: %s", error->message); g_error_free(error); decoder_seek_error(decoder); } cmd = DECODE_COMMAND_NONE; } } while (cmd == DECODE_COMMAND_NONE); } static const char *const pcm_mime_types[] = { /* for streams obtained by the cdio_paranoia input plugin */ "audio/x-mpd-cdda-pcm", NULL }; const struct decoder_plugin pcm_decoder_plugin = { .name = "pcm", .stream_decode = pcm_stream_decode, .mime_types = pcm_mime_types, };
static bool mp3_seek(struct mp3_data *data, long offset) { if (!input_stream_seek(data->input_stream, offset, SEEK_SET)) return false; mad_stream_buffer(&data->stream, data->input_buffer, 0); (data->stream).error = 0; return true; }
static long audiofile_file_seek(AFvirtualfile *vfile, long offset, int is_relative) { struct input_stream *is = (struct input_stream *) vfile->closure; int whence = (is_relative ? SEEK_CUR : SEEK_SET); if (input_stream_seek(is, offset, whence)) { return is->offset; } else { return -1; } }
static sf_count_t sndfile_vio_seek(sf_count_t offset, int whence, void *user_data) { struct input_stream *is = user_data; bool success; success = input_stream_seek(is, offset, whence, NULL); if (!success) return -1; return is->offset; }
/** * Skip the #input_stream to the specified offset. */ static bool dsdiff_skip_to(struct decoder *decoder, struct input_stream *is, goffset offset) { if (is->seekable) return input_stream_seek(is, offset, SEEK_SET, NULL); if (is->offset > offset) return false; char buffer[8192]; while (is->offset < offset) { size_t length = sizeof(buffer); if (offset - is->offset < (goffset)length) length = offset - is->offset; size_t nbytes = decoder_read(decoder, is, buffer, length); if (nbytes == 0) return false; } assert(is->offset == offset); return true; }
bool song_file_update(struct song *song) { const char *suffix; char *path_fs; const struct decoder_plugin *plugin; struct stat st; struct input_stream *is = NULL; assert(song_is_file(song)); /* check if there's a suffix and a plugin */ suffix = uri_get_suffix(song->uri); if (suffix == NULL) return false; plugin = decoder_plugin_from_suffix(suffix, NULL); if (plugin == NULL) return false; path_fs = map_song_fs(song); if (path_fs == NULL) return false; if (song->tag != NULL) { tag_free(song->tag); song->tag = NULL; } if (stat(path_fs, &st) < 0 || !S_ISREG(st.st_mode)) { g_free(path_fs); return false; } song->mtime = st.st_mtime; do { /* load file tag */ song->tag = decoder_plugin_tag_dup(plugin, path_fs); if (song->tag != NULL) break; /* fall back to stream tag */ if (plugin->stream_tag != NULL) { /* open the input_stream (if not already open) */ if (is == NULL) is = input_stream_open(path_fs, NULL); /* now try the stream_tag() method */ if (is != NULL) { song->tag = decoder_plugin_stream_tag(plugin, is); if (song->tag != NULL) break; input_stream_seek(is, 0, SEEK_SET, NULL); } } plugin = decoder_plugin_from_suffix(suffix, plugin); } while (plugin != NULL); if (is != NULL) input_stream_close(is); if (song->tag != NULL && tag_is_empty(song->tag)) song->tag = tag_fallback(path_fs, song->tag); g_free(path_fs); return song->tag != NULL; }
static int wavpack_input_set_pos_rel(void *id, int32_t delta, int mode) { return input_stream_seek(wpin(id)->is, delta, mode) ? 0 : -1; }
static int wavpack_input_set_pos_abs(void *id, uint32_t pos) { return input_stream_seek(wpin(id)->is, pos, SEEK_SET) ? 0 : -1; }