wildmidi: cleanups and fix seeking

Remove time_per_frame, it's too inaccurate.
Fix convert for -1 values.
Use scaling to convert samples to time.
Fix segment handling.
Fix seeking.
Fix buffer clipping (not yet enabled)
Protect the WildMidi library with the object lock to avoid races when changing
properties.
Fix offsets on output buffers, for raw audio the offset contains the sample
position not byte position.
Add better DISCONT handling.

Fixes #519001
This commit is contained in:
Wim Taymans 2009-09-04 17:27:52 +02:00 committed by Wim Taymans
parent e806e7aaeb
commit f874e30998
2 changed files with 189 additions and 173 deletions

View file

@ -284,7 +284,6 @@ gst_wildmidi_init (GstWildmidi * filter, GstWildmidiClass * g_class)
filter->adapter = gst_adapter_new (); filter->adapter = gst_adapter_new ();
filter->bytes_per_frame = WILDMIDI_BPS; filter->bytes_per_frame = WILDMIDI_BPS;
filter->time_per_frame = GST_SECOND / WILDMIDI_RATE;
} }
static void static void
@ -307,14 +306,14 @@ gst_wildmidi_src_convert (GstWildmidi * wildmidi,
gboolean res = TRUE; gboolean res = TRUE;
gint64 frames; gint64 frames;
if (src_format == *dest_format) { if (src_format == *dest_format || src_value == -1) {
*dest_value = src_value; *dest_value = src_value;
goto done; goto done;
} }
switch (src_format) { switch (src_format) {
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
frames = src_value / wildmidi->time_per_frame; frames = gst_util_uint64_scale_int (src_value, WILDMIDI_RATE, GST_SECOND);
break; break;
case GST_FORMAT_BYTES: case GST_FORMAT_BYTES:
frames = src_value / (wildmidi->bytes_per_frame); frames = src_value / (wildmidi->bytes_per_frame);
@ -329,7 +328,8 @@ gst_wildmidi_src_convert (GstWildmidi * wildmidi,
switch (*dest_format) { switch (*dest_format) {
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
*dest_value = frames * wildmidi->time_per_frame; *dest_value =
gst_util_uint64_scale_int (frames, GST_SECOND, WILDMIDI_RATE);
break; break;
case GST_FORMAT_BYTES: case GST_FORMAT_BYTES:
*dest_value = frames * wildmidi->bytes_per_frame; *dest_value = frames * wildmidi->bytes_per_frame;
@ -362,11 +362,13 @@ gst_wildmidi_src_query (GstPad * pad, GstQuery * query)
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_DURATION: case GST_QUERY_DURATION:
gst_query_set_duration (query, GST_FORMAT_TIME, gst_query_set_duration (query, GST_FORMAT_TIME,
wildmidi->o_len * wildmidi->time_per_frame); gst_util_uint64_scale_int (wildmidi->o_len, GST_SECOND,
WILDMIDI_RATE));
break; break;
case GST_QUERY_POSITION: case GST_QUERY_POSITION:
gst_query_set_position (query, GST_FORMAT_TIME, gst_query_set_position (query, GST_FORMAT_TIME,
wildmidi->o_segment->last_stop * wildmidi->time_per_frame); gst_util_uint64_scale_int (wildmidi->o_segment->last_stop, GST_SECOND,
WILDMIDI_RATE));
break; break;
case GST_QUERY_CONVERT: case GST_QUERY_CONVERT:
gst_query_parse_convert (query, &src_format, &src_value, gst_query_parse_convert (query, &src_format, &src_value,
@ -402,53 +404,115 @@ gst_wildmidi_src_query (GstPad * pad, GstQuery * query)
return res; return res;
} }
static GstSegment * static GstEvent *
gst_wildmidi_get_segment (GstWildmidi * wildmidi, GstFormat format, gst_wildmidi_get_new_segment_event (GstWildmidi * wildmidi, GstFormat format)
gboolean update)
{ {
gint64 start, stop, time; gint64 start, stop, time;
GstSegment *segment = gst_segment_new ();
gst_wildmidi_src_convert (wildmidi,
wildmidi->o_segment->format, wildmidi->o_segment->start, &format, &start);
if (wildmidi->o_segment->stop == GST_CLOCK_TIME_NONE) {
stop = GST_CLOCK_TIME_NONE;
} else {
gst_wildmidi_src_convert (wildmidi,
wildmidi->o_segment->format, wildmidi->o_segment->stop, &format, &stop);
}
gst_wildmidi_src_convert (wildmidi,
wildmidi->o_segment->format, wildmidi->o_segment->time, &format, &time);
gst_segment_set_newsegment_full (segment, update,
wildmidi->o_segment->rate, wildmidi->o_segment->applied_rate,
format, start, stop, time);
segment->last_stop = time;
return segment;
}
static GstEvent *
gst_wildmidi_get_new_segment_event (GstWildmidi * wildmidi, GstFormat format,
gboolean update)
{
GstSegment *segment; GstSegment *segment;
GstEvent *event; GstEvent *event;
GstFormat src_format;
segment = gst_wildmidi_get_segment (wildmidi, format, update); segment = wildmidi->o_segment;
src_format = segment->format;
event = gst_event_new_new_segment_full (update, /* convert the segment values to the target format */
segment->rate, segment->applied_rate, segment->format, gst_wildmidi_src_convert (wildmidi, src_format, segment->start, &format,
segment->start, segment->stop, segment->time); &start);
gst_wildmidi_src_convert (wildmidi, src_format, segment->stop, &format,
&stop);
gst_wildmidi_src_convert (wildmidi, src_format, segment->time, &format,
&time);
gst_segment_free (segment); event = gst_event_new_new_segment_full (FALSE,
segment->rate, segment->applied_rate, format, start, stop, time);
return event; return event;
} }
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, accurate;
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);
accurate = ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE);
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 ());
}
/* update the segment now */
gst_segment_set_seek (segment, rate, dst_format, flags,
start_type, start, stop_type, stop, &update);
/* we need to seek to last_stop in the segment now, sample will be updated */
sample = segment->last_stop;
GST_OBJECT_LOCK (wildmidi);
if (accurate) {
WildMidi_SampledSeek (wildmidi->song, &sample);
} else {
WildMidi_FastSeek (wildmidi->song, &sample);
}
GST_OBJECT_UNLOCK (wildmidi);
segment->start = segment->time = segment->last_stop = 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);
wildmidi->discont = TRUE;
GST_PAD_STREAM_UNLOCK (wildmidi->sinkpad);
GST_DEBUG ("seek done");
return TRUE;
}
static gboolean static gboolean
gst_wildmidi_src_event (GstPad * pad, GstEvent * event) gst_wildmidi_src_event (GstPad * pad, GstEvent * event)
{ {
@ -459,66 +523,7 @@ gst_wildmidi_src_event (GstPad * pad, GstEvent * event)
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK: case GST_EVENT_SEEK:
{ res = gst_wildmidi_do_seek (wildmidi, event);
gdouble rate;
GstFormat src_format, dst_format;
GstSeekFlags flags;
GstSeekType start_type, stop_type;
gint64 orig_start, start, stop;
gboolean flush, update;
if (!wildmidi->song)
break;
gst_event_parse_seek (event, &rate, &src_format, &flags,
&start_type, &orig_start, &stop_type, &stop);
dst_format = GST_FORMAT_DEFAULT;
gst_wildmidi_src_convert (wildmidi, src_format, orig_start,
&dst_format, &start);
gst_wildmidi_src_convert (wildmidi, src_format, stop, &dst_format, &stop);
flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
if (flush) {
GST_DEBUG ("performing flush");
gst_pad_push_event (wildmidi->srcpad, gst_event_new_flush_start ());
} else {
gst_pad_stop_task (wildmidi->sinkpad);
}
GST_PAD_STREAM_LOCK (wildmidi->sinkpad);
if (flush) {
gst_pad_push_event (wildmidi->srcpad, gst_event_new_flush_stop ());
}
gst_segment_set_seek (wildmidi->o_segment, rate, dst_format, flags,
start_type, start, stop_type, stop, &update);
if ((flags && GST_SEEK_FLAG_SEGMENT) == GST_SEEK_FLAG_SEGMENT) {
GST_DEBUG_OBJECT (wildmidi, "received segment seek %d, %d",
(gint) start_type, (gint) stop_type);
} else {
GST_DEBUG_OBJECT (wildmidi, "received normal seek %d",
(gint) start_type);
update = FALSE;
}
gst_pad_push_event (wildmidi->srcpad,
gst_wildmidi_get_new_segment_event (wildmidi, GST_FORMAT_TIME,
update));
wildmidi->o_seek = TRUE;
gst_pad_start_task (wildmidi->sinkpad,
(GstTaskFunction) gst_wildmidi_loop, wildmidi->sinkpad);
GST_PAD_STREAM_UNLOCK (wildmidi->sinkpad);
GST_DEBUG ("seek done");
}
res = TRUE;
break; break;
default: default:
break; break;
@ -551,33 +556,41 @@ gst_wildmidi_activatepull (GstPad * pad, gboolean active)
static GstBuffer * static GstBuffer *
gst_wildmidi_clip_buffer (GstWildmidi * wildmidi, GstBuffer * buffer) gst_wildmidi_clip_buffer (GstWildmidi * wildmidi, GstBuffer * buffer)
{ {
gint64 start, stop;
gint64 new_start, new_stop; gint64 new_start, new_stop;
gint64 offset, length; gint64 offset, length;
GstBuffer *out; GstBuffer *out;
guint64 bpf;
/* clipping disabled for now */
return buffer; return buffer;
start = GST_BUFFER_OFFSET (buffer);
stop = GST_BUFFER_OFFSET_END (buffer);
if (!gst_segment_clip (wildmidi->o_segment, GST_FORMAT_DEFAULT, if (!gst_segment_clip (wildmidi->o_segment, GST_FORMAT_DEFAULT,
GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer), start, stop, &new_start, &new_stop)) {
&new_start, &new_stop)) {
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
return NULL; return NULL;
} }
if (GST_BUFFER_OFFSET (buffer) == new_start && if (start == new_start && stop == new_stop)
GST_BUFFER_OFFSET_END (buffer) == new_stop)
return buffer; return buffer;
offset = new_start - GST_BUFFER_OFFSET (buffer);
offset = new_start - start;
length = new_stop - new_start; length = new_stop - new_start;
out = gst_buffer_create_sub (buffer, offset * wildmidi->bytes_per_frame, bpf = wildmidi->bytes_per_frame;
length * wildmidi->bytes_per_frame); out = gst_buffer_create_sub (buffer, offset * bpf, length * bpf);
GST_BUFFER_OFFSET (out) = new_start; GST_BUFFER_OFFSET (out) = new_start;
GST_BUFFER_OFFSET_END (out) = new_stop; GST_BUFFER_OFFSET_END (out) = new_stop;
GST_BUFFER_TIMESTAMP (out) = new_start * wildmidi->time_per_frame; GST_BUFFER_TIMESTAMP (out) =
GST_BUFFER_DURATION (out) = (new_stop - new_start) * wildmidi->time_per_frame; gst_util_uint64_scale_int (new_start, GST_SECOND, WILDMIDI_RATE);
GST_BUFFER_DURATION (out) =
gst_util_uint64_scale_int (new_stop, GST_SECOND, WILDMIDI_RATE) -
GST_BUFFER_TIMESTAMP (out);
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
@ -591,44 +604,50 @@ gst_wildmidi_get_buffer (GstWildmidi * wildmidi)
size_t bytes_read; size_t bytes_read;
gint64 samples; gint64 samples;
GstBuffer *buffer; GstBuffer *buffer;
GstSegment *segment;
guint8 *data;
guint size;
guint bpf;
buffer = gst_buffer_new_and_alloc (256 * wildmidi->bytes_per_frame); bpf = wildmidi->bytes_per_frame;
bytes_read = buffer = gst_buffer_new_and_alloc (256 * bpf);
WildMidi_GetOutput (wildmidi->song, (char *) GST_BUFFER_DATA (buffer),
(unsigned long int) GST_BUFFER_SIZE (buffer)); data = GST_BUFFER_DATA (buffer);
size = GST_BUFFER_SIZE (buffer);
GST_OBJECT_LOCK (wildmidi);
bytes_read = WildMidi_GetOutput (wildmidi->song, (char *) data,
(unsigned long int) size);
GST_OBJECT_UNLOCK (wildmidi);
if (bytes_read == 0) { if (bytes_read == 0) {
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
return NULL; return NULL;
} }
GST_BUFFER_OFFSET (buffer) = /* adjust buffer size */
wildmidi->o_segment->last_stop * wildmidi->bytes_per_frame; size = GST_BUFFER_SIZE (buffer) = bytes_read;
segment = wildmidi->o_segment;
GST_BUFFER_OFFSET (buffer) = segment->last_stop;
GST_BUFFER_TIMESTAMP (buffer) = GST_BUFFER_TIMESTAMP (buffer) =
wildmidi->o_segment->last_stop * wildmidi->time_per_frame; gst_util_uint64_scale_int (segment->last_stop, GST_SECOND, WILDMIDI_RATE);
if (bytes_read < GST_BUFFER_SIZE (buffer)) { samples = size / bpf;
GstBuffer *old = buffer; segment->last_stop += samples;
buffer = gst_buffer_create_sub (buffer, 0, bytes_read); GST_BUFFER_OFFSET_END (buffer) = segment->last_stop;
gst_buffer_unref (old); GST_BUFFER_DURATION (buffer) =
} gst_util_uint64_scale_int (segment->last_stop, GST_SECOND,
WILDMIDI_RATE) - GST_BUFFER_TIMESTAMP (buffer);
samples = GST_BUFFER_SIZE (buffer) / wildmidi->bytes_per_frame;
wildmidi->o_segment->last_stop += samples;
GST_BUFFER_OFFSET_END (buffer) =
wildmidi->o_segment->last_stop * wildmidi->bytes_per_frame;
GST_BUFFER_DURATION (buffer) = samples * wildmidi->time_per_frame;
GST_DEBUG_OBJECT (wildmidi, GST_DEBUG_OBJECT (wildmidi,
"generated buffer %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "buffer ts: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT
" (%d samples)", " (%d samples)",
GST_TIME_ARGS ((guint64) GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
GST_TIME_ARGS (((guint64) (GST_BUFFER_TIMESTAMP (buffer) + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)), samples);
GST_BUFFER_DURATION (buffer)))), samples);
return gst_wildmidi_clip_buffer (wildmidi, buffer); return gst_wildmidi_clip_buffer (wildmidi, buffer);
} }
@ -647,13 +666,11 @@ gst_wildmidi_parse_song (GstWildmidi * wildmidi)
data = gst_adapter_take (wildmidi->adapter, size); data = gst_adapter_take (wildmidi->adapter, size);
/* this method takes our memory block */ /* this method takes our memory block */
GST_OBJECT_LOCK (wildmidi);
wildmidi->song = WildMidi_OpenBuffer (data, size); wildmidi->song = WildMidi_OpenBuffer (data, size);
if (!wildmidi->song) { if (!wildmidi->song)
GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), goto open_failed;
("Unable to parse midi"));
return GST_FLOW_ERROR;
}
WildMidi_LoadSamples (wildmidi->song); WildMidi_LoadSamples (wildmidi->song);
@ -663,21 +680,33 @@ gst_wildmidi_parse_song (GstWildmidi * wildmidi)
wildmidi->high_quality); wildmidi->high_quality);
info = WildMidi_GetInfo (wildmidi->song); info = WildMidi_GetInfo (wildmidi->song);
GST_OBJECT_UNLOCK (wildmidi);
wildmidi->o_len = info->approx_total_samples; wildmidi->o_len = info->approx_total_samples;
outcaps = gst_caps_copy (gst_pad_get_pad_template_caps (wildmidi->srcpad)); outcaps = gst_caps_copy (gst_pad_get_pad_template_caps (wildmidi->srcpad));
gst_pad_set_caps (wildmidi->srcpad, outcaps); gst_pad_set_caps (wildmidi->srcpad, outcaps);
gst_caps_unref (outcaps); gst_caps_unref (outcaps);
/* we keep an internal segment in samples */
gst_segment_set_newsegment (wildmidi->o_segment, FALSE, 1.0, gst_segment_set_newsegment (wildmidi->o_segment, FALSE, 1.0,
GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0); GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0);
gst_pad_push_event (wildmidi->srcpad, gst_pad_push_event (wildmidi->srcpad,
gst_wildmidi_get_new_segment_event (wildmidi, GST_FORMAT_TIME, FALSE)); gst_wildmidi_get_new_segment_event (wildmidi, GST_FORMAT_TIME));
GST_DEBUG_OBJECT (wildmidi, "Parsing song done"); GST_DEBUG_OBJECT (wildmidi, "Parsing song done");
return GST_FLOW_OK; return GST_FLOW_OK;
/* ERRORS */
open_failed:
{
GST_OBJECT_UNLOCK (wildmidi);
GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL),
("Unable to parse midi data"));
return GST_FLOW_ERROR;
}
} }
static GstFlowReturn static GstFlowReturn
@ -686,27 +715,12 @@ gst_wildmidi_do_play (GstWildmidi * wildmidi)
GstBuffer *out; GstBuffer *out;
GstFlowReturn ret; GstFlowReturn ret;
if (wildmidi->o_seek) {
unsigned long int sample;
/* perform a seek internally */
sample = wildmidi->o_segment->time;
if (wildmidi->accurate_seek) {
WildMidi_SampledSeek (wildmidi->song, &sample);
} else {
WildMidi_FastSeek (wildmidi->song, &sample);
}
wildmidi->o_segment->last_stop = wildmidi->o_segment->time = sample;
}
if (!(out = gst_wildmidi_get_buffer (wildmidi))) if (!(out = gst_wildmidi_get_buffer (wildmidi)))
goto eos; goto eos;
if (wildmidi->o_seek) { if (wildmidi->discont) {
GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DISCONT); GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DISCONT);
wildmidi->o_seek = FALSE; wildmidi->discont = FALSE;
} }
gst_buffer_set_caps (out, GST_PAD_CAPS (wildmidi->srcpad)); gst_buffer_set_caps (out, GST_PAD_CAPS (wildmidi->srcpad));
@ -718,7 +732,6 @@ gst_wildmidi_do_play (GstWildmidi * wildmidi)
eos: eos:
{ {
GST_LOG_OBJECT (wildmidi, "Song ended"); GST_LOG_OBJECT (wildmidi, "Song ended");
wildmidi->o_seek = FALSE;
return GST_FLOW_UNEXPECTED; return GST_FLOW_UNEXPECTED;
} }
} }
@ -782,7 +795,7 @@ gst_wildmidi_loop (GstPad * sinkpad)
wildmidi->state = GST_WILDMIDI_STATE_PARSE; wildmidi->state = GST_WILDMIDI_STATE_PARSE;
} else if (ret != GST_FLOW_OK) { } else if (ret != GST_FLOW_OK) {
GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL),
("Unable to load song")); ("Unable to read song"));
goto pause; goto pause;
} else { } else {
GST_DEBUG_OBJECT (wildmidi, "pushing buffer"); GST_DEBUG_OBJECT (wildmidi, "pushing buffer");
@ -792,15 +805,11 @@ gst_wildmidi_loop (GstPad * sinkpad)
break; break;
} }
case GST_WILDMIDI_STATE_PARSE: case GST_WILDMIDI_STATE_PARSE:
{ ret = gst_wildmidi_parse_song (wildmidi);
if (!wildmidi->song) { if (ret != GST_FLOW_OK)
ret = gst_wildmidi_parse_song (wildmidi); goto pause;
if (ret != GST_FLOW_OK)
goto pause;
}
wildmidi->state = GST_WILDMIDI_STATE_PLAY; wildmidi->state = GST_WILDMIDI_STATE_PLAY;
break; break;
}
case GST_WILDMIDI_STATE_PLAY: case GST_WILDMIDI_STATE_PLAY:
ret = gst_wildmidi_do_play (wildmidi); ret = gst_wildmidi_do_play (wildmidi);
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
@ -848,6 +857,7 @@ gst_wildmidi_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED:
wildmidi->offset = 0; wildmidi->offset = 0;
wildmidi->state = GST_WILDMIDI_STATE_LOAD; wildmidi->state = GST_WILDMIDI_STATE_LOAD;
wildmidi->discont = FALSE;
break; break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break; break;
@ -861,9 +871,11 @@ gst_wildmidi_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_OBJECT_LOCK (wildmidi);
if (wildmidi->song) if (wildmidi->song)
WildMidi_Close (wildmidi->song); WildMidi_Close (wildmidi->song);
wildmidi->song = NULL; wildmidi->song = NULL;
GST_OBJECT_UNLOCK (wildmidi);
gst_adapter_clear (wildmidi->adapter); gst_adapter_clear (wildmidi->adapter);
break; break;
case GST_STATE_CHANGE_READY_TO_NULL: case GST_STATE_CHANGE_READY_TO_NULL:
@ -887,16 +899,20 @@ gst_wildmidi_set_property (GObject * object, guint prop_id,
switch (prop_id) { switch (prop_id) {
case ARG_LINEAR_VOLUME: case ARG_LINEAR_VOLUME:
GST_OBJECT_LOCK (object);
wildmidi->linear_volume = g_value_get_boolean (value); wildmidi->linear_volume = g_value_get_boolean (value);
if (wildmidi->song) if (wildmidi->song)
WildMidi_SetOption (wildmidi->song, WM_MO_LINEAR_VOLUME, WildMidi_SetOption (wildmidi->song, WM_MO_LINEAR_VOLUME,
wildmidi->linear_volume); wildmidi->linear_volume);
GST_OBJECT_UNLOCK (object);
break; break;
case ARG_HIGH_QUALITY: case ARG_HIGH_QUALITY:
GST_OBJECT_LOCK (object);
wildmidi->high_quality = g_value_get_boolean (value); wildmidi->high_quality = g_value_get_boolean (value);
if (wildmidi->song) if (wildmidi->song)
WildMidi_SetOption (wildmidi->song, WM_MO_EXPENSIVE_INTERPOLATION, WildMidi_SetOption (wildmidi->song, WM_MO_EXPENSIVE_INTERPOLATION,
wildmidi->high_quality); wildmidi->high_quality);
GST_OBJECT_UNLOCK (object);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -916,10 +932,14 @@ gst_wildmidi_get_property (GObject * object, guint prop_id,
switch (prop_id) { switch (prop_id) {
case ARG_LINEAR_VOLUME: case ARG_LINEAR_VOLUME:
GST_OBJECT_LOCK (object);
g_value_set_boolean (value, wildmidi->linear_volume); g_value_set_boolean (value, wildmidi->linear_volume);
GST_OBJECT_UNLOCK (object);
break; break;
case ARG_HIGH_QUALITY: case ARG_HIGH_QUALITY:
GST_OBJECT_LOCK (object);
g_value_set_boolean (value, wildmidi->high_quality); g_value_set_boolean (value, wildmidi->high_quality);
GST_OBJECT_UNLOCK (object);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);

View file

@ -66,16 +66,12 @@ struct _GstWildmidi
guint64 offset; guint64 offset;
/* output data */ /* output data */
gboolean o_new_segment, o_seek; gboolean discont;
GstSegment o_segment[1]; GstSegment o_segment[1];
gint64 o_len; gint64 o_len;
/* format of the stream */ /* format of the stream */
gint64 bytes_per_frame; guint bytes_per_frame;
GstClockTime time_per_frame;
/* options */
gboolean accurate_seek;
/* wildmidi settings */ /* wildmidi settings */
gboolean high_quality; gboolean high_quality;