2000-06-25 21:38:00 +00:00
|
|
|
/*
|
|
|
|
* Initial main.c file generated by Glade. Edit as required.
|
|
|
|
* Glade will not overwrite this file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2000-07-12 22:52:42 +00:00
|
|
|
//#define DEBUG_ENABLED
|
|
|
|
|
|
|
|
#include <gst/gstclock.h>
|
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
#include "gstplay.h"
|
2000-06-25 21:38:00 +00:00
|
|
|
|
|
|
|
#include "interface.h"
|
|
|
|
#include "support.h"
|
|
|
|
|
|
|
|
#include "codecs.h"
|
|
|
|
|
2000-07-12 22:52:42 +00:00
|
|
|
#define MUTEX_STATUS() (g_mutex_trylock(gdk_threads_mutex)? g_mutex_unlock(gdk_threads_mutex), "was not locked" : "was locked")
|
|
|
|
|
|
|
|
|
|
|
|
#define BUFFER 4
|
|
|
|
|
2000-06-25 21:38:00 +00:00
|
|
|
extern gboolean _gst_plugin_spew;
|
|
|
|
gboolean idle_func(gpointer data);
|
2000-07-12 22:52:42 +00:00
|
|
|
GstElement *show, *video_render_queue;
|
|
|
|
GstElement *audio_play, *audio_render_queue;
|
2000-06-25 21:38:00 +00:00
|
|
|
GstElement *src;
|
|
|
|
GstPipeline *pipeline;
|
2000-07-05 10:21:08 +00:00
|
|
|
GstElement *parse = NULL;
|
|
|
|
GstPlayState state;
|
|
|
|
gboolean picture_shown = FALSE;
|
|
|
|
guchar statusline[200];
|
|
|
|
guchar *statustext = "stopped";
|
2000-06-25 21:38:00 +00:00
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
static void frame_displayed(GstSrc *asrc)
|
|
|
|
{
|
|
|
|
int size, time, frame_time = 0, src_pos;
|
|
|
|
guint mux_rate;
|
|
|
|
static int prev_time = -1;
|
|
|
|
|
2000-07-15 12:06:18 +00:00
|
|
|
if (!parse) return;
|
|
|
|
return;
|
2000-07-12 22:52:42 +00:00
|
|
|
DEBUG("gstplay: frame displayed %s\n", MUTEX_STATUS());
|
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
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;
|
2000-07-12 22:52:42 +00:00
|
|
|
DEBUG("gstplay: frame displayed end %s\n", MUTEX_STATUS());
|
2000-07-05 10:21:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean idle_func(gpointer data) {
|
2000-07-12 22:52:42 +00:00
|
|
|
DEBUG("idle start %s\n",MUTEX_STATUS());
|
2000-07-05 10:21:08 +00:00
|
|
|
gst_src_push(GST_SRC(data));
|
2000-07-12 22:52:42 +00:00
|
|
|
DEBUG("idle stop %s\n",MUTEX_STATUS());
|
2000-07-05 10:21:08 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eof(GstSrc *src) {
|
|
|
|
change_state(GSTPLAY_PAUSE);
|
|
|
|
picture_shown = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void show_next_picture() {
|
|
|
|
picture_shown = FALSE;
|
2000-07-12 22:52:42 +00:00
|
|
|
DEBUG("gstplay: next picture %s\n", MUTEX_STATUS());
|
2000-07-05 10:21:08 +00:00
|
|
|
while (!picture_shown) {
|
2000-07-12 22:52:42 +00:00
|
|
|
gdk_threads_leave();
|
2000-07-05 10:21:08 +00:00
|
|
|
gst_src_push(GST_SRC(src));
|
2000-07-12 22:52:42 +00:00
|
|
|
gdk_threads_enter();
|
2000-07-05 10:21:08 +00:00
|
|
|
}
|
2000-07-12 22:52:42 +00:00
|
|
|
DEBUG("gstplay: next found %s\n", MUTEX_STATUS());
|
2000-06-25 21:38:00 +00:00
|
|
|
}
|
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
void mute_audio(gboolean mute) {
|
|
|
|
gtk_object_set(GTK_OBJECT(audio_play),"mute",mute,NULL);
|
|
|
|
}
|
|
|
|
|
2000-07-13 19:49:50 +00:00
|
|
|
gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
|
|
|
|
{
|
|
|
|
gdk_threads_leave();
|
|
|
|
g_print("setting to ~PLAYING state\n");
|
|
|
|
gst_element_set_state(GST_ELEMENT(pipeline),~GST_STATE_PLAYING);
|
|
|
|
g_print("setting to ~RUNNING state\n");
|
|
|
|
gst_element_set_state(GST_ELEMENT(pipeline),~GST_STATE_RUNNING);
|
|
|
|
gdk_threads_enter();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void destroy(GtkWidget *widget, gpointer data)
|
|
|
|
{
|
|
|
|
|
|
|
|
gtk_main_quit();
|
|
|
|
}
|
|
|
|
|
2000-07-12 22:52:42 +00:00
|
|
|
void gstplay_parse_state_changed(GstElement *element, gint state, gpointer data)
|
|
|
|
{
|
|
|
|
printf("gstplay: element \"%s\" state changed %d\n", gst_element_get_name(element), state);
|
|
|
|
|
|
|
|
if (state == GST_STATE_COMPLETE) {
|
|
|
|
g_print("gstplay: setting to PLAYING state\n");
|
|
|
|
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);
|
|
|
|
gst_clock_reset(gst_clock_get_system());
|
|
|
|
g_print("gstplay: PLAYING\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
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) {
|
2000-06-25 21:38:00 +00:00
|
|
|
gint type;
|
|
|
|
GstType *gsttype;
|
|
|
|
|
|
|
|
type = gst_util_get_int_arg(GTK_OBJECT(sink),"type");
|
|
|
|
gsttype = gst_type_find_by_id(type);
|
|
|
|
|
|
|
|
g_print("have type %d:%s\n", type, gsttype->mime);
|
|
|
|
|
|
|
|
gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(sink));
|
|
|
|
|
|
|
|
gst_pad_disconnect(gst_element_get_pad(src,"src"),
|
|
|
|
gst_element_get_pad(GST_ELEMENT(sink),"sink"));
|
|
|
|
|
2000-06-25 22:21:44 +00:00
|
|
|
if (strstr(gsttype->mime, "mpeg1-system")) {
|
2000-07-12 22:52:42 +00:00
|
|
|
parse = gst_elementfactory_make("mpeg1parse","mpeg1_system_parse");
|
2000-06-25 21:38:00 +00:00
|
|
|
gtk_signal_connect(GTK_OBJECT(parse),"new_pad",
|
|
|
|
GTK_SIGNAL_FUNC(mpeg1_new_pad_created),pipeline);
|
|
|
|
}
|
2000-06-25 22:21:44 +00:00
|
|
|
else if (strstr(gsttype->mime, "mpeg2-system")) {
|
2000-07-12 22:52:42 +00:00
|
|
|
parse = gst_elementfactory_make("mpeg2parse","mpeg2_system_parse");
|
2000-06-25 22:21:44 +00:00
|
|
|
gtk_signal_connect(GTK_OBJECT(parse),"new_pad",
|
|
|
|
GTK_SIGNAL_FUNC(mpeg2_new_pad_created),pipeline);
|
|
|
|
}
|
2000-06-25 21:38:00 +00:00
|
|
|
else if (strstr(gsttype->mime, "avi")) {
|
|
|
|
parse = gst_elementfactory_make("parseavi","parse");
|
|
|
|
gtk_signal_connect(GTK_OBJECT(parse),"new_pad",
|
|
|
|
GTK_SIGNAL_FUNC(avi_new_pad_created),pipeline);
|
|
|
|
}
|
|
|
|
else if (strstr(gsttype->mime, "mpeg1")) {
|
2000-07-15 12:06:18 +00:00
|
|
|
mpeg1_setup_video_thread(gst_element_get_pad(src,"src"), video_render_queue, GST_ELEMENT(pipeline));
|
|
|
|
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);
|
|
|
|
gst_clock_reset(gst_clock_get_system());
|
2000-06-25 21:38:00 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
g_print("unknown media type\n");
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parse) {
|
|
|
|
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(parse));
|
|
|
|
gst_pad_connect(gst_element_get_pad(src,"src"),
|
|
|
|
gst_element_get_pad(parse,"sink"));
|
2000-07-12 22:52:42 +00:00
|
|
|
gtk_signal_connect(GTK_OBJECT(parse),"state_change",
|
|
|
|
GTK_SIGNAL_FUNC(gstplay_parse_state_changed),pipeline);
|
2000-06-25 21:38:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gtk_object_set(GTK_OBJECT(src),"offset",0,NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main (int argc, char *argv[])
|
|
|
|
{
|
|
|
|
GtkWidget *window1;
|
|
|
|
GstElement *typefind;
|
2000-07-12 22:52:42 +00:00
|
|
|
GstElement *video_render_thread;
|
|
|
|
GstElement *audio_render_thread;
|
2000-06-25 21:38:00 +00:00
|
|
|
|
|
|
|
bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR);
|
|
|
|
textdomain (PACKAGE);
|
|
|
|
|
2000-07-12 22:52:42 +00:00
|
|
|
g_thread_init(NULL);
|
2000-07-05 10:21:08 +00:00
|
|
|
gtk_init(&argc,&argv);
|
2000-06-25 21:38:00 +00:00
|
|
|
gnome_init ("gstreamer", VERSION, argc, argv);
|
|
|
|
gst_init(&argc,&argv);
|
|
|
|
gst_plugin_load("mpeg1parse");
|
2000-06-25 22:21:44 +00:00
|
|
|
gst_plugin_load("mpeg2parse");
|
2000-06-25 21:38:00 +00:00
|
|
|
gst_plugin_load("mp1videoparse");
|
|
|
|
gst_plugin_load("mp3parse");
|
2000-07-12 22:52:42 +00:00
|
|
|
gst_plugin_load("parsewav");
|
|
|
|
gst_plugin_load("parseavi");
|
2000-06-25 21:38:00 +00:00
|
|
|
gst_plugin_load("videosink");
|
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
g_snprintf(statusline, 200, "seeking");
|
|
|
|
|
2000-07-12 22:52:42 +00:00
|
|
|
pipeline = gst_pipeline_new("main_pipeline");
|
|
|
|
g_return_val_if_fail(pipeline != NULL, -1);
|
|
|
|
|
|
|
|
video_render_thread = gst_thread_new("video_render_thread");
|
|
|
|
g_return_val_if_fail(video_render_thread != NULL, -1);
|
2000-06-25 21:38:00 +00:00
|
|
|
show = gst_elementfactory_make("videosink","show");
|
|
|
|
g_return_val_if_fail(show != NULL, -1);
|
2000-07-15 12:06:18 +00:00
|
|
|
gtk_object_set(GTK_OBJECT(show),"xv_enabled",FALSE,NULL);
|
2000-06-25 21:38:00 +00:00
|
|
|
window1 = create_window1 (gst_util_get_widget_arg(GTK_OBJECT(show),"widget"));
|
|
|
|
gtk_widget_show (window1);
|
2000-07-13 19:49:50 +00:00
|
|
|
gtk_signal_connect(GTK_OBJECT(window1),"delete_event",
|
|
|
|
GTK_SIGNAL_FUNC(delete_event),NULL);
|
|
|
|
gtk_signal_connect(GTK_OBJECT(window1),"destroy",
|
|
|
|
GTK_SIGNAL_FUNC(destroy),pipeline);
|
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
gtk_signal_connect(GTK_OBJECT(show),"frame_displayed",
|
|
|
|
GTK_SIGNAL_FUNC(frame_displayed),NULL);
|
2000-07-12 22:52:42 +00:00
|
|
|
gst_bin_add(GST_BIN(video_render_thread),GST_ELEMENT(show));
|
|
|
|
gst_element_add_ghost_pad(GST_ELEMENT(video_render_thread),
|
|
|
|
gst_element_get_pad(show,"sink"));
|
|
|
|
|
|
|
|
video_render_queue = gst_elementfactory_make("queue","video_render_queue");
|
|
|
|
gtk_object_set(GTK_OBJECT(video_render_queue),"max_level",BUFFER,NULL);
|
|
|
|
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_render_queue));
|
|
|
|
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_render_thread));
|
|
|
|
gst_pad_connect(gst_element_get_pad(video_render_queue,"src"),
|
|
|
|
gst_element_get_pad(video_render_thread,"sink"));
|
|
|
|
gtk_object_set(GTK_OBJECT(video_render_thread),"create_thread",TRUE,NULL);
|
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
|
2000-07-12 22:52:42 +00:00
|
|
|
audio_render_thread = gst_thread_new("audio_render_thread");
|
|
|
|
g_return_val_if_fail(audio_render_thread != NULL, -1);
|
2000-07-05 10:21:08 +00:00
|
|
|
audio_play = gst_elementfactory_make("audiosink","play_audio");
|
2000-07-12 22:52:42 +00:00
|
|
|
gst_bin_add(GST_BIN(audio_render_thread),GST_ELEMENT(audio_play));
|
|
|
|
gst_element_add_ghost_pad(GST_ELEMENT(audio_render_thread),
|
|
|
|
gst_element_get_pad(audio_play,"sink"));
|
|
|
|
|
|
|
|
audio_render_queue = gst_elementfactory_make("queue","audio_render_queue");
|
|
|
|
gtk_object_set(GTK_OBJECT(audio_render_queue),"max_level",BUFFER,NULL);
|
|
|
|
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_render_queue));
|
|
|
|
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_render_thread));
|
|
|
|
gst_pad_connect(gst_element_get_pad(audio_render_queue,"src"),
|
|
|
|
gst_element_get_pad(audio_render_thread,"sink"));
|
|
|
|
gtk_object_set(GTK_OBJECT(audio_render_thread),"create_thread",TRUE,NULL);
|
2000-06-25 21:38:00 +00:00
|
|
|
|
|
|
|
|
2000-07-12 22:52:42 +00:00
|
|
|
src = gst_elementfactory_make("disksrc","disk_src");
|
2000-06-25 21:38:00 +00:00
|
|
|
g_return_val_if_fail(src != NULL, -1);
|
|
|
|
g_print("should be using file '%s'\n",argv[1]);
|
2000-07-12 22:52:42 +00:00
|
|
|
gtk_object_set(GTK_OBJECT(src),"location",argv[1],NULL);
|
2000-06-25 21:38:00 +00:00
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
gtk_window_set_title (GTK_WINDOW (window1), g_strdup_printf("GStreamer Media player - %s", argv[1]));
|
|
|
|
|
2000-06-25 21:38:00 +00:00
|
|
|
typefind = gst_elementfactory_make("typefind","typefind");
|
|
|
|
g_return_val_if_fail(typefind != NULL, -1);
|
|
|
|
|
|
|
|
gtk_signal_connect(GTK_OBJECT(typefind),"have_type",
|
|
|
|
GTK_SIGNAL_FUNC(have_type),NULL);
|
|
|
|
|
|
|
|
|
|
|
|
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(src));
|
|
|
|
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(typefind));
|
|
|
|
|
|
|
|
|
|
|
|
gtk_signal_connect(GTK_OBJECT(src),"eos",
|
|
|
|
GTK_SIGNAL_FUNC(eof),NULL);
|
|
|
|
|
|
|
|
gst_pad_connect(gst_element_get_pad(src,"src"),
|
|
|
|
gst_element_get_pad(typefind,"sink"));
|
|
|
|
|
2000-07-12 22:52:42 +00:00
|
|
|
g_print("setting to PREROLL state\n");
|
|
|
|
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PREROLL);
|
2000-06-25 21:38:00 +00:00
|
|
|
g_print("setting to RUNNING state\n");
|
|
|
|
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_RUNNING);
|
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
state = GSTPLAY_STOPPED;
|
2000-06-25 21:38:00 +00:00
|
|
|
|
2000-07-05 10:21:08 +00:00
|
|
|
change_state(GSTPLAY_PLAYING);
|
2000-06-25 21:38:00 +00:00
|
|
|
|
2000-07-12 22:52:42 +00:00
|
|
|
gdk_threads_enter();
|
2000-07-05 10:21:08 +00:00
|
|
|
gtk_main();
|
2000-07-12 22:52:42 +00:00
|
|
|
gdk_threads_leave();
|
2000-06-25 21:38:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|