+ simplifying the filter's structure, but it's still not working perfectly + starting to wonder if/how midi integrati...

Original commit message from CVS:
+ simplifying the filter's structure, but it's still not working perfectly
+ starting to wonder if/how midi integration is possible ...
This commit is contained in:
Leif Johnson 2003-06-16 22:20:52 +00:00
parent bea8637738
commit 7e761258c1
4 changed files with 199 additions and 216 deletions

View file

@ -3,24 +3,29 @@
#include <gtk/gtk.h>
#include <gst/gst.h>
#define NUM_BEATS 16
#define SPEED 1e-9
#define NUM_BEATS 12
GtkWidget *window, *vbox, *beat_box, *button_box;
GtkWidget *play_button, *clear_button, *reset_button, *quit_button;
GtkWidget **beat_button;
GtkWidget *speed_scale;
GtkObject *speed_adj;
GstElement *src, *mad, *pod, *osssink, *pipeline;
GstElement *src, *mad, *pod, *sink, *pipeline;
GstClock *element_clock;
GSList *beats;
guint32 *beats;
void
played (GstElement *pod, gpointer data)
{
g_print("Played beat at %u\n",
((guint) (gst_clock_get_time(element_clock) *
(GTK_ADJUSTMENT(speed_adj))->value * SPEED)) % NUM_BEATS);
gint i;
g_print("Played beat at %02u, beats are ",
(guint) (gst_clock_get_time(element_clock) / GST_SECOND *
(GTK_ADJUSTMENT(speed_adj))->value) % NUM_BEATS);
for (i = 0; i <= NUM_BEATS / 32; i++) g_print ("%08x ", beats[i]);
g_print("\n");
}
void
@ -47,18 +52,19 @@ reset (GtkButton *button, gpointer data)
void
beat (GtkToggleButton *button, gpointer data)
{
guint b = GPOINTER_TO_UINT(data);
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
beats = g_slist_append(beats, data);
beats[b / 32] |= 1 << (b % 32);
else
beats = g_slist_remove(beats, data);
g_object_set(G_OBJECT(pod), "tick-list", beats, NULL);
beats[b / 32] &= ~ (1 << (b % 32));
}
void
speed (GtkAdjustment *adjustment, gpointer data)
{
g_object_set(G_OBJECT(pod), "clock-speed", adjustment->value * SPEED, NULL);
/*gst_clock_set_speed(element_clock, adjustment->value * SPEED);*/
g_object_set(G_OBJECT(pod), "tick-rate", adjustment->value, NULL);
/*gst_clock_set_speed(element_clock, adjustment->value);*/
}
void
@ -67,17 +73,21 @@ setup_pipeline (gchar *filename)
src = gst_element_factory_make("filesrc", "filesrc");
mad = gst_element_factory_make("mad", "mad");
pod = gst_element_factory_make("playondemand", "playondemand");
osssink = gst_element_factory_make("osssink", "osssink");
sink = gst_element_factory_make("alsasink", "alsasink");
g_object_set(G_OBJECT(src), "location", filename, NULL);
g_object_set(G_OBJECT(osssink), "fragment", 0x00180008, NULL);
g_object_set(G_OBJECT(sink), "period-count", 32,
"period-size", 512, NULL);
g_object_set(G_OBJECT(pod), "total-ticks", NUM_BEATS,
"clock-speed", SPEED, NULL);
"tick-rate", 1.0,
"max-plays", NUM_BEATS * 2, NULL);
g_object_get(G_OBJECT(pod), "ticks", &beats, NULL);
pipeline = gst_pipeline_new("app");
gst_bin_add_many(GST_BIN(pipeline), src, mad, pod, osssink, NULL);
gst_element_link_many(src, mad, pod, osssink, NULL);
gst_bin_add_many(GST_BIN(pipeline), src, mad, pod, sink, NULL);
gst_element_link_many(src, mad, pod, sink, NULL);
element_clock = gst_bin_get_clock(GST_BIN(pipeline));
gst_element_set_clock(GST_ELEMENT(pod), element_clock);
@ -106,9 +116,9 @@ setup_gui (void)
quit_button = gtk_button_new_with_label("Quit");
for (i = 0; i < NUM_BEATS; i++)
beat_button[i] = gtk_toggle_button_new_with_label(g_strdup_printf("%2d", i));
beat_button[i] = gtk_toggle_button_new_with_label(g_strdup_printf("%2d", i+1));
speed_adj = gtk_adjustment_new(1, 0.0, 2, 0.01, 0.1, 0.0);
speed_adj = gtk_adjustment_new(1, 0.0, 10.0, 0.1, 1.0, 0.0);
speed_scale = gtk_hscale_new(GTK_ADJUSTMENT(speed_adj));
gtk_scale_set_digits(GTK_SCALE(speed_scale), 4);
gtk_range_set_update_policy(GTK_RANGE(speed_scale), GTK_UPDATE_DISCONTINUOUS);
@ -140,19 +150,7 @@ setup_gui (void)
g_signal_connect(G_OBJECT(beat_button[i]), "toggled", G_CALLBACK(beat), GUINT_TO_POINTER(i));
/* show the gui. */
gtk_widget_show(play_button);
gtk_widget_show(clear_button);
gtk_widget_show(reset_button);
gtk_widget_show(quit_button);
for (i = 0; i < NUM_BEATS; i++)
gtk_widget_show(beat_button[i]);
gtk_widget_show(beat_box);
gtk_widget_show(button_box);
gtk_widget_show(speed_scale);
gtk_widget_show(vbox);
gtk_widget_show(window);
gtk_widget_show_all(window);
gtk_idle_add((GtkFunction)gst_bin_iterate, pipeline);
}

View file

@ -5,18 +5,23 @@ _TYPE_ *data_in, *data_out, *filter_data;
filter_data = (_TYPE_ *) filter->buffer;
num_filter = filter->buffer_bytes / sizeof(_TYPE_);
/******************************************************************************/
/* see if we've got any events coming through ... */
do {
while (GST_IS_EVENT(in)) {
/****************************************************************************/
/* see if we've got any events coming through ... */
while (! filter->eos && GST_IS_EVENT(in)) {
if (GST_EVENT_TYPE(in) == GST_EVENT_EOS) {
gst_event_unref(in);
filter->eos = TRUE;
} else if ((GST_EVENT_TYPE(in) == GST_EVENT_SEEK) ||
(GST_EVENT_TYPE(in) == GST_EVENT_FLUSH)) {
filter->eos = FALSE;
filter->write = 0;
} else {
if ((GST_EVENT_TYPE(in) == GST_EVENT_SEEK) ||
(GST_EVENT_TYPE(in) == GST_EVENT_FLUSH))
filter->write = 0;
gst_pad_push(filter->srcpad, in);
}
@ -24,76 +29,81 @@ do {
}
/****************************************************************************/
/* first handle data from the input buffer. */
/* handle data from the input buffer. */
/* only update the input if there hasn't been an eos yet. */
if (! filter->eos) {
register guint j, w = filter->write;
data_in = (_TYPE_ *) GST_BUFFER_DATA(in);
num_in = GST_BUFFER_SIZE(in) / sizeof(_TYPE_);
w = filter->write;
for (j = 0; (j < num_in) && (w+j < num_filter); j++)
filter_data[w+j] = data_in[j];
/* copy the input data to the filter's internal buffer. */
for (j = 0; (j < num_in) && ((w + j) < num_filter); j++)
filter_data[(w + j) % num_filter] = data_in[j];
filter->write += j;
filter->write = (w + j) % num_filter;
if ((w + j) >= num_filter)
filter->eos = TRUE;
if (filter->write >= num_filter) filter->eos = TRUE;
out = in;
} else {
j = num_filter;
w = 0;
out = gst_buffer_new_from_pool(filter->bufpool, 0, 0);
}
/****************************************************************************/
/* check to see if we have to add a new play pointer. */
/* check to see if we have to add new play pointers. */
if (filter->clock) {
current_tick = ((guint) (gst_clock_get_time(filter->clock) *
filter->clock_speed)) % filter->total_ticks;
register gint t, tick_offset;
if (current_tick != last_tick) {
/* now we go through the tick list and play samples */
tick_list = filter->tick_list;
while (tick_list) {
tick = GPOINTER_TO_UINT(tick_list->data);
if (current_tick == tick)
play_on_demand_add_play_pointer(filter, 0);
else if (GST_POD_TICK_ELAPSED(tick, current_tick, last_tick))
play_on_demand_add_play_pointer(filter, GST_POD_SAMPLE_OFFSET(filter, current_tick - tick));
tick_list = g_slist_next(tick_list);
}
last_tick = current_tick;
guint total_ticks = filter->total_ticks;
guint current_tick = \
((guint) (gst_clock_get_time(filter->clock) * filter->tick_rate /
GST_SECOND)) % total_ticks;
/* for some reason modulo arithmetic isn't working for me here, i suspect
some unsigned/signed voodoo. but it's probably safe to do this with an if
statement since it doesn't happen all that often ... */
tick_offset = current_tick - last_tick;
if (tick_offset < 0) tick_offset += total_ticks;
for (tick_offset -= 1, t = current_tick - tick_offset;
tick_offset >= 0;
tick_offset--, t--) {
if (t < 0) t += total_ticks;
if (filter->ticks[t / 32] & (1 << t % 32))
play_on_demand_add_play_pointer(
filter, filter->rate * tick_offset / filter->tick_rate);
}
last_tick = current_tick;
}
/****************************************************************************/
/* now handle output data. */
/* handle output data. */
data_out = (_TYPE_ *) GST_BUFFER_DATA(out);
num_out = GST_BUFFER_SIZE(out) / sizeof(_TYPE_);
{
register guint k, p;
for (k = 0; k < num_out; k++)
data_out[k] = zero;
data_out = (_TYPE_ *) GST_BUFFER_DATA(out);
num_out = GST_BUFFER_SIZE(out) / sizeof(_TYPE_);
/* output play pointer data. */
if (! filter->mute)
for (t = 0; t < filter->max_plays; t++) {
offset = filter->plays[t];
for (k = 0; k < num_out; k++) data_out[k] = zero;
for (p = 0; p < filter->max_plays; p++) {
guint offset = filter->plays[p];
if (offset != G_MAXUINT) {
for (k = 0; (k < num_out) && (offset + k < num_filter); k++)
data_out[k] = CLAMP(data_out[k] + filter_data[offset + k], min, max);
if ((offset + k) == num_filter)
filter->plays[t] = G_MAXUINT;
else
filter->plays[t] = offset + k;
/* only copy audio data if the element's not muted. */
if (! filter->mute)
for (k = 0; (k < num_out) && (offset+k < num_filter); k++)
data_out[k] = CLAMP(data_out[k] + filter_data[offset+k], min, max);
/* update the play pointer. k > 0 even if the filter is muted. */
filter->plays[p] = (offset+k >= num_filter) ? G_MAXUINT : offset + k;
}
}
@ -102,9 +112,8 @@ do {
gst_pad_push(filter->srcpad, out);
if (! filter->eos)
in = gst_pad_pull(filter->sinkpad);
in = (! filter->eos) ? gst_pad_pull(filter->sinkpad) : NULL;
gst_element_interrupt (GST_ELEMENT (filter));
if (gst_element_interrupt (GST_ELEMENT (filter))) break;
} while (TRUE);

View file

@ -24,11 +24,14 @@
#include "gstplayondemand.h"
/* in these files, a 'tick' is a discrete unit of time, usually around the 1ms
* range. a tick is not divisible into smaller units of time. 1ms is probably
* way beyond what a real computer can actually keep track of, but hey ... */
/* some default values */
#define GST_POD_MAX_PLAYS 100 /* maximum simultaneous plays */
#define GST_POD_BUFFER_TIME 5.0 /* buffer length in seconds */
#define GST_POD_CLOCK_SPEED 1e-8 /* 0.1 sec/tick default */
#define GST_POD_TICK_RATE 1e-6 /* ticks per second */
/* buffer pool fallback values ... use if no buffer pool is available */
#define GST_POD_BUFPOOL_SIZE 4096
@ -88,6 +91,7 @@ static void play_on_demand_class_init (GstPlayOnDemandClass *klass);
static void play_on_demand_init (GstPlayOnDemand *filter);
static void play_on_demand_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void play_on_demand_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static void play_on_demand_dispose (GObject *object);
/* GStreamer functionality */
static GstBufferPool* play_on_demand_get_bufferpool (GstPad *pad);
@ -144,9 +148,9 @@ enum {
PROP_MUTE,
PROP_BUFFER_TIME,
PROP_MAX_PLAYS,
PROP_CLOCK_SPEED,
PROP_TICK_RATE,
PROP_TOTAL_TICKS,
PROP_TICK_LIST,
PROP_TICKS,
};
static guint gst_pod_filter_signals[LAST_SIGNAL] = { 0 };
@ -163,40 +167,24 @@ play_on_demand_class_init (GstPlayOnDemandClass *klass)
gstelement_class = (GstElementClass *) klass;
gst_pod_filter_signals[PLAYED_SIGNAL] =
g_signal_new("played",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
g_signal_new("played", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GstPlayOnDemandClass, played),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
gst_pod_filter_signals[PLAY_SIGNAL] =
g_signal_new("play",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
g_signal_new("play", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GstPlayOnDemandClass, play),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
gst_pod_filter_signals[CLEAR_SIGNAL] =
g_signal_new("clear",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
g_signal_new("clear", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GstPlayOnDemandClass, clear),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
gst_pod_filter_signals[RESET_SIGNAL] =
g_signal_new("reset",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
g_signal_new("reset", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GstPlayOnDemandClass, reset),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
klass->play = play_on_demand_play_handler;
klass->clear = play_on_demand_clear_handler;
@ -206,45 +194,33 @@ play_on_demand_class_init (GstPlayOnDemandClass *klass)
gobject_class->set_property = play_on_demand_set_property;
gobject_class->get_property = play_on_demand_get_property;
gobject_class->dispose = play_on_demand_dispose;
gstelement_class->set_clock = play_on_demand_set_clock;
g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_MUTE,
g_param_spec_boolean("mute", "Silence output",
"Do not output any sound",
FALSE, G_PARAM_READWRITE));
g_param_spec_boolean("mute", "Silence output", "Do not output any sound",
FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_BUFFER_TIME,
g_param_spec_float("buffer-time", "Buffer length in seconds",
"Number of seconds of audio the buffer holds",
0.0, G_MAXUINT - 2, GST_POD_BUFFER_TIME, G_PARAM_READWRITE));
g_param_spec_float("buffer-time", "Buffer length in seconds", "Number of seconds of audio the buffer holds",
0.0, G_MAXUINT / GST_AUDIO_MAX_RATE - 10, GST_POD_BUFFER_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_MAX_PLAYS,
g_param_spec_uint("plays", "Maximum simultaneous playback",
"Maximum allowed number of simultaneous plays from the buffer",
1, G_MAXUINT, GST_POD_MAX_PLAYS, G_PARAM_READWRITE));
g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_CLOCK_SPEED,
g_param_spec_float("clock-speed", "Clock speed (ticks/second)",
"The relative speed of a musical tick",
0, G_MAXFLOAT, 1, G_PARAM_READWRITE));
g_param_spec_uint("max-plays", "Maximum simultaneous playbacks", "Maximum allowed number of simultaneous plays from the buffer",
1, G_MAXUINT, GST_POD_MAX_PLAYS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_TICK_RATE,
g_param_spec_float("tick-rate", "Tick rate (ticks/second)", "The rate of musical ticks, the smallest time unit in a song",
0, G_MAXFLOAT, GST_POD_TICK_RATE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_TOTAL_TICKS,
g_param_spec_uint("total-ticks", "Total number of ticks",
"Total number of ticks (only relevant for tick lists)",
1, G_MAXUINT, 1, G_PARAM_READWRITE));
g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_TICK_LIST,
g_param_spec_pointer("tick-list", "List of ticks to play",
"A list of ticks (musical times) at which to play the sample",
G_PARAM_WRITABLE));
g_param_spec_uint("total-ticks", "Total number of ticks", "Total number of ticks in the tick array",
1, G_MAXUINT, 1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_TICKS,
g_param_spec_pointer("ticks", "Ticks to play sample on", "An array of ticks (musical times) at which to play the sample",
G_PARAM_READWRITE));
}
static void
play_on_demand_init (GstPlayOnDemand *filter)
{
guint i;
filter->srcpad = gst_pad_new_from_template(play_on_demand_src_factory(), "src");
filter->sinkpad = gst_pad_new_from_template(play_on_demand_sink_factory(), "sink");
@ -258,23 +234,14 @@ play_on_demand_init (GstPlayOnDemand *filter)
filter->clock = NULL;
/* filter properties */
filter->mute = FALSE;
filter->buffer_time = GST_POD_BUFFER_TIME;
filter->max_plays = GST_POD_MAX_PLAYS;
filter->clock_speed = GST_POD_CLOCK_SPEED;
filter->total_ticks = 1;
filter->tick_list = NULL;
filter->rate = 0;
filter->ticks = g_new(guint32, filter->total_ticks / 32 + 1);
filter->plays = g_new(guint, filter->max_plays);
/* internal buffer stuff */
play_on_demand_resize_buffer(filter);
filter->eos = FALSE;
/* play pointers, stored as an array of buffer offsets */
filter->write = 0;
filter->plays = g_new(guint, filter->max_plays);
for (i = 0; i < filter->max_plays; i++)
filter->plays[i] = G_MAXUINT;
play_on_demand_clear_handler(GST_ELEMENT(filter));
play_on_demand_reset_handler(GST_ELEMENT(filter));
}
static void
@ -284,6 +251,7 @@ play_on_demand_set_property (GObject *object, guint prop_id,
GstPlayOnDemand *filter;
register guint i;
guint new_size, min_size, *new_plays;
guint *new_ticks;
g_return_if_fail(GST_IS_PLAYONDEMAND(object));
filter = GST_PLAYONDEMAND(object);
@ -296,10 +264,9 @@ play_on_demand_set_property (GObject *object, guint prop_id,
filter->buffer_time = g_value_get_float(value);
play_on_demand_resize_buffer(filter);
/* clear out now-invalid play pointers, if there are any. */
/* clear out now-invalid play pointers */
for (i = 0; i < filter->max_plays; i++)
if (filter->plays[i] > filter->buffer_bytes)
filter->plays[i] = G_MAXUINT;
filter->plays[i] = G_MAXUINT;
break;
case PROP_MAX_PLAYS:
@ -308,21 +275,35 @@ play_on_demand_set_property (GObject *object, guint prop_id,
new_plays = g_new(guint, new_size);
for (i = 0; i < min_size; i++) new_plays[i] = filter->plays[i];
for (i = min_size; i < filter->max_plays; i++) new_plays[i] = G_MAXUINT;
for (i = min_size; i < new_size; i++) new_plays[i] = G_MAXUINT;
g_free(filter->plays);
filter->plays = new_plays;
filter->max_plays = new_size;
break;
case PROP_CLOCK_SPEED:
filter->clock_speed = g_value_get_float(value);
case PROP_TICK_RATE:
filter->tick_rate = g_value_get_float(value);
break;
case PROP_TOTAL_TICKS:
filter->total_ticks = g_value_get_uint(value);
new_size = g_value_get_uint(value);
min_size = (new_size < filter->total_ticks) ? new_size : filter->total_ticks;
new_ticks = g_new(guint32, new_size / 32 + 1);
for (i = 0; i <= min_size / 32; i++) new_ticks[i] = filter->ticks[i];
for (i = min_size / 32 + 1; i <= new_size / 32; i++) new_ticks[i] = 0;
g_free(filter->ticks);
filter->ticks = new_ticks;
filter->total_ticks = new_size;
break;
case PROP_TICK_LIST:
filter->tick_list = (GSList *) g_value_get_pointer(value);
case PROP_TICKS:
new_ticks = (guint *) g_value_get_pointer(value);
if (new_ticks) {
g_free(filter->ticks);
filter->ticks = new_ticks;
}
break;
default:
break;
@ -348,18 +329,33 @@ play_on_demand_get_property (GObject *object, guint prop_id,
case PROP_MAX_PLAYS:
g_value_set_uint(value, filter->max_plays);
break;
case PROP_CLOCK_SPEED:
g_value_set_float(value, filter->clock_speed);
case PROP_TICK_RATE:
g_value_set_float(value, filter->tick_rate);
break;
case PROP_TOTAL_TICKS:
g_value_set_uint(value, filter->total_ticks);
break;
case PROP_TICKS:
g_value_set_pointer(value, (gpointer) filter->ticks);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
play_on_demand_dispose (GObject *object)
{
GstPlayOnDemand *filter = GST_PLAYONDEMAND (object);
G_OBJECT_CLASS (parent_class)->dispose (object);
g_free (filter->ticks);
g_free (filter->plays);
g_free (filter->buffer);
}
static GstBufferPool*
play_on_demand_get_bufferpool (GstPad *pad)
{
@ -380,7 +376,7 @@ play_on_demand_pad_link (GstPad *pad, GstCaps *caps)
filter = GST_PLAYONDEMAND(GST_PAD_PARENT(pad));
gst_caps_get_string(caps, "format", &format);
gst_caps_get_int(caps, "rate", &filter->rate);
gst_caps_get_int(caps, "rate", &filter->rate);
gst_caps_get_int(caps, "channels", &filter->channels);
if (strcmp(format, "int") == 0) {
@ -397,21 +393,22 @@ play_on_demand_pad_link (GstPad *pad, GstCaps *caps)
return GST_PAD_LINK_DELAYED;
}
/* clock check macros. in these macros,
f == filter
t == tick in question
c == current tick (from the clock)
l == last tick (last tick when clock was checked)
dt == ticks between c and t */
#define GST_POD_SAMPLE_OFFSET(f, dt) \
((guint) (dt * (f)->rate / (f)->clock_speed))
inline static void
play_on_demand_add_play_pointer (GstPlayOnDemand *filter, guint pos)
{
register guint i;
/* play a sample if the tick in question came between the last time we checked
the clock and the current clock time. only looks complicated because the last
clock time could have been at the end of the total_ticks, so the clock might
have wrapped around ... */
#define GST_POD_TICK_ELAPSED(t, c, l) \
(((l < c) && (l < t) && (t < c)) || ((l > c) && ((l < t) || (t < c))))
if (filter->rate && ((filter->buffer_time * filter->rate) > pos)) {
for (i = 0; i < filter->max_plays; i++) {
if (filter->plays[i] == G_MAXUINT) {
filter->plays[i] = pos;
/* emit a signal to indicate a sample being played */
g_signal_emit(filter, gst_pod_filter_signals[PLAYED_SIGNAL], 0);
break;
}
}
}
}
static void
play_on_demand_loop (GstElement *elem)
@ -419,37 +416,30 @@ play_on_demand_loop (GstElement *elem)
GstPlayOnDemand *filter = GST_PLAYONDEMAND(elem);
guint num_in, num_out, num_filter;
GstBuffer *in, *out;
register guint j, k, t;
guint w, offset;
/* variables for clock check. */
static guint last_tick = 0;
GSList *tick_list;
guint tick, current_tick;
g_return_if_fail(filter != NULL);
g_return_if_fail(GST_IS_PLAYONDEMAND(filter));
filter->bufpool = gst_pad_get_bufferpool(filter->srcpad);
if (filter->bufpool == NULL) {
if (filter->bufpool == NULL)
filter->bufpool = gst_buffer_pool_get_default(GST_POD_BUFPOOL_SIZE,
GST_POD_BUFPOOL_NUM);
}
in = gst_pad_pull(filter->sinkpad);
if (filter->format == GST_PLAYONDEMAND_FORMAT_INT) {
if (filter->width == 16) {
gint16 min = -32768;
gint16 max = 32767;
gint16 min = 0xffff;
gint16 max = 0x7fff;
gint16 zero = 0;
#define _TYPE_ gint16
#include "filter.func"
#undef _TYPE_
} else if (filter->width == 8) {
gint8 min = -128;
gint8 max = 127;
gint8 min = 0xff;
gint8 max = 0x7f;
gint8 zero = 0;
#define _TYPE_ gint8
#include "filter.func"
@ -493,6 +483,7 @@ static void
play_on_demand_clear_handler (GstElement *elem)
{
GstPlayOnDemand *filter;
register guint i;
g_return_if_fail(elem != NULL);
g_return_if_fail(GST_IS_PLAYONDEMAND(elem));
@ -500,6 +491,9 @@ play_on_demand_clear_handler (GstElement *elem)
filter->write = 0;
filter->eos = FALSE;
for (i = 0; i < filter->max_plays; i++) filter->plays[i] = G_MAXUINT;
for (i = 0; i < filter->buffer_bytes; i++) filter->buffer[i] = 0;
}
static void
@ -508,39 +502,21 @@ play_on_demand_reset_handler (GstElement *elem)
GstPlayOnDemand *filter;
register guint i;
play_on_demand_clear_handler (elem);
g_return_if_fail(elem != NULL);
g_return_if_fail(GST_IS_PLAYONDEMAND(elem));
filter = GST_PLAYONDEMAND(elem);
for (i = 0; i < filter->max_plays; i++) {
filter->plays[i] = G_MAXUINT;
}
filter->write = 0;
filter->eos = FALSE;
}
static void
play_on_demand_add_play_pointer (GstPlayOnDemand *filter, guint pos)
{
register guint i;
if (filter->rate && ((filter->buffer_time * filter->rate) > pos))
for (i = 0; i < filter->max_plays; i++)
if (filter->plays[i] == G_MAXUINT) {
filter->plays[i] = pos;
/* emit a signal to indicate a sample being played */
g_signal_emit(filter, gst_pod_filter_signals[PLAYED_SIGNAL], 0);
return;
}
for (i = 0; i <= filter->total_ticks / 32; i++) filter->ticks[i] = 0;
}
static void
play_on_demand_resize_buffer (GstPlayOnDemand *filter)
{
register guint i;
guint new_size, min_size;
gchar *new_buffer;
register guint i;
guint new_size, min_size;
gchar *new_buffer;
/* use a default sample rate of 44100, 1 channel, 1 byte per sample if caps
haven't been set yet */
@ -557,7 +533,7 @@ play_on_demand_resize_buffer (GstPlayOnDemand *filter)
new_buffer = g_new(gchar, new_size);
for (i = 0; i < min_size; i++) new_buffer[i] = filter->buffer[i];
for (i = min_size; i < filter->buffer_bytes; i++) new_buffer[i] = 0;
for (i = min_size; i < new_size; i++) new_buffer[i] = 0;
g_free(filter->buffer);
filter->buffer = new_buffer;

View file

@ -63,9 +63,9 @@ struct _GstPlayOnDemand {
gboolean mute;
gfloat buffer_time;
guint max_plays;
gfloat clock_speed;
gfloat tick_rate;
guint total_ticks;
GSList *tick_list;
guint32 *ticks;
/* internal buffer info */
gchar *buffer;