static gboolean gst_wildmidi_do_seek (GstWildmidi * wildmidi, GstEvent * event) { gdouble rate; GstFormat src_format, dst_format; GstSeekFlags flags; GstSeekType start_type, stop_type; gint64 start, stop; gboolean flush, update; #ifdef HAVE_WILDMIDI_0_2_2 gboolean accurate; #endif gboolean res; unsigned long int sample; GstSegment *segment; if (!wildmidi->song) return FALSE; gst_event_parse_seek (event, &rate, &src_format, &flags, &start_type, &start, &stop_type, &stop); /* convert the input format to samples */ dst_format = GST_FORMAT_DEFAULT; res = TRUE; if (start_type != GST_SEEK_TYPE_NONE) { res = gst_wildmidi_src_convert (wildmidi, src_format, start, &dst_format, &start); } if (res && stop_type != GST_SEEK_TYPE_NONE) { res = gst_wildmidi_src_convert (wildmidi, src_format, stop, &dst_format, &stop); } /* unsupported format */ if (!res) return res; flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH); #ifdef HAVE_WILDMIDI_0_2_2 accurate = ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE); #endif if (flush) { GST_DEBUG ("performing flush"); gst_pad_push_event (wildmidi->srcpad, gst_event_new_flush_start ()); } else { gst_pad_stop_task (wildmidi->sinkpad); } segment = wildmidi->o_segment; GST_PAD_STREAM_LOCK (wildmidi->sinkpad); if (flush) { gst_pad_push_event (wildmidi->srcpad, gst_event_new_flush_stop (TRUE)); } /* update the segment now */ gst_segment_do_seek (segment, rate, dst_format, flags, start_type, start, stop_type, stop, &update); /* we need to seek to position in the segment now, sample will be updated */ sample = segment->position; GST_OBJECT_LOCK (wildmidi); #ifdef HAVE_WILDMIDI_0_2_2 if (accurate) { WildMidi_SampledSeek (wildmidi->song, &sample); } else { WildMidi_FastSeek (wildmidi->song, &sample); } #else WildMidi_FastSeek (wildmidi->song, &sample); #endif GST_OBJECT_UNLOCK (wildmidi); segment->start = segment->time = segment->position = sample; gst_pad_push_event (wildmidi->srcpad, gst_wildmidi_get_new_segment_event (wildmidi, GST_FORMAT_TIME)); gst_pad_start_task (wildmidi->sinkpad, (GstTaskFunction) gst_wildmidi_loop, wildmidi->sinkpad, NULL); wildmidi->discont = TRUE; GST_PAD_STREAM_UNLOCK (wildmidi->sinkpad); GST_DEBUG ("seek done"); return TRUE; }
static void wildmidi_file_decode(struct decoder *decoder, const char *path_fs) { static const struct audio_format audio_format = { .sample_rate = WILDMIDI_SAMPLE_RATE, .format = SAMPLE_FORMAT_S16, .channels = 2, }; midi *wm; const struct _WM_Info *info; enum decoder_command cmd; wm = WildMidi_Open(path_fs); if (wm == NULL) return; info = WildMidi_GetInfo(wm); if (info == NULL) { WildMidi_Close(wm); return; } decoder_initialized(decoder, &audio_format, true, info->approx_total_samples / WILDMIDI_SAMPLE_RATE); do { char buffer[4096]; int len; info = WildMidi_GetInfo(wm); if (info == NULL) break; len = WildMidi_GetOutput(wm, buffer, sizeof(buffer)); if (len <= 0) break; cmd = decoder_data(decoder, NULL, buffer, len, 0); if (cmd == DECODE_COMMAND_SEEK) { unsigned long seek_where = WILDMIDI_SAMPLE_RATE * decoder_seek_where(decoder); WildMidi_SampledSeek(wm, &seek_where); decoder_command_finished(decoder); cmd = DECODE_COMMAND_NONE; } } while (cmd == DECODE_COMMAND_NONE); WildMidi_Close(wm); } static struct tag * wildmidi_tag_dup(const char *path_fs) { midi *wm; const struct _WM_Info *info; struct tag *tag; wm = WildMidi_Open(path_fs); if (wm == NULL) return NULL; info = WildMidi_GetInfo(wm); if (info == NULL) { WildMidi_Close(wm); return NULL; } tag = tag_new(); tag->time = info->approx_total_samples / WILDMIDI_SAMPLE_RATE; WildMidi_Close(wm); return tag; }