/*
* gnome_ui.c
*
* Copyright (C) 2003-06 Karl H. Beckers, Frankfurt
* EMail: khb@jarre-de-the.net
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/time.h> // for timeval struct and related
#include <stdlib.h>
#include <unistd.h>
#ifdef SOLARIS
#include <X11/X.h>
#include <X11/Xlib.h>
#endif // SOLARIS
#include <X11/cursorfont.h>
#include <X11/Xmu/WinUtil.h>
#ifdef HAVE_SHMAT
#include <X11/extensions/XShm.h>
#endif // HAVE_SHMAT
#include <gdk/gdkx.h>
#include <glib.h>
/*
* include <bonobo.h> include <gnome.h> */
#include <glade/glade.h>
#include <pthread.h>
#include <signal.h>
#include "led_meter.h"
#include "job.h"
#include "app_data.h"
#include "control.h"
#include "colors.h"
#include "codecs.h"
#include "frame.h"
#include "gnome_warning.h"
#include "gnome_options.h"
#include "gnome_ui.h"
#include "gnome_frame.h"
#include "xvidcap-intl.h"
#define GLADE_FILE PACKAGE_DATA_DIR"/xvidcap/glade/gnome-xvidcap.glade"
#define DEBUGFILE "gnome_ui.c"
/*
* globals
* need to define this here, because we're calling it from
* an event and/or the preferences (gtk2_options.c)
*/
GtkWidget *xvc_ctrl_main_window = NULL;
GtkWidget *xvc_ctrl_m1 = NULL;
GtkWidget *xvc_result_dialog = NULL;
extern AppData *app;
extern GtkWidget *xvc_pref_main_window;
extern GtkWidget *xvc_warn_main_window;
extern xvCodec tCodecs[NUMCODECS];
extern xvFFormat tFFormats[NUMCAPS];
extern xvAuCodec tAuCodecs[NUMAUCODECS];
static guint stop_timer_id = 0;
static long start_time = 0, pause_time = 0, time_captured = 0;
static char *target_file_name = NULL;
static xvErrorListItem *errors_after_cli = NULL;
static int OK_attempts = 0;
// those are for recording video in thread
pthread_mutex_t recording_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t update_filename_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t recording_condition_unpaused;
static pthread_t recording_thread;
static pthread_attr_t recording_thread_attr;
static Boolean recording_thread_running = FALSE;
// functions
static gboolean stop_recording_gui_stuff(Job * jobp);
static gboolean stop_recording_nongui_stuff(Job * jobp);
static gboolean start_recording_gui_stuff(Job * jobp);
static gboolean start_recording_nongui_stuff(Job * jobp);
static gboolean timer_stop_recording(Job * job);
void warning_submit();
void xvc_reset_ctrl_main_window_according_to_current_prefs();
void GtkChangeLabel(int pic_no);
/*
* XVIDCAP GUI API ( IF THAT WORD IS ALLOWED HERE ;) )
*
* XVC_PREINIT IS FOR GUI PREINITIALIZATION LIKE SETTING FALLBACK OPTIONS
* XVC_CREATEGUI IS FOR GUI CREATION
* XVC_CREATEFRAME SHOULD CREATE THE SELECTION FRAME
* XVC_INITGUI IS FOR MISCELLANEOUS INITIALIZATION STUFF
* XVC_RUNGUI IS A WRAPPER AROUND THE UI'S MAIN LOOP
*
* XVC_ADDTIMEOUT IS A WRAPPER AROUND THE GUI'S FUNCTIONALITY FOR TRIGGERING ACTIONS AT A
* GIVEN TIME
* XVC_CHANGEGUILABEL IS A WRAPPER AROUND A FUNCTION TO CHANGE THE DISPLAY
* OF THE CURRENT FRAME NUMBER (NOT NECESSARY IN A LABEL)
* XVC_STOPCAPTURE IS A HOOK FOR RESETTING THE GUI TO A STOPPED STATE
* XVC_STARTCAPTURE IS A HOOK FOR STARTING A CAPTURE SESSION
*/
Boolean xvc_init_pre(int argc, char **argv)
{
#define DEBUGFUNCTION "xvc_init_pre()"
g_thread_init(NULL);
// gnome program initialization
// make gnome init ignore command line options (we want to handle them
// ourselves
// char *nothing[] = { "--disable-crash-dialog", "--help" };
// gnome_program_init(PACKAGE, VERSION, LIBGNOMEUI_MODULE,
// 2, nothing,
// GNOME_PARAM_APP_DATADIR, PACKAGE_DATA_DIR, NULL);
gtk_init(&argc, &argv);
return TRUE;
#undef DEBUGFUNCTION
}
GtkWidget *glade_create_led_meter(gchar * widget_name, gchar * string1,
gchar * string2, gint int1, gint int2)
{
#define DEBUGFUNCTION "glade_create_led_meter()"
GtkWidget *frame_monitor = led_meter_new();
g_assert(frame_monitor);
gtk_widget_set_name(GTK_WIDGET(frame_monitor), widget_name);
gtk_widget_show(GTK_WIDGET(frame_monitor));
return frame_monitor;
#undef DEBUGFUNCTION
}
Boolean xvc_ui_create()
{
#define DEBUGFUNCTION "xvc_ui_create()"
Display *dpy;
GladeXML *xml;
#ifdef DEBUG
printf("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
// only show the ui if not in nogui
if ((app->flags & FLG_NOGUI) == 0) {
// main window
// load the interface
xml = glade_xml_new(GLADE_FILE, "xvc_ctrl_main_window", NULL);
g_assert(xml);
// connect the signals in the interface
glade_xml_signal_autoconnect(xml);
// store the toplevel widget for further reference
xvc_ctrl_main_window =
glade_xml_get_widget(xml, "xvc_ctrl_main_window");
xml = NULL;
// popup window
// load the interface
xml = glade_xml_new(GLADE_FILE, "xvc_ctrl_m1", NULL);
g_assert(xml);
// connect the signals in the interface
glade_xml_signal_autoconnect(xml);
xvc_ctrl_m1 = glade_xml_get_widget(xml, "xvc_ctrl_m1");
dpy =
GDK_DRAWABLE_XDISPLAY(GTK_WIDGET(xvc_ctrl_main_window)->
window);
} else {
dpy = XOpenDisplay(NULL);
}
// FIXME: This needs to go somewhere else more sensible
#ifdef HasDGA
if (!XF86DGAQueryExtension(dpy, &dga_evb, &dga_errb))
app->flags &= ~FLG_USE_DGA;
else {
int flag = 0;
XF86DGAQueryDirectVideo(dpy, XDefaultScreen(dpy), &flag);
if ((flag & XF86DGADirectPresent) == 0) {
app->flags &= ~FLG_USE_DGA;
if (app->verbose) {
printf("%s %s: no xfdga direct present\n", DEBUGFILE,
DEBUGFUNCTION);
}
}
}
#endif // HasDGA
// FIXME: This needs to go somewhere else more sensible
#ifdef HAVE_SHMAT
if (!XShmQueryExtension(dpy))
app->flags &= ~FLG_USE_SHM;
#endif // HAVE_SHMAT
if (app->flags & FLG_NOGUI) {
XCloseDisplay(dpy);
}
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
return TRUE;
#undef DEBUGFUNCTION
}
Boolean xvc_frame_create()
{
#define DEBUGFUNCTION "xvc_frame_create()"
g_assert(app);
if ((app->flags & FLG_NOGUI) == 0) { // there's one reason for not
// having a main window
g_assert(xvc_ctrl_main_window);
}
if (app->cap_width == 0)
app->cap_width = 10;
if (app->cap_height == 0)
app->cap_height = 10;
xvc_create_gtk_frame(xvc_ctrl_main_window, app->cap_width,
app->cap_height, app->cap_pos_x, app->cap_pos_y);
return TRUE;
#undef DEBUGFUNCTION
}
void xvc_frame_destroy()
{
xvc_destroy_gtk_frame();
}
void xvc_check_start_options()
{
#define DEBUGFUNCTION "xvc_check_start_options()"
int count_non_info_messages = 0;
int rc = 0;
#ifdef DEBUG
printf("%s %s: Entering with errors_after_cli = %p\n", DEBUGFILE,
DEBUGFUNCTION, errors_after_cli);
#endif // DEBUG
if (OK_attempts > 0 && errors_after_cli != NULL) {
errors_after_cli = xvc_app_data_validate(app, 1, &rc);
#ifdef DEBUG
printf("%s %s: new errors_after_cli = %p\n", DEBUGFILE,
DEBUGFUNCTION, errors_after_cli);
#endif // DEBUG
if (rc == -1) {
fprintf(stderr,
"%s %s: Unrecoverable error while validating options, please contact the xvidcap project.\n",
DEBUGFILE, DEBUGFUNCTION);
exit(1);
}
}
if ((app->flags & FLG_NOGUI) == 0) { // we're running with gui
if (errors_after_cli != NULL) {
xvErrorListItem *err;
err = errors_after_cli;
count_non_info_messages = 0;
for (; err != NULL; err = err->next) {
if (err->err->type != XV_ERR_INFO)
count_non_info_messages++;
}
if (count_non_info_messages > 0
|| (app->flags & FLG_RUN_VERBOSE && OK_attempts == 0)) {
xvc_warn_main_window =
xvc_create_warning_with_errors(errors_after_cli, 2);
OK_attempts++;
} else {
warning_submit();
}
} else {
warning_submit();
}
} else { // or without
while (errors_after_cli != NULL && OK_attempts < 6) {
xvErrorListItem *err;
err = errors_after_cli;
count_non_info_messages = rc = 0;
for (; err != NULL; err = err->next) {
if (err->err->type != XV_ERR_INFO)
count_non_info_messages++;
}
if (count_non_info_messages > 0
|| (app->flags & FLG_RUN_VERBOSE && OK_attempts == 0)) {
err = errors_after_cli;
for (; err != NULL; err = err->next) {
if (err->err->type != XV_ERR_INFO ||
app->flags & FLG_RUN_VERBOSE) {
xvc_errors_write_error_msg(err->err->code,
((app->
flags &
FLG_RUN_VERBOSE) ? 1 :
0));
(*err->err->action) (err);
}
}
}
OK_attempts++;
errors_after_cli = xvc_app_data_validate(app, 1, &rc);
if (rc == -1) {
fprintf(stderr,
"%s %s: Unrecoverable error while validating options, please contact the xvidcap project.\n",
DEBUGFILE, DEBUGFUNCTION);
exit(1);
}
}
if (errors_after_cli != NULL && count_non_info_messages > 0) {
fprintf(stderr,
"%s %s: You have specified some conflicting settings which could not be resolved automatically.\n",
DEBUGFILE, DEBUGFUNCTION);
exit(1);
}
warning_submit();
}
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
#undef DEBUGFUNCTION
}
Boolean xvc_ui_init(xvErrorListItem * errors)
{
#define DEBUGFUNCTION "xvc_ui_init()"
#ifdef DEBUG
printf("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
// display warning dialog if required
errors_after_cli = errors;
// the gui warning dialog needs a realized window, therefore we
// schedule it
// do be displayed (potentially) when the main loop starts
// this does not seem to work with nogui
if (!(app->flags & FLG_NOGUI)) {
gtk_init_add((GtkFunction) xvc_check_start_options, NULL);
} else {
xvc_check_start_options();
gtk_init_add((GtkFunction) xvc_capture_start, NULL);
}
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
return TRUE;
#undef DEBUGFUNCTION
}
int xvc_ui_run()
{
#define DEBUGFUNCTION "xvc_ui_run()";
gtk_main();
return 0;
#undef DEBUGFUNCTION
}
void xvc_idle_add(void *func, void *data, Boolean queue_events)
{
if (queue_events || !gtk_events_pending())
g_idle_add(func, data);
}
Boolean xvc_change_filename_display(int pic_no)
{
#define DEBUGFUNCTION "xvc_change_filename_display()"
GtkChangeLabel(pic_no);
return FALSE;
#undef DEBUGFUNCTION
}
void xvc_capture_stop_signal(Boolean wait)
{
#define DEBUGFUNCTION "xvc_capture_stop_signal()"
int status = -1;
#ifdef DEBUG
printf("%s %s: Entering, should we wait? %i\n",
DEBUGFILE, DEBUGFUNCTION, wait);
#endif // DEBUG
job_set_state(VC_STOP);
if (recording_thread_running) {
#ifdef DEBUG
printf("%s %s: stop pressed while recording\n",
DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
// stop waiting for next frame to capture
status = pthread_kill(recording_thread, SIGALRM);
#ifdef DEBUG
printf("%s %s: thread %i kill with rc %i\n",
DEBUGFILE, DEBUGFUNCTION, (int) recording_thread, status);
#endif // DEBUG
}
if (wait) {
while (recording_thread_running) {
usleep(100);
}
}
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
#undef DEBUGFUNCTION
}
Boolean xvc_capture_stop()
{
#define DEBUGFUNCTION "xvc_capture_stop()"
Job *job = xvc_job_ptr();
gboolean rc;
#ifdef DEBUG
printf("%s %s: stopping\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
rc = stop_recording_nongui_stuff(job);
#ifdef DEBUG
printf("%s %s: done stopping non-gui stuff\n", DEBUGFILE,
DEBUGFUNCTION);
#endif // DEBUG
if (!(job->flags & FLG_NOGUI))
rc = stop_recording_gui_stuff(job);
return FALSE;
#undef DEBUGFUNCTION
}
void xvc_capture_start()
{
#define DEBUGFUNCTION "xvc_capture_start()"
Job *job = xvc_job_ptr();
gboolean rc;
rc = start_recording_nongui_stuff(job);
if (!(job->flags & FLG_NOGUI))
rc = start_recording_gui_stuff(job);
#undef DEBUGFUNCTION
}
void
xvc_frame_change(int x, int y, int width, int height,
Boolean reposition_control)
{
#define DEBUGFUNCTION "xvc_frame_change()"
xvc_change_gtk_frame(x, y, width, height, reposition_control);
#undef DEBUGFUNCTION
}
Boolean xvc_frame_monitor(int measured_time)
{
#define DEBUGFUNCTION "xvc_frame_monitor()"
Job *job = xvc_job_ptr();
int percent = 0, diff = 0;
GladeXML *xml = NULL;
GtkWidget *w = NULL;
#ifdef DEBUG
printf("%s %s: Entering with time = %i\n", DEBUGFILE, DEBUGFUNCTION,
measured_time);
#endif // DEBUG
xml = glade_get_widget_tree(xvc_ctrl_main_window);
g_return_val_if_fail(xml != NULL, FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_led_meter");
g_return_val_if_fail(w != NULL, FALSE);
if (measured_time == 0) {
percent = 0;
} else if (measured_time <= job->time_per_frame)
percent = 30;
else if (measured_time >= (job->time_per_frame * 2))
percent = 100;
else {
diff = measured_time - job->time_per_frame;
percent = diff * 70 / job->time_per_frame;
percent += 30;
}
led_meter_set_percent(LED_METER(w), percent);
if (percent == 0)
LED_METER(w)->old_max_da = 0;
#ifdef DEBUG
printf("%s %s: Leaving with percent = %i\n", DEBUGFILE, DEBUGFUNCTION,
percent);
#endif // DEBUG
return FALSE;
#undef DEBUGFUNCTION
}
/*
* HELPER FUNCTIONS ...
*
*
*/
/*
* this isn't used atm
*
gint keySnooper (GtkWidget *grab_widget, GdkEventKey *event, gpointer func_data) {
printf("keyval: %i - mods: %i\n", event->keyval, event->state);
} */
/*
* change value of frame/filename display
*/
void GtkChangeLabel(int pic_no)
{
#define DEBUGFUNCTION "GtkChangeLabel()"
static char file[PATH_MAX + 1], tmp_buf[PATH_MAX + 1];
PangoLayout *layout = NULL;
gint width = 0, height = 0;
int filename_length = 0;
GladeXML *xml = NULL;
GtkWidget *w = NULL;
Job *jobp = xvc_job_ptr();
// generate the string to display in the filename button
if (jobp->flags & FLG_MULTI_IMAGE) {
sprintf(tmp_buf, jobp->file, jobp->movie_no);
sprintf(file, "%s[%04d]", tmp_buf, pic_no);
} else {
sprintf(file, jobp->file, pic_no);
}
// cut the string to a sensible maximum length
filename_length = strlen(file);
if (filename_length > 60) {
char tmp_file[PATH_MAX + 1];
char *tmp_file2, *ptr;
int n;
strncpy(tmp_file, file, 20);
tmp_file[20] = 0;
n = filename_length - 20;
ptr = (char *) &file + n;
tmp_file2 = strncat(tmp_file, "...", 4);
tmp_file2 = strncat(tmp_file, ptr, 45);
strncpy(file, tmp_file2, 45);
}
// get the filename button widget
xml = glade_get_widget_tree(xvc_ctrl_main_window);
g_assert(xml);
w = glade_xml_get_widget(xml, "xvc_ctrl_filename_button");
g_assert(w);
// set the text
gtk_button_set_label(GTK_BUTTON(w), file);
// adjust the size of the filname button
layout = gtk_widget_create_pango_layout(w, file);
g_assert(layout);
pango_layout_get_pixel_size(layout, &width, &height);
g_object_unref(layout);
gtk_widget_set_size_request(GTK_WIDGET(w), (width + 30), -1);
#undef DEBUGFUNCTION
}
// first callbacks here ....
//
//
gboolean
on_xvc_ctrl_main_window_delete_event(GtkWidget * widget,
GdkEvent * event, gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_main_window_delete_event()"
Job *jobp = xvc_job_ptr();
if (jobp && (jobp->state & VC_STOP) == 0) {
xvc_capture_stop_signal(TRUE);
}
xvc_frame_destroy();
gtk_main_quit(); // FIXME: why does this seem to be
// necessary with libglade where
// it was not previously
return FALSE;
#undef DEBUGFUNCTION
}
gboolean
on_xvc_ctrl_main_window_destroy_event(GtkWidget * widget,
GdkEvent * event, gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_main_window_destroy_event()"
gtk_main_quit();
return FALSE;
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_m1_mitem_preferences_activate(GtkMenuItem * menuitem,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_m1_mitem_preferences_activate()"
#ifdef DEBUG
printf("%s %s: Entering with app %p\n", DEBUGFILE, DEBUGFUNCTION, app);
#endif // DEBUG
xvc_create_pref_dialog(app);
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_m1_mitem_save_preferences_activate(GtkMenuItem *
menuitem,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_m1_mitem_save_preferences_activate()"
Job *jobp = xvc_job_ptr();
xvc_write_options_file(jobp);
#undef DEBUGFUNCTION
}
void warning_submit()
{
#define DEBUGFUNCTION "warning_submit()"
Display *mydisplay = NULL;
Window root;
XWindowAttributes win_attr;
Job *jobp = xvc_job_ptr();
#ifdef DEBUG
printf("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
// Get X display and Window Attributes
// notice, here we're still talking app->flags
if (!(app->flags & FLG_NOGUI)) {
mydisplay =
GDK_DRAWABLE_XDISPLAY(GTK_WIDGET(xvc_ctrl_main_window)->
window);
} else {
mydisplay = XOpenDisplay(NULL);
}
g_assert(mydisplay);
root = RootWindow(mydisplay, DefaultScreen(mydisplay));
if (!XGetWindowAttributes(mydisplay, root, &win_attr)) {
char msg[256];
snprintf(msg, 256, "%s %s: Can't get window attributes!\n",
DEBUGFILE, DEBUGFUNCTION);
perror(msg);
}
if (jobp == NULL)
jobp = xvc_job_new();
xvc_job_set_from_app_data(app, mydisplay, win_attr);
// validate the job parameters
xvc_job_validate();
// set controls active/inactive/sensitive/insensitive according to
// current options
if (!(app->flags & FLG_NOGUI)) {
xvc_reset_ctrl_main_window_according_to_current_prefs();
// FIXME: any bad side-effects from removing this?
// stop_recording_gui_stuff(jobp);
}
if (xvc_errors_delete_list(errors_after_cli)) {
fprintf(stderr,
"%s %s: Unrecoverable error while freeing error list, please contact the xvidcap project.\n",
DEBUGFILE, DEBUGFUNCTION);
exit(1);
}
// reset attempts so warnings will be shown again next time ...
OK_attempts = 0;
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
#undef DEBUGFUNCTION
}
#ifdef USE_FFMPEG
void xvc_toggle_cap_type()
{
#define DEBUGFUNCTION "xvc_toggle_cap_type()"
int count_non_info_messages, rc;
count_non_info_messages = 0;
rc = 0;
errors_after_cli = xvc_app_data_validate(app, 1, &rc);
if (rc == -1) {
fprintf(stderr,
"%s %s: Unrecoverable error while validating options, please contact the xvidcap project.\n",
DEBUGFILE, DEBUGFUNCTION);
exit(1);
}
// warning dialog
if (errors_after_cli != NULL) {
xvErrorListItem *err;
err = errors_after_cli;
for (; err != NULL; err = err->next) {
if (err->err->type != XV_ERR_INFO)
count_non_info_messages++;
}
if (count_non_info_messages > 0
|| (app->flags & FLG_RUN_VERBOSE && OK_attempts == 0)) {
xvc_warn_main_window =
xvc_create_warning_with_errors(errors_after_cli, 1);
OK_attempts++;
} else {
warning_submit();
}
} else {
warning_submit();
}
#undef DEBUGFUNCTION
}
void xvc_undo_toggle_cap_type()
{
#define DEBUGFUNCTION "xvc_undo_toggle_cap_type()"
GladeXML *xml = NULL;
GtkWidget *mitem = NULL;
xml = glade_get_widget_tree(xvc_ctrl_m1);
g_assert(xml);
OK_attempts = 0;
#ifdef DEBUG
printf("%s %s: pre current_mode %i\n", DEBUGFILE, DEBUGFUNCTION,
app->current_mode);
#endif // DEBUG
app->current_mode = (app->current_mode == 0) ? 1 : 0;
#ifdef DEBUG
printf("%s %s: post current_mode %i\n", DEBUGFILE, DEBUGFUNCTION,
app->current_mode);
#endif // DEBUG
if (app->current_mode == 0) {
mitem = glade_xml_get_widget(xml, "xvc_ctrl_m1_mitem_sf_capture");
g_assert(mitem);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem), TRUE);
} else {
mitem = glade_xml_get_widget(xml, "xvc_ctrl_m1_mitem_mf_capture");
g_assert(mitem);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem), TRUE);
}
#undef DEBUGFUNCTION
}
#endif // USE_FFMPEG
void
on_xvc_ctrl_m1_mitem_sf_capture_activate(GtkMenuItem * menuitem,
gpointer user_data)
{
#ifdef USE_FFMPEG
#define DEBUGFUNCTION "on_xvc_ctrl_m1_mitem_sf_capture_activate()"
if (app->current_mode == 1
&& gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)) !=
0) {
app->current_mode = (app->current_mode == 0) ? 1 : 0;
xvc_toggle_cap_type();
}
#undef DEBUGFUNCTION
#endif // USE_FFMPEG
}
void
on_xvc_ctrl_m1_mitem_mf_capture_activate(GtkMenuItem * menuitem,
gpointer user_data)
{
#ifdef USE_FFMPEG
#define DEBUGFUNCTION "on_xvc_ctrl_m1_mitem_mf_capture_activate()"
if (app->current_mode == 0
&& gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)) !=
0) {
app->current_mode = (app->current_mode == 0) ? 1 : 0;
xvc_toggle_cap_type();
}
#undef DEBUGFUNCTION
#endif // USE_FFMPEG
}
void
on_xvc_ctrl_m1_mitem_autocontinue_activate(GtkMenuItem * menuitem,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_m1_mitem_autocontinue_activate()"
Job *jobp = xvc_job_ptr();
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) {
if ((!xvc_is_filename_mutable(jobp->file))
|| (jobp->flags & FLG_MULTI_IMAGE) == 0) {
printf
("Output not a video file or no counter in filename\nDisabling autocontinue!\n");
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
(menuitem), FALSE);
} else {
jobp->flags |= FLG_AUTO_CONTINUE;
app->flags |= FLG_AUTO_CONTINUE;
}
} else {
jobp->flags &= ~FLG_AUTO_CONTINUE;
app->flags &= ~FLG_AUTO_CONTINUE;
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_m1_mitem_make_activate(GtkMenuItem * menuitem,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_m1_mitem_make_activate()"
Job *jobp = xvc_job_ptr();
if (!app->current_mode) {
xvc_command_execute(app->single_frame.video_cmd, 0, 0,
jobp->file, jobp->start_no, jobp->pic_no,
jobp->area->width,
jobp->area->height, jobp->fps);
} else {
xvc_command_execute(app->multi_frame.video_cmd, 2,
jobp->movie_no, jobp->file, jobp->start_no,
jobp->pic_no, jobp->area->width,
jobp->area->height, jobp->fps);
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_m1_mitem_help_activate(GtkMenuItem * menuitem,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_m1_mitem_help_activate()"
system("yelp ghelp:xvidcap &");
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_m1_mitem_quit_activate(GtkMenuItem * menuitem,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_m1_mitem_quit_activate()"
gboolean ignore = TRUE;
g_signal_emit_by_name((GtkObject *) xvc_ctrl_main_window,
"destroy_event", 0, &ignore);
#undef DEBUGFUNCTION
}
void do_record_thread(Job * job)
{
#define DEBUGFUNCTION "do_record_thread()"
long pause = 1000;
#ifdef DEBUG
printf("%s %s: Entering with state = %i and tid = %i\n", DEBUGFILE,
DEBUGFUNCTION, job->state, recording_thread);
#endif // DEBUG
recording_thread_running = TRUE;
while ((job->state & VC_READY) == 0) {
#ifdef DEBUG
printf("%s %s: going for next frame with state %i\n", DEBUGFILE,
DEBUGFUNCTION, job->state);
#endif
if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
pthread_mutex_lock(&recording_mutex);
pthread_cond_wait(&recording_condition_unpaused,
&recording_mutex);
pthread_mutex_unlock(&recording_mutex);
#ifdef DEBUG
printf("%s %s: unpaused\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
}
pause = job->capture(job, NULL);
if (pause > 0)
usleep(pause * 1000);
#ifdef DEBUG
printf("%s %s: woke up\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
}
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
recording_thread_running = FALSE;
pthread_exit(NULL);
#undef DEBUGFUNCTION
}
gboolean stop_recording_nongui_stuff(Job * job)
{
#define DEBUGFUNCTION "stop_recording_nongui_stuff()"
int state = 0;
struct timeval curr_time;
long stop_time = 0;
#ifdef DEBUG
printf("%s %s: Entering with thread running %i\n",
DEBUGFILE, DEBUGFUNCTION, recording_thread_running);
#endif // DEBUG
state = VC_STOP;
if (job->flags & FLG_AUTO_CONTINUE) {
state |= VC_CONTINUE;
}
job_set_state(state);
if (recording_thread_running) {
pthread_join(recording_thread, NULL /* (void **) &status */ );
#ifdef DEBUG
printf("%s %s: joined thread\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
}
gettimeofday(&curr_time, NULL);
stop_time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
time_captured += (stop_time - start_time);
if (stop_timer_id)
g_source_remove(stop_timer_id);
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
return FALSE;
#undef DEBUGFUNCTION
}
// this handles the shortcut keybindings
void do_results_help()
{
system((char *) "yelp ghelp:xvidcap?xvidcap-results &");
}
gint
on_xvc_result_dialog_key_press_event(GtkWidget * widget, GdkEvent * event)
{
#define DEBUGFUNCTION "on_xvc_result_dialog_key_press_event()"
GdkEventKey *kevent = NULL;
g_assert(widget);
g_assert(event);
kevent = (GdkEventKey *) event;
#ifdef DEBUG
printf("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
if (kevent->keyval == 65470) {
do_results_help();
}
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
// Tell calling code that we have not handled this event; pass it on.
return FALSE;
#undef DEBUGFUNCTION
}
void
on_xvc_result_dialog_select_filename_button_clicked(GtkButton * button,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_result_select_filename_button_clicked()"
int result = 0;
GladeXML *xml = NULL;
GtkWidget *w = NULL, *dialog = NULL;
#ifdef DEBUG
printf("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
// load the interface
xml = glade_xml_new(GLADE_FILE, "xvc_save_filechooserdialog", NULL);
g_assert(xml);
// connect the signals in the interface
glade_xml_signal_autoconnect(xml);
dialog = glade_xml_get_widget(xml, "xvc_save_filechooserdialog");
g_assert(dialog);
gtk_window_set_title(GTK_WINDOW(dialog), "Save Video As:");
result = gtk_dialog_run(GTK_DIALOG(dialog));
if (result == GTK_RESPONSE_OK) {
target_file_name =
gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
if (xvc_result_dialog != NULL) {
xml = NULL;
xml = glade_get_widget_tree(GTK_WIDGET(xvc_result_dialog));
g_assert(xml);
w = NULL;
w = glade_xml_get_widget(xml,
"xvc_result_dialog_filename_label");
g_assert(w);
gtk_label_set_text(GTK_LABEL(w), target_file_name);
w = NULL;
w = glade_xml_get_widget(xml, "xvc_result_dialog_save_button");
g_assert(w);
printf("setting save button sensitive\n");
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
}
}
gtk_widget_destroy(dialog);
#ifdef DEBUG
printf("%s %s: Leaving with filename %s\n", DEBUGFILE, DEBUGFUNCTION,
target_file_name);
#endif // DEBUG
#undef DEBUGFUNCTION
}
static gboolean stop_recording_gui_stuff(Job * job)
{
#define DEBUGFUNCTION "stop_recording_gui_stuff()"
GladeXML *xml = NULL;
GtkWidget *w = NULL;
CapTypeOptions *target = NULL;
Job *jobp = xvc_job_ptr();
#ifdef DEBUG
printf("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
// playing it safe
xvc_change_filename_display(job->pic_no);
// reset frame_drop_meter
xvc_frame_monitor(0);
xml = glade_get_widget_tree(GTK_WIDGET(xvc_ctrl_main_window));
g_assert(xml);
// GUI stuff
w = glade_xml_get_widget(xml, "xvc_ctrl_pause_toggle");
g_assert(w);
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(w), FALSE);
// gtk_widget_set_sensitive(GTK_WIDGET(MI_file), TRUE);
w = glade_xml_get_widget(xml, "xvc_ctrl_select_toggle");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
w = glade_xml_get_widget(xml, "xvc_ctrl_record_toggle");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(w)))
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(w),
FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_filename_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
w = glade_xml_get_widget(xml, "xvc_ctrl_edit_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
if (!
((jobp->flags & FLG_MULTI_IMAGE) != 0
&& xvc_is_filename_mutable(jobp->file) != TRUE)) {
w = glade_xml_get_widget(xml, "xvc_ctrl_step_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_forward_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
w = glade_xml_get_widget(xml, "xvc_ctrl_back_button");
g_assert(w);
if ((jobp->flags & FLG_MULTI_IMAGE) == 0) {
if (jobp->pic_no >= jobp->step)
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
} else {
if (jobp->movie_no > 0)
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
}
}
w = glade_xml_get_widget(xml, "xvc_ctrl_pause_toggle");
g_assert(w);
if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(w)))
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(w),
FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_stop_toggle");
g_assert(w);
if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(w)))
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(w), TRUE);
GtkChangeLabel(jobp->pic_no);
#ifdef USE_FFMPEG
if (job->target >= CAP_MF)
target = &(app->multi_frame);
else
#endif // USE_FFMPEG
target = &(app->single_frame);
if ((strlen(target->file) < 1 ||
(app->flags & FLG_ALWAYS_SHOW_RESULTS) > 0) &&
(job->flags & FLG_AUTO_CONTINUE) == 0) {
int result = 0;
float fps_ratio = 0;
char buf[100];
GladeXML *xml = NULL;
GtkWidget *w = NULL;
// load the interface
xml = glade_xml_new(GLADE_FILE, "xvc_result_dialog", NULL);
g_assert(xml);
// connect the signals in the interface
glade_xml_signal_autoconnect(xml);
// get the widget
xvc_result_dialog = glade_xml_get_widget(xml, "xvc_result_dialog");
g_assert(xvc_result_dialog);
// width
w = glade_xml_get_widget(xml, "xvc_result_dialog_width_label");
g_assert(w);
snprintf(buf, 99, "%i", job->area->width);
gtk_label_set_text(GTK_LABEL(w), buf);
// height
w = glade_xml_get_widget(xml, "xvc_result_dialog_height_label");
g_assert(w);
snprintf(buf, 99, "%i", job->area->height);
gtk_label_set_text(GTK_LABEL(w), buf);
// video format
w = glade_xml_get_widget(xml,
"xvc_result_dialog_video_format_label");
g_assert(w);
gtk_label_set_text(GTK_LABEL(w),
_(tFFormats[jobp->target].longname));
// video codec
w = glade_xml_get_widget(xml,
"xvc_result_dialog_video_codec_label");
g_assert(w);
gtk_label_set_text(GTK_LABEL(w), tCodecs[jobp->targetCodec].name);
// audio codec
w = glade_xml_get_widget(xml,
"xvc_result_dialog_audio_codec_label");
g_assert(w);
gtk_label_set_text(GTK_LABEL(w),
tAuCodecs[jobp->au_targetCodec].name);
// set fps
w = glade_xml_get_widget(xml, "xvc_result_dialog_fps_label");
g_assert(w);
snprintf(buf, 99, "%.2f", ((float) job->fps / 100));
gtk_label_set_text(GTK_LABEL(w), buf);
// achieved fps
w = glade_xml_get_widget(xml,
"xvc_result_dialog_actual_fps_label");
g_assert(w);
{
char *str_template = NULL;
float total_frames =
((float) jobp->pic_no / (float) job->step) + 1;
float actual_fps =
((float) total_frames) / ((float) time_captured / 1000);
if (actual_fps > ((float) jobp->fps / 100))
actual_fps = (float) jobp->fps / 100;
fps_ratio = actual_fps / ((float) job->fps / 100);
if (fps_ratio > (((float) LM_NUM_DAS - LM_LOW_THRESHOLD) / 10)) {
str_template = "%.2f";
} else if (fps_ratio >
(((float) LM_NUM_DAS - LM_MEDIUM_THRESHOLD) / 10)) {
str_template = "<span background=\"#EEEE00\">%.2f</span>";
} else {
str_template = "<span background=\"#EE0000\">%.2f</span>";
}
snprintf(buf, 99, str_template, actual_fps);
gtk_label_set_markup(GTK_LABEL(w), buf);
}
// fps ratio
w = glade_xml_get_widget(xml,
"xvc_result_dialog_fps_ratio_progressbar");
g_assert(w);
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(w), fps_ratio);
snprintf(buf, 99, "%.2f %%", fps_ratio * 100);
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(w), buf);
// captured frames
w = glade_xml_get_widget(xml,
"xvc_result_dialog_total_frames_label");
g_assert(w);
snprintf(buf, 99, "%i", (jobp->pic_no / job->step) + 1);
gtk_label_set_text(GTK_LABEL(w), buf);
// captured time
w = glade_xml_get_widget(xml,
"xvc_result_dialog_video_length_label");
g_assert(w);
snprintf(buf, 99, "%.2f seconds", ((float) time_captured / 1000));
gtk_label_set_text(GTK_LABEL(w), buf);
if (strlen(target->file) > 0) {
w = glade_xml_get_widget(xml,
"xvc_result_dialog_select_filename_button");
g_assert(w);
gtk_widget_hide(GTK_WIDGET(w));
w = glade_xml_get_widget(xml,
"xvc_result_dialog_filename_label");
g_assert(w);
gtk_widget_hide(GTK_WIDGET(w));
w = glade_xml_get_widget(xml, "xvc_result_dialog_no_button");
g_assert(w);
gtk_widget_hide(GTK_WIDGET(w));
w = glade_xml_get_widget(xml, "xvc_result_dialog_save_button");
g_assert(w);
gtk_widget_hide(GTK_WIDGET(w));
w = glade_xml_get_widget(xml,
"xvc_result_dialog_show_next_time_checkbutton");
g_assert(w);
gtk_widget_show(GTK_WIDGET(w));
w = glade_xml_get_widget(xml,
"xvc_result_dialog_close_button");
g_assert(w);
gtk_widget_show(GTK_WIDGET(w));
}
do {
result = gtk_dialog_run(GTK_DIALOG(xvc_result_dialog));
switch (result) {
case GTK_RESPONSE_OK:
if (target_file_name != NULL) {
char cmd_buf[PATH_MAX * 2 + 5];
int errnum = 0;
snprintf(cmd_buf, (PATH_MAX * 2 + 5), "mv %s %s",
jobp->file, target_file_name);
errnum = system((char *) cmd_buf);
if (errnum != 0) {
GtkWidget *err_dialog =
gtk_message_dialog_new(GTK_WINDOW
(xvc_ctrl_main_window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Error moving file from '%s' to '%s'\n%s",
jobp->file,
target_file_name,
g_strerror(errnum));
gtk_dialog_run(GTK_DIALOG(err_dialog));
gtk_widget_destroy(err_dialog);
}
}
case GTK_RESPONSE_CANCEL:
case GTK_RESPONSE_CLOSE:
w = glade_xml_get_widget(xml,
"xvc_result_dialog_show_next_time_checkbutton");
g_assert(w);
if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
app->flags &= ~FLG_ALWAYS_SHOW_RESULTS;
break;
case GTK_RESPONSE_HELP:
do_results_help();
break;
case GTK_RESPONSE_ACCEPT:
if (!app->current_mode) {
xvc_command_execute(app->single_frame.play_cmd, 1, 0,
jobp->file, jobp->start_no,
jobp->pic_no, jobp->area->width,
jobp->area->height, jobp->fps);
} else {
xvc_command_execute(app->multi_frame.play_cmd, 2,
jobp->movie_no, jobp->file,
jobp->start_no, jobp->pic_no,
jobp->area->width,
jobp->area->height, jobp->fps);
}
break;
default:
break;
}
} while (result == GTK_RESPONSE_HELP
|| result == GTK_RESPONSE_ACCEPT);
gtk_widget_destroy(xvc_result_dialog);
xvc_result_dialog = NULL;
// FIXME: realize move in a way that gives me real error codes
}
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
return FALSE;
#undef DEBUGFUNCTION
}
gboolean timer_stop_recording(Job * job)
{
#define DEBUGFUNCTION "timer_stop_recording()"
xvc_capture_stop_signal(FALSE);
return FALSE;
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_stop_toggle_toggled(GtkToggleToolButton * button,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_stop_toggle_toggled()"
#ifdef DEBUG
printf("%s %s: stopp button toggled\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(button))) {
if (recording_thread_running)
xvc_capture_stop_signal(FALSE);
else {
GladeXML *xml = NULL;
GtkWidget *w = NULL;
xml = glade_get_widget_tree(GTK_WIDGET(xvc_ctrl_main_window));
g_assert(xml);
w = glade_xml_get_widget(xml, "xvc_ctrl_pause_toggle");
g_assert(w);
if (gtk_toggle_tool_button_get_active
(GTK_TOGGLE_TOOL_BUTTON(w)))
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON
(w), FALSE);
}
} else {
// empty
}
#undef DEBUGFUNCTION
}
gboolean start_recording_gui_stuff(Job * job)
{
#define DEBUGFUNCTION "start_recording_gui_stuff()"
GladeXML *xml = NULL;
GtkWidget *w = NULL;
Job *jobp = xvc_job_ptr();
xml = glade_get_widget_tree(GTK_WIDGET(xvc_ctrl_main_window));
g_assert(xml);
// GUI stuff
w = glade_xml_get_widget(xml, "xvc_ctrl_record_toggle");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_stop_toggle");
g_assert(w);
if ((jobp->state & VC_PAUSE) == 0) {
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
}
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(w), FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_select_toggle");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_pause_toggle");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
w = glade_xml_get_widget(xml, "xvc_ctrl_filename_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_edit_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
if (jobp->state & VC_PAUSE) {
w = glade_xml_get_widget(xml, "xvc_ctrl_step_button");
g_assert(w);
if ((jobp->flags & FLG_MULTI_IMAGE) == 0) {
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
w = glade_xml_get_widget(xml, "xvc_ctrl_forward_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
if (jobp->pic_no >= jobp->step) {
w = glade_xml_get_widget(xml, "xvc_ctrl_back_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
}
} else {
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
if (!xvc_is_filename_mutable(jobp->file)) {
w = glade_xml_get_widget(xml, "xvc_ctrl_forward_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_back_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
}
}
} else {
w = glade_xml_get_widget(xml, "xvc_ctrl_forward_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_back_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
}
if (job->flags & FLG_MULTI_IMAGE) {
job->pic_no = job->start_no;
GtkChangeLabel(job->pic_no);
}
return FALSE;
#undef DEBUGFUNCTION
}
gboolean start_recording_nongui_stuff(Job * job)
{
#define DEBUGFUNCTION "start_recording_nongui_stuff()"
struct timeval curr_time;
if (!recording_thread_running) {
// non-gui stuff
// the following also unsets VC_READY
job_keep_and_merge_state(VC_PAUSE, (VC_REC | VC_START));
if (job->flags & FLG_MULTI_IMAGE) {
job->pic_no = job->start_no;
}
if ((job->state & VC_PAUSE) == 0) {
// if (job->max_time != 0 && (job->state & VC_PAUSE) == 0) {
gettimeofday(&curr_time, NULL);
time_captured = 0;
start_time =
curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
if (job->max_time != 0) {
// install a timer which stops recording
// we need milli secs ..
stop_timer_id =
gtk_timeout_add((guint32) (job->max_time * 1000),
(GtkFunction) timer_stop_recording,
job);
}
}
// initialize recording thread
pthread_mutex_init(&recording_mutex, NULL);
pthread_mutex_init(&update_filename_mutex, NULL);
pthread_cond_init(&recording_condition_unpaused, NULL);
pthread_attr_init(&recording_thread_attr);
pthread_attr_setdetachstate(&recording_thread_attr,
PTHREAD_CREATE_JOINABLE);
pthread_create(&recording_thread, &recording_thread_attr,
(void *) do_record_thread, (void *) job);
}
return FALSE;
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_record_toggle_toggled(GtkToggleToolButton * button,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_record_toggle_toggled()"
if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(button))) {
xvc_capture_start();
} else {
// empty
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_pause_toggle_toggled(GtkToggleToolButton * button,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_pause_toggle_toggled()"
struct timeval curr_time;
GladeXML *xml = NULL;
GtkWidget *w = NULL;
Job *jobp = xvc_job_ptr();
xml = glade_get_widget_tree(GTK_WIDGET(xvc_ctrl_main_window));
g_assert(xml);
#ifdef DEBUG
printf("%s %s: button active? (%d)\n", DEBUGFILE, DEBUGFUNCTION, (int)
gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON
(button)));
#endif
if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(button))) {
gettimeofday(&curr_time, NULL);
pause_time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
if ((jobp->state & VC_REC) != 0) {
time_captured += (pause_time - start_time);
} else {
time_captured = 0;
}
// stop timer handling only if max_time is configured
if (jobp->max_time != 0) {
if (stop_timer_id)
g_source_remove(stop_timer_id);
}
job_merge_and_remove_state(VC_PAUSE, VC_STOP);
// GUI stuff
w = glade_xml_get_widget(xml, "xvc_ctrl_stop_toggle");
g_assert(w);
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(w),
FALSE);
// make the led monitor stop
xvc_frame_monitor(0);
// gtk_widget_set_sensitive(GTK_WIDGET(stop), TRUE);
if ((jobp->flags & FLG_MULTI_IMAGE) == 0 && jobp->state & VC_REC) {
w = glade_xml_get_widget(xml, "xvc_ctrl_step_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
w = glade_xml_get_widget(xml, "xvc_ctrl_forward_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
if (jobp->pic_no >= jobp->step) {
w = glade_xml_get_widget(xml, "xvc_ctrl_back_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
}
w = glade_xml_get_widget(xml, "xvc_ctrl_edit_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
}
} else {
job_remove_state(VC_PAUSE | VC_STEP);
// step is always only active if a running recording session is
// paused
// so releasing pause can always deactivate it
w = glade_xml_get_widget(xml, "xvc_ctrl_step_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
// the following only when recording is going on (not when just
// pressing and
// releasing pause
if (jobp->state & VC_REC) {
w = glade_xml_get_widget(xml, "xvc_ctrl_forward_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_back_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
w = glade_xml_get_widget(xml, "xvc_ctrl_edit_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
}
gettimeofday(&curr_time, NULL);
start_time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
// restart timer handling only if max_time is configured
if (jobp->max_time != 0) {
// install a timer which stops recording
// we need milli secs ..
stop_timer_id = g_timeout_add((guint32)
(jobp->max_time * 1000 -
time_captured), (GtkFunction)
timer_stop_recording, jobp);
}
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_step_button_clicked(GtkButton * button, gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_step_button_clicked()"
GladeXML *xml = NULL;
GtkWidget *w = NULL;
Job *jobp = xvc_job_ptr();
if ((jobp->flags & FLG_MULTI_IMAGE) == 0) {
if (!(jobp->state & (VC_PAUSE | VC_REC)))
return;
job_merge_state(VC_STEP);
// FIXME: what is the following condition meant to achieve?
// if (jobp->pic_no == jobp->step ) {
if (jobp->pic_no > (jobp->max_frames - jobp->step)) {
xml = glade_get_widget_tree(GTK_WIDGET(xvc_ctrl_main_window));
g_assert(xml);
w = glade_xml_get_widget(xml, "xvc_ctrl_step_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
}
// FIXME: find a clever way of making the led only flash for step
// prolly needs a completely different handling of the led
// updater, though
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_filename_button_clicked(GtkButton * button, gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_step_button_clicked()"
Job *jobp = xvc_job_ptr();
if ((jobp->flags & FLG_MULTI_IMAGE) == 0) {
if (jobp->pic_no != jobp->start_no
&& ((jobp->state & VC_STOP) > 0
|| (jobp->state & VC_PAUSE) > 0)) {
jobp->pic_no = jobp->start_no;
GtkChangeLabel(jobp->pic_no);
}
} else {
if (jobp->movie_no != 0 && (jobp->state & VC_STOP) > 0) {
jobp->movie_no = 0;
jobp->pic_no = jobp->start_no;
GtkChangeLabel(jobp->pic_no);
}
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_back_button_clicked(GtkButton * button, gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_back_button_clicked()"
Job *jobp = xvc_job_ptr();
if ((jobp->flags & FLG_MULTI_IMAGE) == 0) {
if (jobp->pic_no >= jobp->step) {
jobp->pic_no -= jobp->step;
GtkChangeLabel(jobp->pic_no);
} else {
fprintf(stderr,
"%s %s: back button active although picture number < step. this should never happen\n",
DEBUGFILE, DEBUGFUNCTION);
}
if (jobp->pic_no < jobp->step)
gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
} else {
if (jobp->movie_no > 0) {
jobp->movie_no -= 1;
GtkChangeLabel(jobp->pic_no);
} else {
fprintf(stderr,
"%s %s: back button active although movie number == 0. this should never happen\n",
DEBUGFILE, DEBUGFUNCTION);
}
if (jobp->movie_no == 0)
gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_forward_button_clicked(GtkButton * button, gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_forward_button_clicked()"
GladeXML *xml = NULL;
GtkWidget *w = NULL;
Job *jobp = xvc_job_ptr();
if ((jobp->flags & FLG_MULTI_IMAGE) == 0) {
jobp->pic_no += jobp->step;
GtkChangeLabel(jobp->pic_no);
if (jobp->pic_no == jobp->step) {
xml = glade_get_widget_tree(GTK_WIDGET(xvc_ctrl_main_window));
g_assert(xml);
w = glade_xml_get_widget(xml, "xvc_ctrl_back_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
}
} else {
jobp->movie_no += 1;
GtkChangeLabel(jobp->pic_no);
if (jobp->movie_no == 1) {
xml = glade_get_widget_tree(GTK_WIDGET(xvc_ctrl_main_window));
g_assert(xml);
w = glade_xml_get_widget(xml, "xvc_ctrl_back_button");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
}
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_lock_toggle_toggled(GtkToggleToolButton *
togglebutton, gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_lock_toggle_toggled()"
GtkTooltips *tooltips;
XRectangle *frame_rectangle;
int x, y, pheight, pwidth;
tooltips = gtk_tooltips_new();
if (gtk_toggle_tool_button_get_active(togglebutton)) {
xvc_frame_lock = 1; // button pressed = move frame with
// control
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(togglebutton), tooltips,
_("Detach selection frame"),
_("Detach selection frame"));
gtk_window_set_gravity(GTK_WINDOW(xvc_ctrl_main_window),
GDK_GRAVITY_NORTH_WEST);
gtk_window_get_position(GTK_WINDOW(xvc_ctrl_main_window), &x, &y);
gtk_window_get_size(GTK_WINDOW(xvc_ctrl_main_window), &pwidth,
&pheight);
gtk_window_set_gravity(GTK_WINDOW(xvc_ctrl_main_window),
GDK_GRAVITY_STATIC);
gtk_window_get_position(GTK_WINDOW(xvc_ctrl_main_window), &x, &y);
gtk_window_get_size(GTK_WINDOW(xvc_ctrl_main_window), &pwidth,
&pheight);
if (x < 0)
x = 0;
y += pheight + FRAME_OFFSET;
if (y < 0)
y = 0;
frame_rectangle = xvc_get_capture_area();
xvc_frame_change(x, y, frame_rectangle->width,
frame_rectangle->height, FALSE);
} else {
xvc_frame_lock = 0;
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(togglebutton), tooltips,
_("Attach selection frame"),
_("Attach selection frame"));
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_select_toggle_toggled(GtkToggleToolButton *
togglebutton, gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_select_toggle_toggled()"
Job *jobp = xvc_job_ptr();
if (gtk_toggle_tool_button_get_active(togglebutton)) {
Display *display =
GDK_DRAWABLE_XDISPLAY(GTK_WIDGET(xvc_ctrl_main_window)->
window);
Cursor cursor;
Window root, target = None, temp = None;
XEvent event;
int buttons = 0;
int x_down, y_down, x_up, y_up, x, y, pheight = 0, pwidth = 0;
int width, height;
XGCValues gcv;
GC gc;
g_assert(display);
root = RootWindow(display, DefaultScreen(display));
cursor = XCreateFontCursor(display, XC_crosshair);
gcv.background = XBlackPixel(display, XDefaultScreen(display));
gcv.foreground = XWhitePixel(display, XDefaultScreen(display));
gcv.function = GXinvert;
gcv.plane_mask = gcv.background ^ gcv.foreground;
gcv.subwindow_mode = IncludeInferiors;
gc = XCreateGC(display, root,
GCBackground | GCForeground | GCFunction |
GCPlaneMask | GCSubwindowMode, &gcv);
// grab the mouse
//
if (XGrabPointer(display, root, False,
PointerMotionMask | ButtonPressMask |
ButtonReleaseMask, GrabModeSync,
GrabModeAsync, root, cursor, CurrentTime)
!= GrabSuccess) {
fprintf(stderr, "%s %s: Can't grab mouse!\n", DEBUGFILE,
DEBUGFUNCTION);
return;
}
x_down = y_down = x_up = y_up = width = height = 0;
while (buttons < 2) {
// allow pointer events
XAllowEvents(display, SyncPointer, CurrentTime);
// search in the queue for button events
XWindowEvent(display, root,
PointerMotionMask | ButtonPressMask |
ButtonReleaseMask, &event);
switch (event.type) {
case ButtonPress:
x_down = event.xbutton.x;
y_down = event.xbutton.y;
target = event.xbutton.subwindow; // window selected
//
if (target == None) {
target = root;
}
buttons++;
break;
case ButtonRelease:
x_up = event.xbutton.x;
y_up = event.xbutton.y;
buttons++;
break;
default:
// motion notify
if (buttons == 1) {
if (width) {
// remove old frame
XDrawRectangle(display, root, gc, x, y, width,
height);
}
// button is pressed
if (x_down > event.xbutton.x) {
width = x_down - event.xbutton.x + 1;
x = event.xbutton.x;
} else {
width = event.xbutton.x - x_down + 1;
x = x_down;
}
if (y_down > event.xbutton.y) {
height = y_down - event.xbutton.y + 1;
y = event.xbutton.y;
} else {
height = event.xbutton.y - y_down + 1;
y = y_down;
}
XDrawRectangle(display, root, gc, x, y, width, height);
}
break;
}
}
if (width > 0) // remove old frame
XDrawRectangle(display, root, gc, x, y, width, height);
XUngrabPointer(display, CurrentTime); // Done with pointer
XFreeCursor(display, cursor);
XFreeGC(display, gc);
if ((x_down != x_up) && (y_down != y_up)) {
// an individual frame was selected
if (x_up < x_down) {
width = x_down - x_up + 2;
x = x_up;
} else {
width = x_up - x_down + 2;
x = x_down;
}
if (y_up < y_down) {
height = y_down - y_up + 2;
y = y_up;
} else {
height = y_up - y_down + 2;
y = y_down;
}
if (target != root)
target = XmuClientWindow(display, target);
XGetWindowAttributes(display, target, &jobp->win_attr);
jobp->win_attr.width = width;
jobp->win_attr.height = height;
} else {
if (target != root) {
// get the real window
target = XmuClientWindow(display, target);
}
XGetWindowAttributes(display, target, &jobp->win_attr);
XTranslateCoordinates(display, target, root, 0, 0, &x, &y,
&temp);
}
jobp->win_attr.x = x;
jobp->win_attr.y = y;
// we must move the panel a little bit, so get the height of
// the panel to adjust the y value
gdk_window_get_size(GDK_WINDOW(xvc_ctrl_main_window->window),
&pwidth, &pheight);
pheight = pheight + FRAME_OFFSET;
if (xvc_is_frame_locked()) {
gtk_window_move(GTK_WINDOW(xvc_ctrl_main_window), x,
y - pheight);
}
if (jobp->flags & FLG_RUN_VERBOSE) {
printf("Original Selection geometry: %dx%d+%d+%d\n",
jobp->win_attr.width, jobp->win_attr.height, x, y);
}
#ifdef USE_FFMPEG
//
// make sure we have even width and height for ffmpeg
//
if (jobp->target >= CAP_FFM) {
Boolean changed = FALSE;
if ((jobp->win_attr.width % 2) > 0) {
jobp->win_attr.width--;
changed = TRUE;
}
if ((jobp->win_attr.height % 2) > 0) {
jobp->win_attr.height--;
changed = TRUE;
}
if (jobp->win_attr.width < 20) {
jobp->win_attr.width = 20;
changed = TRUE;
}
if (jobp->win_attr.height < 20) {
jobp->win_attr.height = 20;
changed = TRUE;
}
if (changed) {
if (jobp->flags & FLG_RUN_VERBOSE) {
printf
("Modified Selection geometry: %dx%d+%d+%d\n",
jobp->win_attr.width, jobp->win_attr.height, x,
y);
}
}
}
#endif // USE_FFMPEG
xvc_change_gtk_frame(x, y, jobp->win_attr.width,
jobp->win_attr.height, FALSE);
jobp->ncolors =
xvc_get_colors(display, &jobp->win_attr, &jobp->colors);
if (jobp->get_colors) {
if (jobp->color_table)
free(jobp->color_table);
jobp->color_table =
(*jobp->get_colors) (jobp->colors, jobp->ncolors);
}
if (jobp->flags & FLG_RUN_VERBOSE) {
fprintf(stderr, "%s %s: color_table first entry: 0x%.8X\n",
DEBUGFILE, DEBUGFUNCTION,
*(u_int32_t *) jobp->color_table);
}
xvc_job_set_save_function(jobp->win_attr.visual, jobp->target);
#ifdef DEBUG
printf("%s%s: new visual: %d\n", DEBUGFILE, DEBUGFUNCTION,
jobp->win_attr.visual->class);
#endif
}
gtk_toggle_tool_button_set_active(togglebutton, FALSE);
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_m1_mitem_animate_activate(GtkButton * button,
gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_m1_mitem_animate_activate()"
Job *jobp = xvc_job_ptr();
if (!app->current_mode) {
xvc_command_execute(app->single_frame.play_cmd, 1, 0,
jobp->file, jobp->start_no, jobp->pic_no,
jobp->area->width,
jobp->area->height, jobp->fps);
} else {
xvc_command_execute(app->multi_frame.play_cmd, 2,
jobp->movie_no, jobp->file, jobp->start_no,
jobp->pic_no, jobp->area->width,
jobp->area->height, jobp->fps);
}
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_edit_button_clicked(GtkToolButton * button, gpointer user_data)
{
#define DEBUGFUNCTION "on_xvc_ctrl_edit_button_clicked()"
Job *jobp = xvc_job_ptr();
if (!app->current_mode) {
xvc_command_execute(app->single_frame.edit_cmd, 2,
jobp->pic_no, jobp->file, jobp->start_no,
jobp->pic_no, jobp->area->width,
jobp->area->height, jobp->fps);
} else {
xvc_command_execute(app->multi_frame.edit_cmd, 2,
jobp->movie_no, jobp->file, jobp->start_no,
jobp->pic_no, jobp->area->width,
jobp->area->height, jobp->fps);
}
#undef DEBUGFUNCTION
}
void
position_popup_menu(GtkMenu * menu, gint * x, gint * y,
gboolean * push_in, gpointer user_data)
{
#define DEBUGFUNCTION "position_popup_menu()"
int pheight = 0, px = 0, py = 0, tx = 0, ty = 0;
GtkWidget *w = NULL;
w = GTK_WIDGET(user_data);
g_return_if_fail(w != NULL);
pheight = w->allocation.height;
px = w->allocation.x;
py = w->allocation.y;
tx += px;
ty += py;
w = gtk_widget_get_toplevel(GTK_WIDGET(w));
g_return_if_fail(w != NULL);
gdk_window_get_origin(GDK_WINDOW(w->window), &px, &py);
tx += px;
ty += py;
*x = tx;
*y = ty + pheight;
#undef DEBUGFUNCTION
}
// this pops up the menu on right click on filename button
gint
on_xvc_ctrl_filename_button_button_press_event(GtkWidget * widget,
GdkEvent * event)
{
#define DEBUGFUNCTION "on_xvc_ctrl_filename_button_press_event()"
gboolean is_sensitive = FALSE;
GdkEventButton *bevent = NULL;
g_assert(widget);
g_assert(event);
bevent = (GdkEventButton *) event;
// FIXME: changing from menu sensitive or not to button sensitive or
// not ... make sure that that's what I set elsewhere, too.
g_object_get((gpointer) widget, (gchar *) "sensitive",
&is_sensitive, NULL);
if (bevent->button == (guint) 3 && is_sensitive == TRUE) {
g_assert(xvc_ctrl_m1);
gtk_menu_popup(GTK_MENU(xvc_ctrl_m1), NULL, NULL,
position_popup_menu, widget, bevent->button,
bevent->time);
// Tell calling code that we have handled this event; the buck
// stops here.
return TRUE;
}
// Tell calling code that we have not handled this event; pass it on.
return FALSE;
#undef DEBUGFUNCTION
}
// this handles the shortcut keybindings for the menu
gint
on_xvc_ctrl_main_window_key_press_event(GtkWidget * widget,
GdkEvent * event)
{
#define DEBUGFUNCTION "on_xvc_ctrl_main_window_key_press_event()"
gboolean is_sensitive = FALSE;
GtkWidget *button = NULL, *mitem = NULL;
GdkEventKey *kevent = NULL;
GladeXML *xml = NULL;
g_assert(widget);
g_assert(event);
kevent = (GdkEventKey *) event;
#ifdef DEBUG
printf("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
xml = glade_get_widget_tree(xvc_ctrl_main_window);
g_assert(xml);
button = glade_xml_get_widget(xml, "xvc_ctrl_filename_button");
g_assert(button);
g_object_get((gpointer) button, (gchar *) "sensitive",
&is_sensitive, NULL);
if (kevent->keyval == 112 && kevent->state == 4) {
xml = glade_get_widget_tree(xvc_ctrl_m1);
g_assert(xml);
mitem = glade_xml_get_widget(xml, "xvc_ctrl_m1_mitem_preferences");
g_assert(mitem);
gtk_menu_item_activate(GTK_MENU_ITEM(mitem));
return TRUE;
} else if (kevent->keyval == 113 && kevent->state == 4) {
xml = glade_get_widget_tree(xvc_ctrl_m1);
g_assert(xml);
mitem = glade_xml_get_widget(xml, "xvc_ctrl_m1_mitem_quit");
g_assert(mitem);
gtk_menu_item_activate(GTK_MENU_ITEM(mitem));
return TRUE;
} else if (kevent->keyval == 65470
|| (kevent->state == 4 && kevent->keyval == 104)) {
xml = glade_get_widget_tree(xvc_ctrl_m1);
g_assert(xml);
mitem = glade_xml_get_widget(xml, "xvc_ctrl_m1_mitem_help");
g_assert(mitem);
gtk_menu_item_activate(GTK_MENU_ITEM(mitem));
return TRUE;
}
#ifdef DEBUG
printf("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
// Tell calling code that we have not handled this event; pass it on.
return FALSE;
#undef DEBUGFUNCTION
}
void
on_xvc_ctrl_m1_mitem_about_activate(GtkMenuItem * menuitem,
gpointer user_data)
{
GladeXML *xml = NULL;
// load the interface
xml = glade_xml_new(GLADE_FILE, "xvc_about_main_window", NULL);
g_assert(xml);
// connect the signals in the interface
glade_xml_signal_autoconnect(xml);
}
void xvc_reset_ctrl_main_window_according_to_current_prefs()
{
#define DEBUGFUNCTION "xvc_reset_ctrl_main_window_according_to_current_prefs()"
GladeXML *mwxml = NULL, *menuxml = NULL;
GtkWidget *w = NULL;
GtkTooltips *tooltips;
Job *jobp = xvc_job_ptr();
#ifdef DEBUG
printf("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
#endif // DEBUG
mwxml = glade_get_widget_tree(xvc_ctrl_main_window);
g_assert(mwxml);
menuxml = glade_get_widget_tree(xvc_ctrl_m1);
g_assert(menuxml);
// various GUI initialization things
//
// first: the autocontinue menu item
//
// make autocontinue menuitem invisible if no ffmpeg
#ifndef USE_FFMPEG
w = NULL;
w = glade_xml_get_widget(menuxml, "xvc_ctrl_m1_mitem_autocontinue");
g_return_if_fail(w != NULL);
gtk_widget_hide(GTK_WIDGET(w));
w = NULL;
w = glade_xml_get_widget(menuxml, "xvc_ctrl_m1_separator1");
g_return_if_fail(w != NULL);
gtk_widget_hide(GTK_WIDGET(w));
#else // USE_FFMPEG
// the rest in case we have ffmpeg
if ((jobp->flags & FLG_MULTI_IMAGE) != 0) {
w = glade_xml_get_widget(menuxml,
"xvc_ctrl_m1_mitem_autocontinue");
g_assert(w);
if ((jobp->flags & FLG_AUTO_CONTINUE) != 0) {
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), TRUE);
} else {
if (xvc_is_filename_mutable(jobp->file)) {
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
FALSE);
} else {
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
FALSE);
}
}
} else {
w = glade_xml_get_widget(menuxml,
"xvc_ctrl_m1_mitem_autocontinue");
g_assert(w);
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), FALSE);
}
#endif // USE_FFMPEG
//
// the filename button
//
GtkChangeLabel(jobp->pic_no);
//
// previous and next buttons have different meanings for on-the-fly
// encoding
// and individual frame capture ... this sets the tooltips accordingly
//
//
//
if ((jobp->flags & FLG_MULTI_IMAGE) == 0) {
tooltips = gtk_tooltips_new();
g_assert(tooltips);
w = NULL;
w = glade_xml_get_widget(mwxml, "xvc_ctrl_back_button");
g_assert(w);
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(w), tooltips,
_("Move cursor back one frame"),
_("Move cursor back one frame"));
if (jobp->pic_no >= jobp->step)
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
else
gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE);
w = glade_xml_get_widget(mwxml, "xvc_ctrl_forward_button");
g_assert(w);
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(w), tooltips,
_("Move cursor to next frame"),
_("Move cursor to next frame"));
gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE);
w = glade_xml_get_widget(mwxml, "xvc_ctrl_filename_button");
g_assert(w);
gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), GTK_WIDGET(w),
_
("Left Click: Reset frame counter and filename\nRight Click: Popup Menu"),
_
("Left Click: Reset frame counter and filename\nRight Click: Popup Menu"));
w = glade_xml_get_widget(mwxml, "xvc_ctrl_edit_button");
g_assert(w);
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(w), tooltips,
_("Edit current individual frame"),
_("Edit current individual frame"));
w = glade_xml_get_widget(mwxml, "xvc_ctrl_step_button");
g_assert(w);
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(w), tooltips,
_("Capture single frame"),
_("Capture single frame"));
} else {
GtkWidget *next = NULL, *previous = NULL, *filename = NULL, *w =
NULL;
next = glade_xml_get_widget(mwxml, "xvc_ctrl_forward_button");
g_assert(next);
previous = glade_xml_get_widget(mwxml, "xvc_ctrl_back_button");
g_assert(previous);
filename = glade_xml_get_widget(mwxml, "xvc_ctrl_filename_button");
g_assert(filename);
tooltips = gtk_tooltips_new();
g_assert(tooltips);
if (xvc_is_filename_mutable(jobp->file)) {
gtk_widget_set_sensitive(GTK_WIDGET(next), TRUE);
if (jobp->movie_no > 0)
gtk_widget_set_sensitive(GTK_WIDGET(previous), TRUE);
else
gtk_widget_set_sensitive(GTK_WIDGET(previous), FALSE);
} else {
gtk_widget_set_sensitive(GTK_WIDGET(next), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(previous), FALSE);
}
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(previous), tooltips,
_("Move cursor to previous movie"),
_("Move cursor to previous movie"));
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(next), tooltips,
_("Move cursor to next movie"),
_("Move cursor to next movie"));
gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),
GTK_WIDGET(filename),
_
("Left Click: Reset movie counter to zero\nRight Click: Popup Menu"),
_
("Left Click: Reset movie counter to zero\nRight Click: Popup Menu"));
w = glade_xml_get_widget(mwxml, "xvc_ctrl_edit_button");
g_assert(w);
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(w), tooltips,
_("Edit current movie"),
_("Edit current movie"));
w = glade_xml_get_widget(mwxml, "xvc_ctrl_step_button");
g_assert(w);
gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(w), tooltips, NULL, NULL);
}
//
// capture type radio buttons
//
// make capture type radio buttons invisible if no ffmpeg
#ifndef USE_FFMPEG
w = NULL;
w = glade_xml_get_widget(menuxml, "xvc_ctrl_m1_mitem_sf_capture");
g_return_if_fail(w != NULL);
gtk_widget_hide(GTK_WIDGET(w));
w = NULL;
w = glade_xml_get_widget(menuxml, "xvc_ctrl_m1_mitem_mf_capture");
g_return_if_fail(w != NULL);
gtk_widget_hide(GTK_WIDGET(w));
#else // USE_FFMPEG
if (app->current_mode == 0) {
w = NULL;
w = glade_xml_get_widget(menuxml, "xvc_ctrl_m1_mitem_sf_capture");
g_return_if_fail(w != NULL);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), TRUE);
} else {
w = NULL;
w = glade_xml_get_widget(menuxml, "xvc_ctrl_m1_mitem_mf_capture");
g_return_if_fail(w != NULL);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), TRUE);
}
#endif // USE_FFMPEG
#undef DEBUGFUNCTION
}
syntax highlighted by Code2HTML, v. 0.9.1