#include <glib/gstdio.h>
#include <glib-object.h>
#include <gtk/gtk.h>
+
+#if !defined(_WIN32)
#include <gdk/gdkx.h>
+#endif
+
+#if defined(_ENABLE_GST)
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
#include <gst/video/video.h>
#include <gst/pbutils/missing-plugins.h>
+#endif
+
#include "settings.h"
#include "presets.h"
#include "callbacks.h"
struct preview_s
{
+#if defined(_ENABLE_GST)
GstElement *play;
+ gulong xid;
+#endif
gint64 len;
gint64 pos;
gboolean seek_lock;
gint width;
gint height;
GtkWidget *view;
- gulong xid;
GdkPixbuf *pix;
gint button_width;
gint button_height;
gchar *current;
};
-static gboolean live_preview_cb(GstBus *bus, GstMessage *msg, gpointer data);
+#if defined(_ENABLE_GST)
+G_MODULE_EXPORT gboolean live_preview_cb(GstBus *bus, GstMessage *msg, gpointer data);
static GstBusSyncReply create_window(GstBus *bus, GstMessage *msg,
gpointer data);
-gboolean preview_expose_cb(GtkWidget *widget, GdkEventExpose *event,
+#endif
+
+G_MODULE_EXPORT gboolean preview_expose_cb(GtkWidget *widget, GdkEventExpose *event,
signal_user_data_t *ud);
void
ghb_screen_par(signal_user_data_t *ud, gint *par_n, gint *par_d)
{
+#if defined(_ENABLE_GST)
GValue disp_par = {0,};
GstElement *xover;
GObjectClass *klass;
g_value_init(&disp_par, GST_TYPE_FRACTION);
gst_value_set_fraction(&disp_par, 1, 1);
g_object_get(ud->preview->play, "video-sink", &xover, NULL);
+ if (xover == NULL)
+ goto fail;
+
klass = G_OBJECT_GET_CLASS(xover);
+ if (klass == NULL)
+ goto fail;
+
pspec = g_object_class_find_property(klass, "pixel-aspect_ratio");
if (pspec)
{
*par_n = gst_value_get_fraction_numerator(&disp_par);
*par_d = gst_value_get_fraction_denominator(&disp_par);
g_value_unset(&disp_par);
+ return;
+
+fail:
+ *par_n = 1;
+ *par_d = 1;
+#else
+ *par_n = 1;
+ *par_d = 1;
+#endif
}
void
num = par_n * disp_par_d;
den = par_d * disp_par_n;
- if (num > den)
+ if (par_n > par_d)
*width = *width * num / den;
else
*height = *height * den / num;
void
ghb_preview_init(signal_user_data_t *ud)
{
- GstBus *bus;
- GstElement *xover;
-
ud->preview = g_malloc0(sizeof(preview_t));
ud->preview->view = GHB_WIDGET(ud->builder, "preview_image");
gtk_widget_realize(ud->preview->view);
g_signal_connect(G_OBJECT(ud->preview->view), "expose_event",
G_CALLBACK(preview_expose_cb), ud);
- ud->preview->xid = GDK_DRAWABLE_XID(ud->preview->view->window);
- ud->preview->play = gst_element_factory_make("playbin", "play");
ud->preview->pause = TRUE;
ud->preview->encode_frame = -1;
ud->preview->live_id = -1;
+
+#if defined(_ENABLE_GST)
+ GstBus *bus;
+ GstElement *xover;
+
+ ud->preview->xid = GDK_DRAWABLE_XID(ud->preview->view->window);
+ ud->preview->play = gst_element_factory_make("playbin", "play");
//xover = gst_element_factory_make("xvimagesink", "xover");
//xover = gst_element_factory_make("ximagesink", "xover");
xover = gst_element_factory_make("gconfvideosink", "xover");
+ if (xover == NULL)
+ {
+ GtkWidget *widget = GHB_WIDGET(ud->builder, "live_preview_box");
+ gtk_widget_hide (widget);
+ widget = GHB_WIDGET(ud->builder, "live_preview_duration_box");
+ gtk_widget_hide (widget);
+ return;
+ }
+
g_object_set(G_OBJECT(ud->preview->play), "video-sink", xover, NULL);
+ g_object_set(ud->preview->play, "subtitle-font-desc",
+ "sans bold 20", NULL);
//g_object_set(G_OBJECT(xover), "force-aspect-ratio", TRUE, NULL);
bus = gst_pipeline_get_bus(GST_PIPELINE(ud->preview->play));
gst_bus_add_watch(bus, live_preview_cb, ud);
gst_bus_set_sync_handler(bus, create_window, ud->preview);
gst_object_unref(bus);
+#else
+ GtkWidget *widget = GHB_WIDGET(ud->builder, "live_preview_box");
+ gtk_widget_hide (widget);
+ widget = GHB_WIDGET(ud->builder, "live_preview_duration_box");
+ gtk_widget_hide (widget);
+#endif
}
void
}
}
+#if defined(_ENABLE_GST)
static GstBusSyncReply
create_window(GstBus *bus, GstMessage *msg, gpointer data)
{
g_list_free(vstreams);
}
-static gboolean
+G_MODULE_EXPORT gboolean
live_preview_cb(GstBus *bus, GstMessage *msg, gpointer data)
{
signal_user_data_t *ud = (signal_user_data_t*)data;
gst_element_set_state(ud->preview->play, GST_STATE_PAUSED);
ud->preview->pause = TRUE;
}
+#endif
void
live_preview_stop(signal_user_data_t *ud)
img = GTK_IMAGE(GHB_WIDGET(ud->builder, "live_preview_play_image"));
gtk_image_set_from_stock(img, "gtk-media-play", GTK_ICON_SIZE_BUTTON);
+#if defined(_ENABLE_GST)
gst_element_set_state(ud->preview->play, GST_STATE_NULL);
+#endif
ud->preview->pause = TRUE;
ud->preview->state = PREVIEW_STATE_IMAGE;
extern void hb_get_tempory_directory(hb_handle_t *h, char path[512]);
-void
+G_MODULE_EXPORT void
live_preview_start_cb(GtkWidget *xwidget, signal_user_data_t *ud)
{
gchar *tmp_dir;
if (ud->preview->encoded[frame] &&
g_file_test(name, G_FILE_TEST_IS_REGULAR))
{
+#if defined(_ENABLE_GST)
if (ud->preview->pause)
live_preview_start(ud);
else
live_preview_pause(ud);
+#endif
}
else
{
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(prog), "Done");
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(prog), 1);
ud->preview->encoded[ud->preview->encode_frame] = TRUE;
+#if defined(_ENABLE_GST)
live_preview_start(ud);
+#endif
widget = GHB_WIDGET(ud->builder, "live_progress_box");
gtk_widget_hide (widget);
widget = GHB_WIDGET(ud->builder, "live_preview_progress");
}
}
-static gboolean
+#if defined(_ENABLE_GST)
+G_MODULE_EXPORT gboolean
unlock_progress_cb(signal_user_data_t *ud)
{
ud->preview->progress_lock = FALSE;
// so that it is not called again
return FALSE;
}
+#endif
void
ghb_live_preview_progress(signal_user_data_t *ud)
{
+#if defined(_ENABLE_GST)
GstFormat fmt = GST_FORMAT_TIME;
gint64 len = -1, pos = -1;
gtk_range_set_value(progress, percent);
}
g_idle_add((GSourceFunc)unlock_progress_cb, ud);
+#endif
}
-static gboolean
+#if defined(_ENABLE_GST)
+G_MODULE_EXPORT gboolean
unlock_seek_cb(signal_user_data_t *ud)
{
ud->preview->seek_lock = FALSE;
// so that it is not called again
return FALSE;
}
+#endif
-void
+G_MODULE_EXPORT void
live_preview_seek_cb(GtkWidget *widget, signal_user_data_t *ud)
{
+#if defined(_ENABLE_GST)
gdouble dval;
gint64 pos;
GST_SEEK_TYPE_SET, pos,
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
g_idle_add((GSourceFunc)unlock_seek_cb, ud);
+#endif
}
void
ud->preview->pix =
ghb_get_preview_image(titleindex, ud->preview->frame,
- ud, TRUE, &width, &height);
+ ud, &width, &height);
if (ud->preview->pix == NULL) return;
preview_width = gdk_pixbuf_get_width(ud->preview->pix);
preview_height = gdk_pixbuf_get_height(ud->preview->pix);
g_free(text);
g_debug("preview %d x %d", preview_width, preview_height);
- target_height = MIN(ud->preview->button_height, 128);
+ target_height = MIN(ud->preview->button_height, 200);
height = target_height;
width = preview_width * height / preview_height;
+ if (width > 400)
+ {
+ width = 400;
+ height = preview_height * width / preview_width;
+ }
if ((height >= 16) && (width >= 16))
{
}
}
-static gboolean
+#if defined(_ENABLE_GST)
+G_MODULE_EXPORT gboolean
delayed_expose_cb(signal_user_data_t *ud)
{
GstElement *vsink;
GstXOverlay *xover;
g_object_get(ud->preview->play, "video-sink", &vsink, NULL);
+ if (vsink == NULL)
+ return FALSE;
+
if (GST_IS_BIN(vsink))
xover = GST_X_OVERLAY(gst_bin_get_by_interface(
GST_BIN(vsink), GST_TYPE_X_OVERLAY));
// so that it is not called again
return FALSE;
}
+#endif
-gboolean
+G_MODULE_EXPORT gboolean
preview_expose_cb(
GtkWidget *widget,
GdkEventExpose *event,
signal_user_data_t *ud)
{
+#if defined(_ENABLE_GST)
if (ud->preview->state == PREVIEW_STATE_LIVE)
{
if (GST_STATE(ud->preview->play) >= GST_STATE_PAUSED)
}
return TRUE;
}
+#endif
if (ud->preview->pix != NULL)
{
return TRUE;
}
-void
+G_MODULE_EXPORT void
preview_button_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, signal_user_data_t *ud)
{
g_debug("allocate %d x %d", allocation->width, allocation->height);
}
}
-void
+G_MODULE_EXPORT void
preview_frame_value_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
if (ud->preview->live_id >= 0)
ghb_set_preview_image(ud);
}
-gboolean
+G_MODULE_EXPORT gboolean
preview_window_delete_cb(
GtkWidget *widget,
GdkEvent *event,
return TRUE;
}
-gboolean
+G_MODULE_EXPORT gboolean
settings_window_delete_cb(
GtkWidget *widget,
GdkEvent *event,
return TRUE;
}
-void
+G_MODULE_EXPORT void
preview_duration_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
g_debug("preview_duration_changed_cb ()");
return FALSE;
}
+GdkDrawable*
+ghb_curved_rect_mask(gint width, gint height, gint radius)
+{
+ GdkDrawable *shape;
+ cairo_t *cr;
+ double w, h;
+
+ if (!width || !height)
+ return NULL;
+
+ shape = (GdkDrawable *)gdk_pixmap_new (NULL, width, height, 1);
+
+ cr = gdk_cairo_create (shape);
+
+ w = width;
+ h = height;
+ if (radius > width / 2)
+ radius = width / 2;
+ if (radius > height / 2)
+ radius = height / 2;
+
+ // fill shape with black
+ cairo_save(cr);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_fill (cr);
+ cairo_restore (cr);
+
+ cairo_move_to (cr, 0, radius);
+ cairo_curve_to (cr, 0 , 0, 0 , 0, radius, 0);
+ cairo_line_to (cr, w - radius, 0);
+ cairo_curve_to (cr, w, 0, w, 0, w, radius);
+ cairo_line_to (cr, w , h - radius);
+ cairo_curve_to (cr, w, h, w, h, w - radius, h);
+ cairo_line_to (cr, 0 + radius, h);
+ cairo_curve_to (cr, 0, h, 0, h, 0, h - radius);
+
+ cairo_close_path(cr);
+
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+
+ cairo_destroy(cr);
+
+ return shape;
+}
+
+G_MODULE_EXPORT void
+preview_hud_size_alloc_cb(
+ GtkWidget *widget,
+ GtkAllocation *allocation,
+ signal_user_data_t *ud)
+{
+ GdkDrawable *shape;
+
+ //g_message("preview_hud_size_alloc_cb()");
+ if (GTK_WIDGET_VISIBLE(widget) && allocation->height > 50)
+ {
+ shape = ghb_curved_rect_mask(allocation->width,
+ allocation->height, allocation->height/4);
+ if (shape != NULL)
+ {
+ gtk_widget_shape_combine_mask(widget, shape, 0, 0);
+ gdk_pixmap_unref(shape);
+ }
+ }
+}
+
G_MODULE_EXPORT gboolean
preview_configure_cb(
GtkWidget *widget,
{
gint x, y;
- g_debug("preview_configure_cb()");
+ //g_message("preview_configure_cb()");
if (GTK_WIDGET_VISIBLE(widget))
{
gtk_window_get_position(GTK_WINDOW(widget), &x, &y);
{
gint x, y;
- g_debug("settings_configure_cb()");
+ //g_message("settings_configure_cb()");
if (GTK_WIDGET_VISIBLE(widget))
{
gtk_window_get_position(GTK_WINDOW(widget), &x, &y);
return FALSE;
}
-#if 0
-G_MODULE_EXPORT gboolean
-preview_window_expose_cb(
- GtkWidget *widget,
- GdkEventExpose *event,
- signal_user_data_t *ud)
-{
- GdkRegion *region;
- GtkWidget *child;
- cairo_t *cr;
-
- //g_debug("preview_window_expose_cb()");
- /* get our child (in this case, the draw area) */
- child = GHB_WIDGET(ud->builder, "preview_image");
- /* create a cairo context to draw to the window */
- cr = gdk_cairo_create (widget->window);
- /* the source data is the (composited) event box */
- gdk_cairo_set_source_pixmap (cr, child->window,
- child->allocation.x,
- child->allocation.y);
- /* draw no more than our expose event intersects our child */
- region = gdk_region_rectangle (&child->allocation);
- gdk_region_intersect (region, event->region);
- gdk_cairo_region (cr, region);
- cairo_clip (cr);
- /* composite, with a 100% opacity */
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- cairo_paint_with_alpha (cr, 1);
-
- cairo_reset_clip(cr);
- /* get our child (in this case, the event box) */
- child = GHB_WIDGET(ud->builder, "preview_event_box");
- /* create a cairo context to draw to the window */
- cr = gdk_cairo_create (widget->window);
- /* the source data is the (composited) event box */
- gdk_cairo_set_source_pixmap (cr, child->window,
- child->allocation.x,
- child->allocation.y);
- /* draw no more than our expose event intersects our child */
- region = gdk_region_rectangle (&child->allocation);
- gdk_region_intersect (region, event->region);
- gdk_cairo_region (cr, region);
- cairo_clip (cr);
- /* composite, with a 85% opacity */
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- cairo_paint_with_alpha (cr, .85);
-
- /* we're done */
- cairo_destroy (cr);
- return FALSE;
-}
-
-#endif