mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 08:41:07 +00:00
+ 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:
parent
bea8637738
commit
7e761258c1
4 changed files with 199 additions and 216 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
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. */
|
||||
|
||||
{
|
||||
register guint k, p;
|
||||
|
||||
data_out = (_TYPE_ *) GST_BUFFER_DATA(out);
|
||||
num_out = GST_BUFFER_SIZE(out) / sizeof(_TYPE_);
|
||||
|
||||
for (k = 0; k < num_out; k++)
|
||||
data_out[k] = zero;
|
||||
for (k = 0; k < num_out; k++) data_out[k] = zero;
|
||||
|
||||
/* output play pointer data. */
|
||||
if (! filter->mute)
|
||||
for (t = 0; t < filter->max_plays; t++) {
|
||||
offset = filter->plays[t];
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
/* 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->ticks = g_new(guint32, filter->total_ticks / 32 + 1);
|
||||
filter->plays = g_new(guint, filter->max_plays);
|
||||
for (i = 0; i < filter->max_plays; i++)
|
||||
filter->plays[i] = G_MAXUINT;
|
||||
|
||||
play_on_demand_resize_buffer(filter);
|
||||
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,9 +264,8 @@ 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;
|
||||
|
||||
break;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,31 +502,13 @@ 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
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue