static gboolean gst_audiosink_change_state(GstElement *element,
GstElementState state);
+static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id);
+static void gst_audiosink_get_arg(GtkObject *object,GtkArg *arg,guint id);
+
void gst_audiosink_chain(GstPad *pad,GstBuffer *buf);
/* AudioSink signals and args */
enum {
- HANDOFF,
+ SIGNAL_HANDOFF,
LAST_SIGNAL
};
enum {
ARG_0,
+ ARG_MUTE,
+ ARG_FORMAT,
+ ARG_CHANNELS,
+ ARG_FREQUENCY,
/* FILL ME */
};
parent_class = gtk_type_class(GST_TYPE_FILTER);
- gst_audiosink_signals[HANDOFF] =
+ gtk_object_add_arg_type("GstAudioSink::mute", GTK_TYPE_BOOL,
+ GTK_ARG_READWRITE, ARG_MUTE);
+ gtk_object_add_arg_type("GstAudioSink::format", GTK_TYPE_INT,
+ GTK_ARG_READWRITE, ARG_FORMAT);
+ gtk_object_add_arg_type("GstAudioSink::channels", GTK_TYPE_INT,
+ GTK_ARG_READWRITE, ARG_CHANNELS);
+ gtk_object_add_arg_type("GstAudioSink::frequency", GTK_TYPE_INT,
+ GTK_ARG_READWRITE, ARG_FREQUENCY);
+
+ gtkobject_class->set_arg = gst_audiosink_set_arg;
+ gtkobject_class->get_arg = gst_audiosink_get_arg;
+
+ gst_audiosink_signals[SIGNAL_HANDOFF] =
gtk_signal_new("handoff",GTK_RUN_LAST,gtkobject_class->type,
GTK_SIGNAL_OFFSET(GstAudioSinkClass,handoff),
gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1,
}
}
- gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[HANDOFF],
+ gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[SIGNAL_HANDOFF],
audiosink);
if (GST_BUFFER_DATA(buf) != NULL) {
gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard");
audiosink->clocktime = (info.bytes*1000000LL)/(audiosink->frequency*audiosink->channels);
//g_print("audiosink: bytes sent %d time %llu\n", info.bytes, audiosink->clocktime);
gst_clock_set(audiosink->clock, audiosink->clocktime);
- write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
+ if (!audiosink->mute)
+ write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
//audiosink->clocktime += (1000000LL*GST_BUFFER_SIZE(buf)/(audiosink->channels*
// (audiosink->format/8)*(audiosink->frequency)));
//g_print("audiosink: writing to soundcard ok\n");
//g_print("a done\n");
}
-void gst_audiosink_set_format(GstAudioSink *audiosink,gint format) {
- g_return_if_fail(audiosink != NULL);
- g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
-
- audiosink->format = format;
-
- gst_audiosink_sync_parms(audiosink);
-}
+static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id) {
+ GstAudioSink *audiosink;
-void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels) {
- g_return_if_fail(audiosink != NULL);
- g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_AUDIOSINK(object));
+ audiosink = GST_AUDIOSINK(object);
- audiosink->channels = channels;
-
- gst_audiosink_sync_parms(audiosink);
+ switch(id) {
+ case ARG_MUTE:
+ audiosink->mute = GTK_VALUE_BOOL(*arg);
+ break;
+ case ARG_FORMAT:
+ audiosink->format = GTK_VALUE_INT(*arg);
+ gst_audiosink_sync_parms(audiosink);
+ break;
+ case ARG_CHANNELS:
+ audiosink->channels = GTK_VALUE_INT(*arg);
+ gst_audiosink_sync_parms(audiosink);
+ break;
+ case ARG_FREQUENCY:
+ audiosink->frequency = GTK_VALUE_INT(*arg);
+ gst_audiosink_sync_parms(audiosink);
+ break;
+ default:
+ break;
+ }
}
-void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) {
- g_return_if_fail(audiosink != NULL);
- g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
+static void gst_audiosink_get_arg(GtkObject *object,GtkArg *arg,guint id) {
+ GstAudioSink *audiosink;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_AUDIOSINK(object));
+ audiosink = GST_AUDIOSINK(object);
- audiosink->frequency = frequency;
-
- gst_audiosink_sync_parms(audiosink);
+ switch(id) {
+ case ARG_MUTE:
+ GTK_VALUE_BOOL(*arg) = audiosink->mute;
+ break;
+ case ARG_FORMAT:
+ GTK_VALUE_INT(*arg) = audiosink->format;
+ break;
+ case ARG_CHANNELS:
+ GTK_VALUE_INT(*arg) = audiosink->channels;
+ break;
+ case ARG_FREQUENCY:
+ GTK_VALUE_INT(*arg) = audiosink->frequency;
+ break;
+ default:
+ break;
+ }
}
static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
gint format;
gint channels;
gint frequency;
+ gboolean mute;
};
struct _GstAudioSinkClass {
ARG_LOCATION,
ARG_BYTESPERREAD,
ARG_OFFSET,
+ ARG_SIZE,
};
GTK_ARG_READWRITE, ARG_BYTESPERREAD);
gtk_object_add_arg_type("GstDiskSrc::offset", GTK_TYPE_INT,
GTK_ARG_READWRITE, ARG_OFFSET);
+ gtk_object_add_arg_type("GstDiskSrc::size", GTK_TYPE_INT,
+ GTK_ARG_READABLE, ARG_SIZE);
gtkobject_class->set_arg = gst_disksrc_set_arg;
gtkobject_class->get_arg = gst_disksrc_get_arg;
disksrc->curoffset = 0;
disksrc->bytes_per_read = 4096;
disksrc->seq = 0;
+ disksrc->size = 0;
+ disksrc->new_seek = FALSE;
}
case ARG_OFFSET:
src->curoffset = GTK_VALUE_INT(*arg);
lseek(src->fd,src->curoffset, SEEK_SET);
+ src->new_seek = TRUE;
break;
default:
break;
case ARG_OFFSET:
GTK_VALUE_INT(*arg) = src->curoffset;
break;
+ case ARG_SIZE:
+ GTK_VALUE_INT(*arg) = src->size;
+ break;
default:
arg->type = GTK_TYPE_INVALID;
break;
/* read it in from the file */
readbytes = read(disksrc->fd,GST_BUFFER_DATA(buf),disksrc->bytes_per_read);
- if (readbytes == 0) {
+ if (readbytes == -1) {
+ perror("read()");
+ gst_buffer_unref(buf);
+ return;
+ }
+ else if (readbytes == 0) {
gst_src_signal_eos(GST_SRC(disksrc));
- gst_buffer_unref(buf);
+ gst_buffer_unref(buf);
return;
}
/* if we didn't get as many bytes as we asked for, we're at EOF */
if (readbytes < disksrc->bytes_per_read)
- GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS);
+ GST_BUFFER_FLAG_SET(buf, GST_BUFFER_EOS);
+
+ /* if we have a new buffer froma seek, mark it */
+ if (disksrc->new_seek) {
+ GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLUSH);
+ disksrc->new_seek = FALSE;
+ }
+
GST_BUFFER_OFFSET(buf) = disksrc->curoffset;
GST_BUFFER_SIZE(buf) = readbytes;
disksrc->curoffset += readbytes;
+ DEBUG("pushing with offset %lu\n", GST_BUFFER_OFFSET(buf));
/* we're done, push the buffer off now */
gst_pad_push(disksrc->srcpad,buf);
}
/* open the file, necessary to go to RUNNING state */
static gboolean gst_disksrc_open_file(GstDiskSrc *src) {
+ struct stat f_stat;
g_return_val_if_fail(!GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN), FALSE);
/* open the file */
gst_element_error(GST_ELEMENT(src),"opening file");
return FALSE;
}
+ if (fstat(src->fd, &f_stat) < 0) {
+ perror("fstat()");
+ }
+ else {
+ src->size = f_stat.st_size;
+ DEBUG("gstdisksrc: file size %ld\n", src->size);
+ }
GST_FLAG_SET(src,GST_DISKSRC_OPEN);
return TRUE;
}
src->fd = 0;
src->curoffset = 0;
src->seq = 0;
+ src->size = 0;
GST_FLAG_UNSET(src,GST_DISKSRC_OPEN);
}
gulong curoffset; /* current offset in file */
gulong bytes_per_read; /* bytes per read */
+ gboolean new_seek;
gulong seq; /* buffer sequence number */
+ gulong size;
};
struct _GstDiskSrcClass {
/* if we didn't get as many bytes as we asked for, we're at EOF */
if (readbytes < fdsrc->bytes_per_read) {
- // FIXME: set the buffer's EOF bit here
+ // set the buffer's EOF bit here
+ GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS);
}
GST_BUFFER_OFFSET(buf) = fdsrc->curoffset;
GST_BUFFER_SIZE(buf) = readbytes;
if (queue->level_buffers >= queue->max_buffers) {
DEBUG("queue: %s waiting %d\n", name, queue->level_buffers);
- GST_UNLOCK(queue);
while (queue->level_buffers >= queue->max_buffers) {
+ GST_UNLOCK(queue);
g_mutex_lock(queue->fulllock);
STATUS("O");
g_cond_wait(queue->fullcond,queue->fulllock);
g_mutex_unlock(queue->fulllock);
+ GST_LOCK(queue);
}
- GST_LOCK(queue);
DEBUG("queue: %s waiting done %d\n", name, queue->level_buffers);
}
DEBUG("queue: %s push %d\n", name, queue->level_buffers);
if (!queue->level_buffers) {
- GST_UNLOCK(queue);
while (!queue->level_buffers) {
+ GST_UNLOCK(queue);
g_mutex_lock(queue->emptylock);
STATUS("U");
g_cond_wait(queue->emptycond,queue->emptylock);
g_mutex_unlock(queue->emptylock);
+ GST_LOCK(queue);
}
- GST_LOCK(queue);
}
front = queue->queue;
GST_BUFFER_EOS = (1 << 1),
GST_BUFFER_ORIGINAL = (1 << 2),
GST_BUFFER_DONTFREE = (1 << 3),
+ GST_BUFFER_FLUSH = (1 << 4),
} GstBufferFlags;
bin_PROGRAMS = gstplay
gstplay_SOURCES = \
- main.c \
+ gstplay.c \
mpeg1.c mpeg2.c avi.c\
support.c support.h \
interface.c interface.h \
#include <gnome.h>
#include <gst/gst.h>
+#include "gstplay.h"
#include "callbacks.h"
#include "interface.h"
#include "support.h"
extern GstElement *src;
+extern gboolean picture_shown;
+extern GstPlayState state;
+extern guchar statusline[];
+extern guchar *statustext;
void
on_file1_activate (GtkMenuItem *menuitem,
}
void
+on_toggle_play_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ update_buttons(0);
+ change_state(GSTPLAY_PLAYING);
+
+}
+
+void
+on_toggle_pause_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ update_buttons(1);
+ change_state(GSTPLAY_PAUSE);
+
+}
+
+void
+on_toggle_stop_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ update_buttons(2);
+ change_state(GSTPLAY_STOPPED);
+}
+
+void
on_hscale1_value_changed (GtkAdjustment *adj,
gpointer user_data)
{
- gtk_object_set(GTK_OBJECT(src),"offset",10000000,NULL);
+ int size = gst_util_get_int_arg(GTK_OBJECT(src),"size");
+
+ gtk_object_set(GTK_OBJECT(src),"offset",(int)(adj->value*size/100.0),NULL);
+ if (state != GSTPLAY_PLAYING) {
+ show_next_picture();
+ }
+}
+
+void
+on_drawingarea1_configure_event (GtkWidget *widget, GdkEventConfigure *event,
+ gpointer user_data)
+{
+ gdk_draw_rectangle(widget->window,
+ widget->style->black_gc,
+ TRUE, 0,0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, 8, 15, statustext);
+ gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, widget->allocation.width-100, 15, statusline);
}
on_hscale1_value_changed (GtkAdjustment *adj,
gpointer user_data);
+void
+on_drawingarea1_configure_event (GtkWidget *widget, GdkEventConfigure *event,
+ gpointer user_data);
+
+void
+on_toggle_play_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+on_toggle_pause_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+on_toggle_stop_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data);
# include <config.h>
#endif
-#include <gnome.h>
-#include <gst/gst.h>
+#include "gstplay.h"
#include "interface.h"
#include "support.h"
extern gboolean _gst_plugin_spew;
gboolean idle_func(gpointer data);
-GstElement *show;
+GstElement *show, *audio_play;
GstElement *src;
GstPipeline *pipeline;
+GstElement *parse = NULL;
+GstPlayState state;
+gboolean picture_shown = FALSE;
+guchar statusline[200];
+guchar *statustext = "stopped";
-void eof(GstSrc *src) {
- g_print("have eos, quitting\n");
- exit(0);
+static void frame_displayed(GstSrc *asrc)
+{
+ int size, time, frame_time = 0, src_pos;
+ guint mux_rate;
+ static int prev_time = -1;
+
+ mux_rate = gst_util_get_int_arg(GTK_OBJECT(parse),"mux_rate");
+ size = gst_util_get_int_arg(GTK_OBJECT(src),"size");
+ time = (size*8)/mux_rate;
+ frame_time = gst_util_get_int_arg(GTK_OBJECT(show),"frame_time");
+ src_pos = gst_util_get_int_arg(GTK_OBJECT(src),"offset");
+ frame_time = (src_pos*8)/mux_rate;
+
+ if (frame_time >= prev_time) {
+
+ g_snprintf(statusline, 200, "%02d:%02d / %02d:%02d\n",
+ frame_time/60, frame_time%60,
+ time/60, time%60);
+
+ //printf("%d %d %g\n", frame_time, size, frame_time*100.0/size);
+
+ update_status_area();
+ if (state == GSTPLAY_PLAYING)
+ update_slider(src_pos*100.0/size);
+ }
+ picture_shown = TRUE;
+
+ prev_time = frame_time;
+}
+
+gboolean idle_func(gpointer data) {
+ gst_src_push(GST_SRC(data));
+ return TRUE;
+}
+
+static void eof(GstSrc *src) {
+ change_state(GSTPLAY_PAUSE);
+ picture_shown = TRUE;
+}
+
+void show_next_picture() {
+ picture_shown = FALSE;
+ while (!picture_shown) {
+ gst_src_push(GST_SRC(src));
+ gtk_main_iteration_do(FALSE);
+ }
}
-void have_type(GstSink *sink) {
+void mute_audio(gboolean mute) {
+ gtk_object_set(GTK_OBJECT(audio_play),"mute",mute,NULL);
+}
+
+void change_state(GstPlayState new_state) {
+
+ if (new_state == state) return;
+ switch (new_state) {
+ case GSTPLAY_PLAYING:
+ mute_audio(FALSE);
+ statustext = "playing";
+ update_status_area();
+ gtk_idle_add(idle_func,src);
+ state = GSTPLAY_PLAYING;
+ update_buttons(0);
+ break;
+ case GSTPLAY_PAUSE:
+ statustext = "paused";
+ update_status_area();
+ if (state != GSTPLAY_STOPPED) gtk_idle_remove_by_data(src);
+ mute_audio(TRUE);
+ state = GSTPLAY_PAUSE;
+ update_buttons(1);
+ break;
+ case GSTPLAY_STOPPED:
+ if (state != GSTPLAY_PAUSE) gtk_idle_remove_by_data(src);
+ statustext = "stopped";
+ update_status_area();
+ mute_audio(TRUE);
+ state = GSTPLAY_STOPPED;
+ gtk_object_set(GTK_OBJECT(src),"offset",0,NULL);
+ update_buttons(2);
+ update_slider(0.0);
+ show_next_picture();
+ break;
+ }
+}
+
+static void have_type(GstSink *sink) {
gint type;
GstType *gsttype;
- GstElement *parse = NULL;
type = gst_util_get_int_arg(GTK_OBJECT(sink),"type");
gsttype = gst_type_find_by_id(type);
GTK_SIGNAL_FUNC(avi_new_pad_created),pipeline);
}
else if (strstr(gsttype->mime, "mpeg1")) {
- mpeg1_setup_video_thread(gst_element_get_pad(src,"src"), show, pipeline);
+ mpeg1_setup_video_thread(gst_element_get_pad(src,"src"), show, GST_ELEMENT(pipeline));
}
else {
g_print("unknown media type\n");
bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR);
textdomain (PACKAGE);
+ gtk_init(&argc,&argv);
gnome_init ("gstreamer", VERSION, argc, argv);
gst_init(&argc,&argv);
gst_plugin_load("mpeg1parse");
gst_plugin_load("mpeg2parse");
gst_plugin_load("mp1videoparse");
gst_plugin_load("mp3parse");
- gst_plugin_load("parsewav");
- gst_plugin_load("parseavi");
+ //gst_plugin_load("parsewav");
+ //gst_plugin_load("parseavi");
gst_plugin_load("videosink");
+ g_snprintf(statusline, 200, "seeking");
+
show = gst_elementfactory_make("videosink","show");
g_return_val_if_fail(show != NULL, -1);
-
window1 = create_window1 (gst_util_get_widget_arg(GTK_OBJECT(show),"widget"));
gtk_widget_show (window1);
+ gtk_signal_connect(GTK_OBJECT(show),"frame_displayed",
+ GTK_SIGNAL_FUNC(frame_displayed),NULL);
+
+ audio_play = gst_elementfactory_make("audiosink","play_audio");
pipeline = gst_pipeline_new("pipeline");
g_return_val_if_fail(pipeline != NULL, -1);
gtk_object_set(GTK_OBJECT(src),"location",argv[1],NULL);
g_print("should be using file '%s'\n",argv[1]);
+ gtk_window_set_title (GTK_WINDOW (window1), g_strdup_printf("GStreamer Media player - %s", argv[1]));
+
typefind = gst_elementfactory_make("typefind","typefind");
g_return_val_if_fail(typefind != NULL, -1);
g_print("setting to RUNNING state\n");
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_RUNNING);
- /*
- * The following code was added by Glade to create one of each component
- * (except popup menus), just so that you see something after building
- * the project. Delete any components that you don't want shown initially.
- */
+ state = GSTPLAY_STOPPED;
- while (1) {
- gst_src_push(GST_SRC(src));
- }
+ change_state(GSTPLAY_PLAYING);
+ gtk_main();
return 0;
}
#include "interface.h"
#include "support.h"
+GtkWidget *drawingarea1;
+GtkObject *adjustment;
+GtkWidget *button6;
+GtkWidget *button7;
+GtkWidget *button8;
+extern guchar statusline[];
+extern guchar *statustext;
+
static GnomeUIInfo file1_menu_uiinfo[] =
{
{
GtkWidget *handlebox1;
GtkWidget *toolbar1;
GtkWidget *tmp_toolbar_icon;
- GtkWidget *button6;
- GtkWidget *button7;
- GtkWidget *button8;
GtkWidget *vseparator1;
- GtkObject *adjustment;
window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_object_set_data (GTK_OBJECT (window1), "window1", window1);
gtk_widget_show (vbox2);
gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, TRUE, 0);
- adjustment = gtk_adjustment_new (0, 0, 100, 1, 10, 10);
+ adjustment = gtk_adjustment_new (0, 0.0, 110.0, 1, 10.0, 10.0);
hscale1 = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
gtk_widget_ref (hscale1);
gtk_object_set_data_full (GTK_OBJECT (window1), "hscale1", hscale1,
tmp_toolbar_icon = create_pixmap (window1, "pixmaps/play.xpm", TRUE);
button6 = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar1),
- GTK_TOOLBAR_CHILD_BUTTON,
+ GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
NULL,
_("button6"),
NULL, NULL,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button6);
+ gtk_signal_connect (GTK_OBJECT (button6), "toggled",
+ GTK_SIGNAL_FUNC (on_toggle_play_toggled), NULL);
+
tmp_toolbar_icon = create_pixmap (window1, "pixmaps/pause.xpm", TRUE);
button7 = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar1),
- GTK_TOOLBAR_CHILD_BUTTON,
+ GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
NULL,
_("button7"),
NULL, NULL,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button7);
+ gtk_signal_connect (GTK_OBJECT (button7), "toggled",
+ GTK_SIGNAL_FUNC (on_toggle_pause_toggled), NULL);
+
tmp_toolbar_icon = create_pixmap (window1, "pixmaps/stop.xpm", TRUE);
button8 = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar1),
- GTK_TOOLBAR_CHILD_BUTTON,
+ GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
NULL,
_("button8"),
NULL, NULL,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button8);
+ gtk_signal_connect (GTK_OBJECT (button8), "toggled",
+ GTK_SIGNAL_FUNC (on_toggle_stop_toggled), NULL);
+
vseparator1 = gtk_vseparator_new ();
gtk_widget_ref (vseparator1);
gtk_object_set_data_full (GTK_OBJECT (window1), "vseparator1", vseparator1,
gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar1), vseparator1, NULL, NULL);
gtk_widget_set_usize (vseparator1, 8, 21);
+ drawingarea1 = gtk_drawing_area_new ();
+ gtk_widget_ref (drawingarea1);
+ gtk_object_set_data_full (GTK_OBJECT (window1), "drawingarea1", drawingarea1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (drawingarea1);
+ gtk_box_pack_start (GTK_BOX (vbox1), drawingarea1, FALSE, TRUE, 1);
+ gtk_widget_set_usize (drawingarea1, -2, 21);
+
+ gtk_signal_connect (GTK_OBJECT (drawingarea1), "configure_event",
+ GTK_SIGNAL_FUNC (on_drawingarea1_configure_event),
+ NULL);
return window1;
}
+void update_buttons(int active)
+{
+ gtk_signal_handler_block_by_func(GTK_OBJECT(button6),
+ GTK_SIGNAL_FUNC (on_toggle_play_toggled),
+ NULL);
+ gtk_signal_handler_block_by_func(GTK_OBJECT(button7),
+ GTK_SIGNAL_FUNC (on_toggle_pause_toggled),
+ NULL);
+ gtk_signal_handler_block_by_func(GTK_OBJECT(button8),
+ GTK_SIGNAL_FUNC (on_toggle_stop_toggled),
+ NULL);
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button6), FALSE);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button7), FALSE);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button8), FALSE);
+
+ if (active == 0) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button6), TRUE);
+ }
+ else if (active == 1) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button7), TRUE);
+ }
+ else if (active == 2) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button8), TRUE);
+ }
+
+ gtk_signal_handler_unblock_by_func(GTK_OBJECT(button6),
+ GTK_SIGNAL_FUNC (on_toggle_play_toggled),
+ NULL);
+ gtk_signal_handler_unblock_by_func(GTK_OBJECT(button7),
+ GTK_SIGNAL_FUNC (on_toggle_pause_toggled),
+ NULL);
+ gtk_signal_handler_unblock_by_func(GTK_OBJECT(button8),
+ GTK_SIGNAL_FUNC (on_toggle_stop_toggled),
+ NULL);
+}
+
+void update_slider(gfloat value)
+{
+ gtk_signal_handler_block_by_func(adjustment,
+ GTK_SIGNAL_FUNC (on_hscale1_value_changed),
+ NULL);
+ gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustment), value);
+ gtk_signal_handler_unblock_by_func(adjustment,
+ GTK_SIGNAL_FUNC (on_hscale1_value_changed),
+ NULL);
+}
+
+void update_status_area()
+{
+ GtkWidget *widget = drawingarea1;
+
+ gdk_draw_rectangle(widget->window,
+ widget->style->black_gc,
+ TRUE, 0,
+ 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, 8, 15, statustext);
+ gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, widget->allocation.width-100, 15, statusline);
+
+}
*/
GtkWidget* create_window1 (GtkWidget *video_element);
+void update_status_area();
+void update_slider(gfloat value);
+void update_buttons(int active);
-#define BUFFER 1
+#define BUFFER 15
#define VIDEO_DECODER "mpeg_play"
#ifdef HAVE_CONFIG_H
extern gboolean _gst_plugin_spew;
extern GstElement *show;
+extern GstElement *audio_play;
void mpeg1_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline)
{
- GstElement *parse_audio, *decode, *play;
+ GstElement *parse_audio, *decode;
GstElement *audio_queue;
GstElement *audio_thread;
// connect to audio pad
//if (0) {
- if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0) {
+ if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0 && audio_play) {
gst_plugin_load("mp3parse");
gst_plugin_load("mpg123");
// construct internal pipeline elements
g_return_if_fail(parse_audio != NULL);
decode = gst_elementfactory_make("mpg123","decode_audio");
g_return_if_fail(decode != NULL);
- play = gst_elementfactory_make("audiosink","play_audio");
- g_return_if_fail(play != NULL);
// create the thread and pack stuff into it
audio_thread = gst_thread_new("audio_thread");
g_return_if_fail(audio_thread != NULL);
gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(parse_audio));
gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(decode));
- gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(play));
+ gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(audio_play));
// set up pad connections
gst_element_add_ghost_pad(GST_ELEMENT(audio_thread),
gst_pad_connect(gst_element_get_pad(parse_audio,"src"),
gst_element_get_pad(decode,"sink"));
gst_pad_connect(gst_element_get_pad(decode,"src"),
- gst_element_get_pad(play,"sink"));
+ gst_element_get_pad(audio_play,"sink"));
// construct queue and connect everything in the main pipelie
audio_queue = gst_elementfactory_make("queue","audio_queue");
-#define BUFFER 1
+#define BUFFER 15
#define VIDEO_DECODER "mpeg2play"
#ifdef HAVE_CONFIG_H
extern gboolean _gst_plugin_spew;
-extern GstElement *show;
+extern GstElement *show, *audio_play;
void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline)
{
- GstElement *parse_audio, *decode, *play;
+ GstElement *parse_audio, *decode;
GstElement *audio_queue;
GstElement *audio_thread;
// connect to audio pad
//if (0) {
- if (strncmp(gst_pad_get_name(pad), "private_stream_1.0", 18) == 0) {
+ if (strncmp(gst_pad_get_name(pad), "private_stream_1.0", 18) == 0 && audio_play) {
gst_plugin_load("ac3parse");
gst_plugin_load("ac3dec");
// construct internal pipeline elements
g_return_if_fail(parse_audio != NULL);
decode = gst_elementfactory_make("ac3dec","decode_audio");
g_return_if_fail(decode != NULL);
- play = gst_elementfactory_make("audiosink","play_audio");
- g_return_if_fail(play != NULL);
// create the thread and pack stuff into it
audio_thread = gst_thread_new("audio_thread");
g_return_if_fail(audio_thread != NULL);
gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(parse_audio));
gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(decode));
- gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(play));
+ gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(audio_play));
// set up pad connections
gst_element_add_ghost_pad(GST_ELEMENT(audio_thread),
gst_pad_connect(gst_element_get_pad(parse_audio,"src"),
gst_element_get_pad(decode,"sink"));
gst_pad_connect(gst_element_get_pad(decode,"src"),
- gst_element_get_pad(play,"sink"));
+ gst_element_get_pad(audio_play,"sink"));
// construct queue and connect everything in the main pipelie
audio_queue = gst_elementfactory_make("queue","audio_queue");
}
// connect to audio pad
//if (0) {
- if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0) {
+ if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0 && audio_play) {
gst_plugin_load("mp3parse");
gst_plugin_load("mpg123");
// construct internal pipeline elements
g_return_if_fail(parse_audio != NULL);
decode = gst_elementfactory_make("mpg123","decode_audio");
g_return_if_fail(decode != NULL);
- play = gst_elementfactory_make("audiosink","play_audio");
- g_return_if_fail(play != NULL);
// create the thread and pack stuff into it
audio_thread = gst_thread_new("audio_thread");
g_return_if_fail(audio_thread != NULL);
gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(parse_audio));
gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(decode));
- gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(play));
+ gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(audio_play));
// set up pad connections
gst_element_add_ghost_pad(GST_ELEMENT(audio_thread),
gst_pad_connect(gst_element_get_pad(parse_audio,"src"),
gst_element_get_pad(decode,"sink"));
gst_pad_connect(gst_element_get_pad(decode,"src"),
- gst_element_get_pad(play,"sink"));
+ gst_element_get_pad(audio_play,"sink"));
// construct queue and connect everything in the main pipelie
audio_queue = gst_elementfactory_make("queue","audio_queue");
}
#ifdef HAVE_LIBMMX
-
+static mmx_t MMX_10w = (mmx_t)(long long)0x000D000D000D000DLL; //dd 00080 0080h, 000800080h
static mmx_t MMX_80w = (mmx_t)(long long)0x0080008000800080LL; //dd 00080 0080h, 000800080h
static mmx_t MMX_00FFw = (mmx_t)(long long)0x00ff00ff00ff00ffLL; //dd 000FF 00FFh, 000FF00FFh
pmullw_m2r(MMX16_Vgrncoeff, mm3); // Cr2green
movq_m2r(*(mmx_t *)lum, mm7); // L2
pmullw_m2r(MMX16_Vredcoeff, mm1); // Cr2red
- // "psubw MMX_10w, %%mm6\n"
+ psubw_m2r(MMX_10w, mm6);
psrlw_i2r(8, mm7); // L2 00 L7 00 L5 00 L3 00 L1
pmullw_m2r(MMX16_Ycoeff, mm6); // lum1
- // "psubw MMX_10w, %%mm7\n" // L2
+ psubw_m2r(MMX_10w, mm7);
paddw_r2r(mm3, mm2); // Cb2green + Cr2green == green
pmullw_m2r(MMX16_Ycoeff, mm7); // lum2
packuswb_r2r(mm5, mm5);
packuswb_r2r(mm7, mm7);
pand_m2r(MMX_00FFw, mm6); // L3
+ psubw_m2r(MMX_10w, mm6);
punpcklbw_r2r(mm3, mm3);
// "psubw MMX_10w, %%mm6\n" // L3
punpcklbw_r2r(mm5, mm5);
movq_r2r(mm4, mm5);
// "psubw MMX_10w, %%mm7\n" // L4
punpcklwd_r2r(mm3, mm4);
+ psubw_m2r(MMX_10w, mm7);
pmullw_m2r(MMX16_Ycoeff, mm7); // lum4
punpckhwd_r2r(mm3, mm5);
pos += inc;
}
*eip++ = RETURN;
- g_print("scaler start/end %p %p %p\n", copy_row, eip, eip-copy_row);
+ DEBUG("scaler start/end %p %p %p\n", copy_row, eip, eip-copy_row);
}
static gboolean gst_audiosink_change_state(GstElement *element,
GstElementState state);
+static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id);
+static void gst_audiosink_get_arg(GtkObject *object,GtkArg *arg,guint id);
+
void gst_audiosink_chain(GstPad *pad,GstBuffer *buf);
/* AudioSink signals and args */
enum {
- HANDOFF,
+ SIGNAL_HANDOFF,
LAST_SIGNAL
};
enum {
ARG_0,
+ ARG_MUTE,
+ ARG_FORMAT,
+ ARG_CHANNELS,
+ ARG_FREQUENCY,
/* FILL ME */
};
parent_class = gtk_type_class(GST_TYPE_FILTER);
- gst_audiosink_signals[HANDOFF] =
+ gtk_object_add_arg_type("GstAudioSink::mute", GTK_TYPE_BOOL,
+ GTK_ARG_READWRITE, ARG_MUTE);
+ gtk_object_add_arg_type("GstAudioSink::format", GTK_TYPE_INT,
+ GTK_ARG_READWRITE, ARG_FORMAT);
+ gtk_object_add_arg_type("GstAudioSink::channels", GTK_TYPE_INT,
+ GTK_ARG_READWRITE, ARG_CHANNELS);
+ gtk_object_add_arg_type("GstAudioSink::frequency", GTK_TYPE_INT,
+ GTK_ARG_READWRITE, ARG_FREQUENCY);
+
+ gtkobject_class->set_arg = gst_audiosink_set_arg;
+ gtkobject_class->get_arg = gst_audiosink_get_arg;
+
+ gst_audiosink_signals[SIGNAL_HANDOFF] =
gtk_signal_new("handoff",GTK_RUN_LAST,gtkobject_class->type,
GTK_SIGNAL_OFFSET(GstAudioSinkClass,handoff),
gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1,
}
}
- gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[HANDOFF],
+ gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[SIGNAL_HANDOFF],
audiosink);
if (GST_BUFFER_DATA(buf) != NULL) {
gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard");
audiosink->clocktime = (info.bytes*1000000LL)/(audiosink->frequency*audiosink->channels);
//g_print("audiosink: bytes sent %d time %llu\n", info.bytes, audiosink->clocktime);
gst_clock_set(audiosink->clock, audiosink->clocktime);
- write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
+ if (!audiosink->mute)
+ write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
//audiosink->clocktime += (1000000LL*GST_BUFFER_SIZE(buf)/(audiosink->channels*
// (audiosink->format/8)*(audiosink->frequency)));
//g_print("audiosink: writing to soundcard ok\n");
//g_print("a done\n");
}
-void gst_audiosink_set_format(GstAudioSink *audiosink,gint format) {
- g_return_if_fail(audiosink != NULL);
- g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
-
- audiosink->format = format;
-
- gst_audiosink_sync_parms(audiosink);
-}
+static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id) {
+ GstAudioSink *audiosink;
-void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels) {
- g_return_if_fail(audiosink != NULL);
- g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_AUDIOSINK(object));
+ audiosink = GST_AUDIOSINK(object);
- audiosink->channels = channels;
-
- gst_audiosink_sync_parms(audiosink);
+ switch(id) {
+ case ARG_MUTE:
+ audiosink->mute = GTK_VALUE_BOOL(*arg);
+ break;
+ case ARG_FORMAT:
+ audiosink->format = GTK_VALUE_INT(*arg);
+ gst_audiosink_sync_parms(audiosink);
+ break;
+ case ARG_CHANNELS:
+ audiosink->channels = GTK_VALUE_INT(*arg);
+ gst_audiosink_sync_parms(audiosink);
+ break;
+ case ARG_FREQUENCY:
+ audiosink->frequency = GTK_VALUE_INT(*arg);
+ gst_audiosink_sync_parms(audiosink);
+ break;
+ default:
+ break;
+ }
}
-void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) {
- g_return_if_fail(audiosink != NULL);
- g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
+static void gst_audiosink_get_arg(GtkObject *object,GtkArg *arg,guint id) {
+ GstAudioSink *audiosink;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_AUDIOSINK(object));
+ audiosink = GST_AUDIOSINK(object);
- audiosink->frequency = frequency;
-
- gst_audiosink_sync_parms(audiosink);
+ switch(id) {
+ case ARG_MUTE:
+ GTK_VALUE_BOOL(*arg) = audiosink->mute;
+ break;
+ case ARG_FORMAT:
+ GTK_VALUE_INT(*arg) = audiosink->format;
+ break;
+ case ARG_CHANNELS:
+ GTK_VALUE_INT(*arg) = audiosink->channels;
+ break;
+ case ARG_FREQUENCY:
+ GTK_VALUE_INT(*arg) = audiosink->frequency;
+ break;
+ default:
+ break;
+ }
}
static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
gint format;
gint channels;
gint frequency;
+ gboolean mute;
};
struct _GstAudioSinkClass {
ARG_LOCATION,
ARG_BYTESPERREAD,
ARG_OFFSET,
+ ARG_SIZE,
};
GTK_ARG_READWRITE, ARG_BYTESPERREAD);
gtk_object_add_arg_type("GstDiskSrc::offset", GTK_TYPE_INT,
GTK_ARG_READWRITE, ARG_OFFSET);
+ gtk_object_add_arg_type("GstDiskSrc::size", GTK_TYPE_INT,
+ GTK_ARG_READABLE, ARG_SIZE);
gtkobject_class->set_arg = gst_disksrc_set_arg;
gtkobject_class->get_arg = gst_disksrc_get_arg;
disksrc->curoffset = 0;
disksrc->bytes_per_read = 4096;
disksrc->seq = 0;
+ disksrc->size = 0;
+ disksrc->new_seek = FALSE;
}
case ARG_OFFSET:
src->curoffset = GTK_VALUE_INT(*arg);
lseek(src->fd,src->curoffset, SEEK_SET);
+ src->new_seek = TRUE;
break;
default:
break;
case ARG_OFFSET:
GTK_VALUE_INT(*arg) = src->curoffset;
break;
+ case ARG_SIZE:
+ GTK_VALUE_INT(*arg) = src->size;
+ break;
default:
arg->type = GTK_TYPE_INVALID;
break;
/* read it in from the file */
readbytes = read(disksrc->fd,GST_BUFFER_DATA(buf),disksrc->bytes_per_read);
- if (readbytes == 0) {
+ if (readbytes == -1) {
+ perror("read()");
+ gst_buffer_unref(buf);
+ return;
+ }
+ else if (readbytes == 0) {
gst_src_signal_eos(GST_SRC(disksrc));
- gst_buffer_unref(buf);
+ gst_buffer_unref(buf);
return;
}
/* if we didn't get as many bytes as we asked for, we're at EOF */
if (readbytes < disksrc->bytes_per_read)
- GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS);
+ GST_BUFFER_FLAG_SET(buf, GST_BUFFER_EOS);
+
+ /* if we have a new buffer froma seek, mark it */
+ if (disksrc->new_seek) {
+ GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLUSH);
+ disksrc->new_seek = FALSE;
+ }
+
GST_BUFFER_OFFSET(buf) = disksrc->curoffset;
GST_BUFFER_SIZE(buf) = readbytes;
disksrc->curoffset += readbytes;
+ DEBUG("pushing with offset %lu\n", GST_BUFFER_OFFSET(buf));
/* we're done, push the buffer off now */
gst_pad_push(disksrc->srcpad,buf);
}
/* open the file, necessary to go to RUNNING state */
static gboolean gst_disksrc_open_file(GstDiskSrc *src) {
+ struct stat f_stat;
g_return_val_if_fail(!GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN), FALSE);
/* open the file */
gst_element_error(GST_ELEMENT(src),"opening file");
return FALSE;
}
+ if (fstat(src->fd, &f_stat) < 0) {
+ perror("fstat()");
+ }
+ else {
+ src->size = f_stat.st_size;
+ DEBUG("gstdisksrc: file size %ld\n", src->size);
+ }
GST_FLAG_SET(src,GST_DISKSRC_OPEN);
return TRUE;
}
src->fd = 0;
src->curoffset = 0;
src->seq = 0;
+ src->size = 0;
GST_FLAG_UNSET(src,GST_DISKSRC_OPEN);
}
gulong curoffset; /* current offset in file */
gulong bytes_per_read; /* bytes per read */
+ gboolean new_seek;
gulong seq; /* buffer sequence number */
+ gulong size;
};
struct _GstDiskSrcClass {
/* if we didn't get as many bytes as we asked for, we're at EOF */
if (readbytes < fdsrc->bytes_per_read) {
- // FIXME: set the buffer's EOF bit here
+ // set the buffer's EOF bit here
+ GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS);
}
GST_BUFFER_OFFSET(buf) = fdsrc->curoffset;
GST_BUFFER_SIZE(buf) = readbytes;
if (queue->level_buffers >= queue->max_buffers) {
DEBUG("queue: %s waiting %d\n", name, queue->level_buffers);
- GST_UNLOCK(queue);
while (queue->level_buffers >= queue->max_buffers) {
+ GST_UNLOCK(queue);
g_mutex_lock(queue->fulllock);
STATUS("O");
g_cond_wait(queue->fullcond,queue->fulllock);
g_mutex_unlock(queue->fulllock);
+ GST_LOCK(queue);
}
- GST_LOCK(queue);
DEBUG("queue: %s waiting done %d\n", name, queue->level_buffers);
}
DEBUG("queue: %s push %d\n", name, queue->level_buffers);
if (!queue->level_buffers) {
- GST_UNLOCK(queue);
while (!queue->level_buffers) {
+ GST_UNLOCK(queue);
g_mutex_lock(queue->emptylock);
STATUS("U");
g_cond_wait(queue->emptycond,queue->emptylock);
g_mutex_unlock(queue->emptylock);
+ GST_LOCK(queue);
}
- GST_LOCK(queue);
}
front = queue->queue;
gtk_object_set(GTK_OBJECT(smooth),"tolerance",9,NULL);
encode = gst_elementfactory_make("mpeg2enc","encode");
g_return_if_fail(encode != NULL);
- gtk_object_set(GTK_OBJECT(encode),"frames_per_second",29.97,NULL);
+ gtk_object_set(GTK_OBJECT(encode),"frames_per_second",24.0,NULL);
//encode = gst_elementfactory_make("mpeg1encoder","encode");
//gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL);
exit(0);
}
+gboolean idle_func(gpointer data) {
+ gst_src_push(GST_SRC(data));
+ return TRUE;
+}
+
void mpeg2parse_newpad(GstElement *parser,GstPad *pad, GstElement *pipeline) {
GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *show;
GstElement *audio_queue, *video_queue;
g_print("have %d args\n",argc);
+ gtk_init(&argc,&argv);
gst_init(&argc,&argv);
gnome_init("MPEG2 Video player","0.0.1",argc,argv);
gst_plugin_load("mpeg2parse");
g_print("setting to RUNNING state\n");
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_RUNNING);
- while (1) {
- gst_src_push(GST_SRC(src));
- }
+ gtk_idle_add(idle_func,src);
+
+ gtk_main();
}