mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-16 12:25:50 +00:00
playondemand: remove unported plugin from 0.8
These days one would do the effect e.g. using gnonlin.
This commit is contained in:
parent
bae725ed1f
commit
aa4b5b3bf5
6 changed files with 0 additions and 985 deletions
1
gst/playondemand/.gitignore
vendored
1
gst/playondemand/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
demo_mp3
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
plugin_LTLIBRARIES = libgstplayondemand.la
|
||||
|
||||
libgstplayondemand_la_SOURCES = gstplayondemand.c
|
||||
libgstplayondemand_la_CFLAGS = $(GST_CFLAGS)
|
||||
libgstplayondemand_la_LIBADD =
|
||||
libgstplayondemand_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgstplayondemand_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
noinst_HEADERS = gstplayondemand.h filter.func
|
||||
|
||||
if HAVE_GTK
|
||||
noinst_PROGRAMS = demo_mp3
|
||||
endif
|
||||
|
||||
demo_mp3_SOURCES = demo-mp3.c gstplayondemand.h
|
||||
## putting GTK_CFLAGS first fixes a weird compilation error with GTK and XML
|
||||
demo_mp3_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS)
|
||||
demo_mp3_LDFLAGS = $(GST_LIBS) $(GTK_LIBS)
|
|
@ -1,187 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#define NUM_BEATS 12
|
||||
#define TICK_RATE(x) (x * 1e-6)
|
||||
|
||||
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, *dec, *pod, *sink, *pipeline;
|
||||
GstClock *element_clock;
|
||||
guint32 *beats;
|
||||
|
||||
void
|
||||
played (GstElement * pod, gpointer data)
|
||||
{
|
||||
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
|
||||
play (GtkButton * button, gpointer data)
|
||||
{
|
||||
g_signal_emit_by_name (G_OBJECT (pod), "play", NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
clear (GtkButton * button, gpointer data)
|
||||
{
|
||||
g_signal_emit_by_name (G_OBJECT (pod), "clear", NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
reset (GtkButton * button, gpointer data)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_signal_emit_by_name (G_OBJECT (pod), "reset", NULL, NULL);
|
||||
for (i = 0; i < NUM_BEATS; i++)
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (beat_button[i]), 0);
|
||||
}
|
||||
|
||||
void
|
||||
beat (GtkToggleButton * button, gpointer data)
|
||||
{
|
||||
guint b = GPOINTER_TO_UINT (data);
|
||||
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
|
||||
beats[b / 32] |= 1 << (b % 32);
|
||||
else
|
||||
beats[b / 32] &= ~(1 << (b % 32));
|
||||
}
|
||||
|
||||
void
|
||||
speed (GtkAdjustment * adjustment, gpointer data)
|
||||
{
|
||||
/*g_signal_stop_emission_by_name(G_OBJECT(pod), "deep-notify"); */
|
||||
g_object_set (G_OBJECT (pod), "tick-rate", TICK_RATE (adjustment->value),
|
||||
NULL);
|
||||
/*gst_clock_set_speed(element_clock, adjustment->value); */
|
||||
}
|
||||
|
||||
void
|
||||
setup_pipeline (gchar * filename)
|
||||
{
|
||||
src = gst_element_factory_make ("filesrc", "source");
|
||||
dec = gst_element_factory_make ("vorbisfile", "decoder");
|
||||
pod = gst_element_factory_make ("playondemand", "sequencer");
|
||||
sink = gst_element_factory_make (DEFAULT_AUDIOSINK, "sink");
|
||||
|
||||
g_object_set (G_OBJECT (src), "location", filename, NULL);
|
||||
g_object_set (G_OBJECT (sink), "period-count", 64, "period-size", 512, NULL);
|
||||
g_object_set (G_OBJECT (pod), "total-ticks", NUM_BEATS,
|
||||
"tick-rate", 1.0e-6, "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, dec, pod, sink, NULL);
|
||||
gst_element_link_many (src, dec, pod, sink, NULL);
|
||||
|
||||
element_clock = gst_element_get_clock (GST_ELEMENT (sink));
|
||||
gst_element_set_clock (GST_ELEMENT (pod), element_clock);
|
||||
}
|
||||
|
||||
void
|
||||
setup_gui (void)
|
||||
{
|
||||
guint i;
|
||||
|
||||
beat_button = g_new (GtkWidget *, NUM_BEATS);
|
||||
|
||||
/* initialize gui elements ... */
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (window), 12);
|
||||
|
||||
vbox = gtk_vbox_new (TRUE, 0);
|
||||
gtk_box_set_spacing (GTK_BOX (vbox), 12);
|
||||
|
||||
beat_box = gtk_hbox_new (TRUE, 0);
|
||||
button_box = gtk_hbox_new (TRUE, 0);
|
||||
|
||||
play_button = gtk_button_new_with_label ("Play");
|
||||
clear_button = gtk_button_new_with_label ("Reset Sound");
|
||||
reset_button = gtk_button_new_with_label ("Reset All");
|
||||
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 + 1));
|
||||
|
||||
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);
|
||||
|
||||
/* do the packing stuff ... */
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 96, 96);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (button_box), play_button, TRUE, TRUE, 2);
|
||||
gtk_box_pack_start (GTK_BOX (button_box), clear_button, TRUE, TRUE, 2);
|
||||
gtk_box_pack_start (GTK_BOX (button_box), reset_button, TRUE, TRUE, 2);
|
||||
gtk_box_pack_start (GTK_BOX (button_box), quit_button, TRUE, TRUE, 2);
|
||||
|
||||
for (i = 0; i < NUM_BEATS; i++)
|
||||
gtk_box_pack_start (GTK_BOX (beat_box), beat_button[i], TRUE, TRUE, 2);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button_box, TRUE, FALSE, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), beat_box, TRUE, FALSE, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), speed_scale, TRUE, FALSE, 2);
|
||||
|
||||
/* connect things ... */
|
||||
g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play), NULL);
|
||||
g_signal_connect (G_OBJECT (clear_button), "clicked", G_CALLBACK (clear),
|
||||
NULL);
|
||||
g_signal_connect (G_OBJECT (reset_button), "clicked", G_CALLBACK (reset),
|
||||
NULL);
|
||||
g_signal_connect (G_OBJECT (quit_button), "clicked", gtk_main_quit, NULL);
|
||||
g_signal_connect (G_OBJECT (pod), "played", G_CALLBACK (played), NULL);
|
||||
g_signal_connect (G_OBJECT (speed_adj), "value_changed", G_CALLBACK (speed),
|
||||
NULL);
|
||||
for (i = 0; i < NUM_BEATS; i++)
|
||||
g_signal_connect (G_OBJECT (beat_button[i]), "toggled", G_CALLBACK (beat),
|
||||
GUINT_TO_POINTER (i));
|
||||
|
||||
/* show the gui. */
|
||||
gtk_widget_show_all (window);
|
||||
|
||||
gtk_idle_add ((GtkFunction) gst_bin_iterate, pipeline);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
gst_init (&argc, &argv);
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print ("usage: %s <mp3-filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
setup_pipeline (argv[1]);
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
setup_gui ();
|
||||
gtk_main ();
|
||||
g_free (beat_button);
|
||||
return 0;
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
/* -*- C -*- */
|
||||
|
||||
_TYPE_ *data_in, *data_out, *filter_data;
|
||||
|
||||
filter_data = (_TYPE_ *) filter->buffer;
|
||||
num_filter = filter->buffer_bytes / sizeof(_TYPE_);
|
||||
|
||||
do {
|
||||
/* see if we've got any events coming through ... */
|
||||
|
||||
while (! filter->eos && in != NULL && GST_IS_EVENT (in)) {
|
||||
GstEvent *event = GST_EVENT (in);
|
||||
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
|
||||
gst_data_unref (in);
|
||||
in = NULL;
|
||||
filter->eos = TRUE;
|
||||
} else if ((GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) ||
|
||||
(GST_EVENT_TYPE (event) == GST_EVENT_FLUSH)) {
|
||||
gst_data_unref (in);
|
||||
in = NULL;
|
||||
filter->eos = FALSE;
|
||||
filter->write = 0;
|
||||
} else {
|
||||
gst_pad_push(filter->srcpad, in);
|
||||
}
|
||||
|
||||
in = (in == NULL && ! filter->eos) ? gst_pad_pull(filter->sinkpad) : NULL;
|
||||
}
|
||||
|
||||
/* handle data from the input buffer. */
|
||||
|
||||
if (! filter->eos) {
|
||||
register guint j, w = filter->write;
|
||||
|
||||
data_in = (_TYPE_ *) GST_BUFFER_DATA (GST_BUFFER (in));
|
||||
num_in = GST_BUFFER_SIZE (in) / sizeof(_TYPE_);
|
||||
|
||||
for (j = 0; (j < num_in) && (w+j < num_filter); j++)
|
||||
filter_data[w+j] = data_in[j];
|
||||
|
||||
filter->write += j;
|
||||
|
||||
if (filter->write >= num_filter) filter->eos = TRUE;
|
||||
|
||||
out = GST_BUFFER (in);
|
||||
} else {
|
||||
out = gst_buffer_new_and_alloc (GST_POD_BUFPOOL_SIZE);
|
||||
}
|
||||
|
||||
in = NULL;
|
||||
|
||||
/* check to see if we have to add new play pointers. */
|
||||
|
||||
if (filter->clock) {
|
||||
register gint t, tick_offset;
|
||||
|
||||
guint total_ticks = filter->total_ticks;
|
||||
guint current_tick = \
|
||||
((guint) (gst_clock_get_time(filter->clock) * \
|
||||
filter->tick_rate / GST_SECOND)) % total_ticks;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 (p = 0; p < filter->max_plays; p++) {
|
||||
guint offset = filter->plays[p];
|
||||
|
||||
if (offset != G_MAXUINT) {
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* push out the buffer and get a new buffer if we're allowed to loop. */
|
||||
|
||||
gst_pad_push(filter->srcpad, GST_DATA (out));
|
||||
|
||||
if (gst_element_interrupt (GST_ELEMENT (filter))) break;
|
||||
|
||||
in = (in == NULL && ! filter->eos) ? gst_pad_pull(filter->sinkpad) : NULL;
|
||||
|
||||
} while (TRUE);
|
|
@ -1,568 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <gst/gst.h>
|
||||
#include <gst/audio/audio.h>
|
||||
|
||||
#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_TICK_RATE 1e-6 /* ticks per second */
|
||||
|
||||
/* buffer pool fallback values ... use if no buffer pool is available */
|
||||
#define GST_POD_BUFPOOL_SIZE 4096
|
||||
#define GST_POD_BUFPOOL_NUM 6
|
||||
|
||||
static GstStaticPadTemplate play_on_demand_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; "
|
||||
GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS)
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate play_on_demand_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; "
|
||||
GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS)
|
||||
);
|
||||
|
||||
|
||||
/* GObject functionality */
|
||||
static void play_on_demand_class_init (GstPlayOnDemandClass * klass);
|
||||
static void play_on_demand_base_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_finalize (GObject * object);
|
||||
|
||||
/* GStreamer functionality */
|
||||
static GstPadLinkReturn play_on_demand_pad_link (GstPad * pad,
|
||||
const GstCaps * caps);
|
||||
static void play_on_demand_loop (GstElement * elem);
|
||||
static void play_on_demand_set_clock (GstElement * elem, GstClock * clock);
|
||||
|
||||
/* signal handlers */
|
||||
static void play_on_demand_play_handler (GstElement * elem);
|
||||
static void play_on_demand_clear_handler (GstElement * elem);
|
||||
static void play_on_demand_reset_handler (GstElement * elem);
|
||||
|
||||
/* utility functions */
|
||||
static void play_on_demand_add_play_pointer (GstPlayOnDemand * filter,
|
||||
guint pos);
|
||||
static void play_on_demand_resize_buffer (GstPlayOnDemand * filter);
|
||||
|
||||
GType
|
||||
gst_play_on_demand_get_type (void)
|
||||
{
|
||||
static GType play_on_demand_type = 0;
|
||||
|
||||
if (!play_on_demand_type) {
|
||||
static const GTypeInfo play_on_demand_info = {
|
||||
sizeof (GstPlayOnDemandClass),
|
||||
(GBaseInitFunc) play_on_demand_base_init,
|
||||
NULL,
|
||||
(GClassInitFunc) play_on_demand_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstPlayOnDemand),
|
||||
0,
|
||||
(GInstanceInitFunc) play_on_demand_init,
|
||||
};
|
||||
|
||||
play_on_demand_type = g_type_register_static (GST_TYPE_ELEMENT,
|
||||
"GstPlayOnDemand", &play_on_demand_info, 0);
|
||||
}
|
||||
return play_on_demand_type;
|
||||
}
|
||||
|
||||
|
||||
/* signals and properties */
|
||||
enum
|
||||
{
|
||||
/* add signals here */
|
||||
PLAYED_SIGNAL,
|
||||
STOPPED_SIGNAL,
|
||||
PLAY_SIGNAL,
|
||||
CLEAR_SIGNAL,
|
||||
RESET_SIGNAL,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_MUTE,
|
||||
PROP_BUFFER_TIME,
|
||||
PROP_MAX_PLAYS,
|
||||
PROP_TICK_RATE,
|
||||
PROP_TOTAL_TICKS,
|
||||
PROP_TICKS
|
||||
};
|
||||
|
||||
static guint gst_pod_filter_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
|
||||
static void
|
||||
play_on_demand_base_init (GstPlayOnDemandClass * klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&play_on_demand_src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&play_on_demand_sink_template));
|
||||
gst_element_class_set_details_simple (element_class, "Play On Demand",
|
||||
"Filter/Editor/Audio",
|
||||
"Schedule a stream to play at specific times, or when a signal is received",
|
||||
"Leif Morgan Johnson <leif@ambient.2y.net>");
|
||||
}
|
||||
|
||||
static void
|
||||
play_on_demand_class_init (GstPlayOnDemandClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass *) 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_STRUCT_OFFSET (GstPlayOnDemandClass, played),
|
||||
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
|
||||
gst_pod_filter_signals[STOPPED_SIGNAL] =
|
||||
g_signal_new ("stopped", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstPlayOnDemandClass, stopped),
|
||||
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_STRUCT_OFFSET (GstPlayOnDemandClass, play),
|
||||
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_STRUCT_OFFSET (GstPlayOnDemandClass, clear),
|
||||
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_STRUCT_OFFSET (GstPlayOnDemandClass, reset),
|
||||
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;
|
||||
klass->reset = play_on_demand_reset_handler;
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
gobject_class->set_property = play_on_demand_set_property;
|
||||
gobject_class->get_property = play_on_demand_get_property;
|
||||
gobject_class->finalize = play_on_demand_finalize;
|
||||
|
||||
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_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
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_MAXFLOAT,
|
||||
GST_POD_BUFFER_TIME,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_PLAYS,
|
||||
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_PARAM_STATIC_STRINGS));
|
||||
|
||||
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_PARAM_STATIC_STRINGS));
|
||||
|
||||
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 in the tick array", 1, G_MAXUINT, 1,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
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 | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static void
|
||||
play_on_demand_init (GstPlayOnDemand * filter)
|
||||
{
|
||||
filter->srcpad =
|
||||
gst_pad_new_from_static_template (&play_on_demand_src_template, "src");
|
||||
filter->sinkpad =
|
||||
gst_pad_new_from_static_template (&play_on_demand_sink_template, "sink");
|
||||
|
||||
gst_pad_set_link_function (filter->sinkpad, play_on_demand_pad_link);
|
||||
|
||||
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
|
||||
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
|
||||
|
||||
gst_element_set_loop_function (GST_ELEMENT (filter), play_on_demand_loop);
|
||||
|
||||
filter->clock = NULL;
|
||||
|
||||
filter->rate = 0;
|
||||
|
||||
filter->ticks = g_new (guint32, filter->total_ticks / 32 + 1);
|
||||
filter->plays = g_new (guint, filter->max_plays);
|
||||
|
||||
play_on_demand_resize_buffer (filter);
|
||||
play_on_demand_reset_handler (GST_ELEMENT (filter));
|
||||
}
|
||||
|
||||
static void
|
||||
play_on_demand_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
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);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MUTE:
|
||||
filter->mute = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_BUFFER_TIME:
|
||||
filter->buffer_time = g_value_get_float (value);
|
||||
play_on_demand_resize_buffer (filter);
|
||||
|
||||
/* clear out now-invalid play pointers */
|
||||
for (i = 0; i < filter->max_plays; i++)
|
||||
filter->plays[i] = G_MAXUINT;
|
||||
|
||||
break;
|
||||
case PROP_MAX_PLAYS:
|
||||
new_size = g_value_get_uint (value);
|
||||
min_size = (new_size < filter->max_plays) ? new_size : filter->max_plays;
|
||||
|
||||
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 < new_size; i++)
|
||||
new_plays[i] = G_MAXUINT;
|
||||
|
||||
g_free (filter->plays);
|
||||
filter->plays = new_plays;
|
||||
filter->max_plays = new_size;
|
||||
|
||||
break;
|
||||
case PROP_TICK_RATE:
|
||||
filter->tick_rate = g_value_get_float (value);
|
||||
break;
|
||||
case PROP_TOTAL_TICKS:
|
||||
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_TICKS:
|
||||
new_ticks = (guint *) g_value_get_pointer (value);
|
||||
if (new_ticks) {
|
||||
g_free (filter->ticks);
|
||||
filter->ticks = new_ticks;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
play_on_demand_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstPlayOnDemand *filter;
|
||||
|
||||
g_return_if_fail (GST_IS_PLAYONDEMAND (object));
|
||||
filter = GST_PLAYONDEMAND (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MUTE:
|
||||
g_value_set_boolean (value, filter->mute);
|
||||
break;
|
||||
case PROP_BUFFER_TIME:
|
||||
g_value_set_float (value, filter->buffer_time);
|
||||
break;
|
||||
case PROP_MAX_PLAYS:
|
||||
g_value_set_uint (value, filter->max_plays);
|
||||
break;
|
||||
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_finalize (GObject * object)
|
||||
{
|
||||
GstPlayOnDemand *filter = GST_PLAYONDEMAND (object);
|
||||
|
||||
g_free (filter->ticks);
|
||||
g_free (filter->plays);
|
||||
g_free (filter->buffer);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static GstPadLinkReturn
|
||||
play_on_demand_pad_link (GstPad * pad, const GstCaps * caps)
|
||||
{
|
||||
const gchar *mimetype;
|
||||
GstPlayOnDemand *filter;
|
||||
GstStructure *structure;
|
||||
|
||||
g_return_val_if_fail (caps != NULL, GST_PAD_LINK_DELAYED);
|
||||
g_return_val_if_fail (pad != NULL, GST_PAD_LINK_DELAYED);
|
||||
|
||||
filter = GST_PLAYONDEMAND (GST_PAD_PARENT (pad));
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
mimetype = gst_structure_get_name (structure);
|
||||
gst_structure_get_int (structure, "rate", &filter->rate);
|
||||
gst_structure_get_int (structure, "channels", &filter->channels);
|
||||
|
||||
if (strcmp (mimetype, "audio/x-raw-int") == 0) {
|
||||
filter->format = GST_PLAYONDEMAND_FORMAT_INT;
|
||||
gst_structure_get_int (structure, "width", &filter->width);
|
||||
} else if (strcmp (mimetype, "audio/x-raw-float") == 0) {
|
||||
filter->format = GST_PLAYONDEMAND_FORMAT_FLOAT;
|
||||
}
|
||||
|
||||
play_on_demand_resize_buffer (filter);
|
||||
|
||||
return gst_pad_try_set_caps (filter->srcpad, caps);
|
||||
}
|
||||
|
||||
inline 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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
play_on_demand_loop (GstElement * elem)
|
||||
{
|
||||
GstPlayOnDemand *filter = GST_PLAYONDEMAND (elem);
|
||||
guint num_in, num_out, num_filter;
|
||||
GstData *in = NULL;
|
||||
GstBuffer *out = NULL;
|
||||
static guint last_tick = 0;
|
||||
|
||||
g_return_if_fail (filter != NULL);
|
||||
g_return_if_fail (GST_IS_PLAYONDEMAND (filter));
|
||||
|
||||
in = (in == NULL && !filter->eos) ? gst_pad_pull (filter->sinkpad) : NULL;
|
||||
|
||||
if (filter->format == GST_PLAYONDEMAND_FORMAT_INT) {
|
||||
if (filter->width == 16) {
|
||||
gint16 min = 0xffff;
|
||||
gint16 max = 0x7fff;
|
||||
gint16 zero = 0;
|
||||
|
||||
#define _TYPE_ gint16
|
||||
#include "filter.func"
|
||||
#undef _TYPE_
|
||||
} else if (filter->width == 8) {
|
||||
gint8 min = 0xff;
|
||||
gint8 max = 0x7f;
|
||||
gint8 zero = 0;
|
||||
|
||||
#define _TYPE_ gint8
|
||||
#include "filter.func"
|
||||
#undef _TYPE_
|
||||
}
|
||||
} else if (filter->format == GST_PLAYONDEMAND_FORMAT_FLOAT) {
|
||||
gfloat min = -1.0;
|
||||
gfloat max = 1.0;
|
||||
gfloat zero = 0.0;
|
||||
|
||||
#define _TYPE_ gfloat
|
||||
#include "filter.func"
|
||||
#undef _TYPE_
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
play_on_demand_set_clock (GstElement * elem, GstClock * clock)
|
||||
{
|
||||
GstPlayOnDemand *filter;
|
||||
|
||||
g_return_if_fail (elem != NULL);
|
||||
g_return_if_fail (GST_IS_PLAYONDEMAND (elem));
|
||||
filter = GST_PLAYONDEMAND (elem);
|
||||
|
||||
filter->clock = clock;
|
||||
}
|
||||
|
||||
static void
|
||||
play_on_demand_play_handler (GstElement * elem)
|
||||
{
|
||||
GstPlayOnDemand *filter;
|
||||
|
||||
g_return_if_fail (elem != NULL);
|
||||
g_return_if_fail (GST_IS_PLAYONDEMAND (elem));
|
||||
filter = GST_PLAYONDEMAND (elem);
|
||||
|
||||
play_on_demand_add_play_pointer (filter, 0);
|
||||
}
|
||||
|
||||
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));
|
||||
filter = GST_PLAYONDEMAND (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] = (gchar) 0;
|
||||
}
|
||||
|
||||
static void
|
||||
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->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;
|
||||
|
||||
/* use a default sample rate of 44100, 1 channel, 1 byte per sample if caps
|
||||
haven't been set yet */
|
||||
new_size = (guint) filter->buffer_time;
|
||||
new_size *= (filter->rate) ? filter->rate : 44100;
|
||||
new_size *= (filter->channels) ? filter->channels : 1;
|
||||
|
||||
if (filter->format && filter->format == GST_PLAYONDEMAND_FORMAT_FLOAT)
|
||||
new_size *= sizeof (gfloat);
|
||||
else
|
||||
new_size *= (filter->width) ? filter->width / 8 : 1;
|
||||
|
||||
min_size =
|
||||
(new_size < filter->buffer_bytes) ? new_size : filter->buffer_bytes;
|
||||
|
||||
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 < new_size; i++)
|
||||
new_buffer[i] = (gchar) 0;
|
||||
|
||||
g_free (filter->buffer);
|
||||
filter->buffer = new_buffer;
|
||||
filter->buffer_bytes = new_size;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
return gst_element_register (plugin, "playondemand",
|
||||
GST_RANK_NONE, GST_TYPE_PLAYONDEMAND);
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"playondemand",
|
||||
"Plays a stream at specific times, or when it receives a signal",
|
||||
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|
|
@ -1,97 +0,0 @@
|
|||
/* -*- c-basic-offset: 2 -*-
|
||||
* GStreamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GST_PLAYONDEMAND_H__
|
||||
#define __GST_PLAYONDEMAND_H__
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_PLAYONDEMAND \
|
||||
(gst_play_on_demand_get_type())
|
||||
#define GST_PLAYONDEMAND(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAYONDEMAND,GstPlayOnDemand))
|
||||
#define GST_PLAYONDEMAND_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLAYONDEMAND,GstPlayOnDemandClass))
|
||||
#define GST_IS_PLAYONDEMAND(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLAYONDEMAND))
|
||||
#define GST_IS_PLAYONDEMAND_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAYONDEMAND))
|
||||
|
||||
typedef struct _GstPlayOnDemand GstPlayOnDemand;
|
||||
typedef struct _GstPlayOnDemandClass GstPlayOnDemandClass;
|
||||
typedef enum _GstPlayOnDemandFormat GstPlayOnDemandFormat;
|
||||
|
||||
enum _GstPlayOnDemandFormat {
|
||||
GST_PLAYONDEMAND_FORMAT_INT,
|
||||
GST_PLAYONDEMAND_FORMAT_FLOAT
|
||||
};
|
||||
|
||||
struct _GstPlayOnDemand {
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad, *srcpad;
|
||||
GstClock *clock;
|
||||
|
||||
/* filter properties */
|
||||
gboolean mute;
|
||||
gfloat buffer_time;
|
||||
guint max_plays;
|
||||
gfloat tick_rate;
|
||||
guint total_ticks;
|
||||
guint32 *ticks;
|
||||
|
||||
/* internal buffer info */
|
||||
gchar *buffer;
|
||||
guint buffer_bytes;
|
||||
gboolean eos;
|
||||
|
||||
/* play pointers == internal buffer offsets for producing output sound */
|
||||
guint *plays;
|
||||
guint write;
|
||||
|
||||
/* audio format info (used to calculate buffer_samples) */
|
||||
GstPlayOnDemandFormat format;
|
||||
guint rate;
|
||||
guint channels;
|
||||
guint width;
|
||||
};
|
||||
|
||||
struct _GstPlayOnDemandClass {
|
||||
GstElementClass parent_class;
|
||||
|
||||
void (*play) (GstElement *elem);
|
||||
void (*clear) (GstElement *elem);
|
||||
void (*reset) (GstElement *elem);
|
||||
void (*played) (GstElement *elem);
|
||||
void (*stopped) (GstElement *elem);
|
||||
};
|
||||
|
||||
GType gst_play_on_demand_get_type(void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_PLAYONDEMAND_H__ */
|
Loading…
Reference in a new issue