/* * Copyright (C) 2004-2005 Vadim Berezniker * http://www.kryptolus.com * * 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, 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 GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "common.h" #include "sabbu.h" #include "gui_status_bar.h" #include "kry_waveform_group.h" #include "gui_waveforms.h" #include "sound.h" #include "sound_out.h" #include "kryTextFileReader.h" extern struct sabbu app; void gui_main_audio_set_keyframes(GList *keyframes) { int keyframes_count = g_list_length(keyframes); long *markers = kry_new(long, keyframes_count); long *markers_orig = markers; kryListIterator iter; while(keyframes) { long val = (long) keyframes->data; markers[0] = val; markers++; keyframes = keyframes->next; } struct KryWaveformKeyframeList *list = kry_waveform_group_get_keyframe_list(app.ui.waveform_group); if(list) kry_free(list->list); list = kry_new(struct KryWaveformKeyframeList, 1); list->list = markers_orig; list->count = keyframes_count; kry_waveform_group_set_keyframe_list(app.ui.waveform_group, list); } struct _window_configure { GtkWindow *window; GtkSpinButton *spin_snap; GtkSpinButton *spin_spacing_x; GtkSpinButton *spin_spacing_y; } window_configure; gboolean gui_main_video_configure_check() { int spacing_x, spacing_y, snap; spacing_x = gtk_spin_button_get_value_as_int(window_configure.spin_spacing_x); spacing_y = gtk_spin_button_get_value_as_int(window_configure.spin_spacing_y); snap = gtk_spin_button_get_value_as_int(window_configure.spin_snap); if(snap > spacing_x || snap > spacing_y || snap <= 0) { gui_error(_("Snap must be less than either of the spacing values")); return FALSE; } gui_main_enable(); app.ui.tab_video.grid_interval_x = spacing_x; app.ui.tab_video.grid_interval_y = spacing_y; app.ui.tab_video.grid_snap_distance = snap; return TRUE; } void gui_main_video_configure_close_cb(GtkWidget *widget, gpointer data) { if(gui_main_video_configure_check()) { gui_main_focus(); gtk_widget_destroy(GTK_WIDGET(window_configure.window)); } } gboolean gui_main_video_configure_delete_cb(GtkWidget *widget, gpointer data) { if(gui_main_video_configure_check()) { gui_main_focus(); return FALSE; } else { return TRUE; } } void gui_main_menu_video_configure_grid (gpointer callback_data, guint callback_action, GtkWidget *menu_item) { GtkWindow *window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); GtkLabel *label_spacing_x = GTK_LABEL(gtk_label_new(_("Horizontal Spacing:"))); GtkLabel *label_spacing_y = GTK_LABEL(gtk_label_new(_("Vertical Spacing"))); GtkLabel *label_snap = GTK_LABEL(gtk_label_new(_("Snap:"))); GtkVBox *vbox = GTK_VBOX(gtk_vbox_new(FALSE, 0)); GtkButton *button = GTK_BUTTON(gtk_button_new_with_label(_("Close"))); GtkTable *table = GTK_TABLE(gtk_table_new(3, 2, FALSE)); GtkSpinButton *spin_spacing_x = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(1, 1000, 1)); GtkSpinButton *spin_spacing_y = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(1, 1000, 1)); GtkSpinButton *spin_snap = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(1, 1000, 1)); gtk_window_set_title(window, _("Configure Grid")); gtk_window_set_transient_for(window, app.ui.window); gtk_window_set_position(window, GTK_WIN_POS_CENTER_ON_PARENT); gtk_window_set_modal(window, TRUE); gtk_spin_button_set_value(spin_spacing_x, app.ui.tab_video.grid_interval_x); gtk_spin_button_set_value(spin_spacing_y, app.ui.tab_video.grid_interval_y); gtk_spin_button_set_value(spin_snap, app.ui.tab_video.grid_snap_distance); gtk_table_attach_defaults(table, GTK_WIDGET(label_spacing_x), 0, 1, 0, 1); gtk_table_attach_defaults(table, GTK_WIDGET(label_spacing_y), 0, 1, 1, 2); gtk_table_attach_defaults(table, GTK_WIDGET(label_snap), 0, 1, 2, 3); gtk_table_attach_defaults(table, GTK_WIDGET(spin_spacing_x), 1, 2, 0, 1); gtk_table_attach_defaults(table, GTK_WIDGET(spin_spacing_y), 1, 2, 1, 2); gtk_table_attach_defaults(table, GTK_WIDGET(spin_snap), 1, 2, 2, 3); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, TRUE, 0); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox)); window_configure.spin_snap = spin_snap; window_configure.spin_spacing_x = spin_spacing_x; window_configure.spin_spacing_y = spin_spacing_y; window_configure.window = window; g_signal_connect(button, "clicked", G_CALLBACK(gui_main_video_configure_close_cb), NULL); g_signal_connect(window, "delete-event", G_CALLBACK(gui_main_video_configure_delete_cb), NULL); gui_main_disable(); gtk_widget_show_all(GTK_WIDGET(window)); } void gui_main_menu_video_ahow_grid (gpointer callback_data, guint callback_action, GtkWidget *menu_item) { app.ui.tab_video.showGrid = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_item)); gtk_widget_queue_draw(GTK_WIDGET(app.ui.video_area)); } void gui_main_menu_video_keyframes_load(gpointer callback_data, guint callback_action, GtkWidget *menu_item) { char *filename = gui_main_open_file(__("FileDialog|Open Key Frames List"), file_filter_keyframe); if(!filename) return; kryTextFileReader *reader = new kryTextFileReader(filename); if(!reader->Open()) { gui_error(_("Error opening keyframes file")); delete reader; return; } GList *list = NULL; while(char *line = reader->GetLine()) { long time = time_string_to_mili(line, -1); list = g_list_append(list, (gpointer) time); kry_free(line); } gui_main_audio_set_keyframes(list); g_list_free(list); delete reader; } void gui_main_menu_video_keyframes_save(gpointer callback_data, guint callback_action, GtkWidget *menu_item) { KryWaveformKeyframeList *list = kry_waveform_group_get_keyframe_list(app.ui.waveform_group); if(!list) return; char *def_name = NULL; if(app.ui.tab_video.video && app.ui.tab_video.video->filename) { char *base = g_path_get_basename(app.ui.tab_video.video->filename); for(int i = strlen(base) - 1; i >= 0; i--) { if(base[i] == '.') { base[i] = 0; break; } } def_name = kry_strdup_printf(KRY_LOC "%s.keyframes", base); kry_free(base); } char *filename = gui_main_save_file(__("FileDialog|Save Key Frames List"), file_filter_keyframe, "keyframes", def_name); if(def_name) kry_free(def_name); if(!filename) return; FILE *fh = fopen(filename, "w"); if(!fh) { gui_error(_("Cannot write to file")); return; } for(int i = 0; i < list->count; i++) { char *text = time_mili_to_string(list->list[i]); fwrite(text, strlen(text), 1, fh); fwrite("\n", strlen("\n"), 1, fh); kry_free(text); } fclose(fh); } void gui_main_menu_video_keyframes_mark(gpointer callback_data, guint callback_action, GtkWidget *menu_item) { struct video_ffmpeg *video = app.ui.tab_video.video; AVPacket pkt; int frames = 0, keyframes_count = 0; int64_t pos; double last_val = 0; double val; GList *keyframes = NULL; if(!app.ui.sound_info || !app.ui.tab_video.video) return; if(!video_seek(video, 0)) return; gui_main_disable(); gui_status_bar_text_and_progress_mode(app.ui.status_bar, __("Status|Marking Keyframes...")); pos = video_get_duration(video); while(video_get_frame(video, &pkt)) { val = pkt.pts / (double) pos; if(val - last_val > 0.05) { if(pos && pkt.pts <= pos) gui_status_bar_set_progress(app.ui.status_bar, pkt.pts / (double) pos, TRUE); last_val = val; } if(pkt.flags & PKT_FLAG_KEY) { keyframes = g_list_append(keyframes, (gpointer) ((long) ((pkt.pts / (double) AV_TIME_BASE) * 1000))); keyframes_count++; } frames++; } gui_main_audio_set_keyframes(keyframes); g_list_free(keyframes); gui_status_bar_text_only_mode(app.ui.status_bar); gui_main_enable(); } void gui_video_open(char *filename) { if(app.opts.video_disabled) return; try { app.ui.tab_video.video = video_open(filename); } catch(kryError error) { gui_error(error.GetMessage()); return; } gui_main_recent_list_add(app.ui.menu.video.open_recent, &app.ui.list_recent_videos, app.ui.cb_recent_videos, kry_strdup(filename)); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.tab_video.button_lock), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.tab_video.button_video), TRUE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(app.ui.tab_video.button_video), TRUE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(app.ui.tab_video.button_lock), TRUE); kry_marker_set_value(app.ui.tab_video.marker_start_prev, -1); gui_status_bar_push_text_with_color(app.ui.status_bar, STATUS_VIDEO_OPENED, __("Status|Video Succesfully Opened"), app.ui.status_bar_color_table->Get(STATUS_COLOR_SUCCESS)); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.video.close), TRUE); } void gui_main_menu_video_openrecent(GtkWidget *menu, char *filename) { gui_video_open(filename); } void gui_main_menu_video_open(gpointer callback_data, guint callback_action, GtkWidget *menu_item) { if(app.opts.video_disabled) return; char *filename; filename = gui_main_open_file(__("FileDialog|Open Video"), file_filter_video); if(!filename) return; gui_video_open(filename); } void gui_main_video_close() { if(!app.ui.tab_video.video) return; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(app.ui.tab_video.button_lock), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.tab_video.button_lock), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.tab_video.button_video), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.tab_video.button_jump_start), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.tab_video.button_jump_end), FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(app.ui.tab_video.button_solid), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.video.close), FALSE); video_close(app.ui.tab_video.video); app.ui.tab_video.video = NULL; } void gui_main_menu_video_close(GtkWidget *menu_item, guint callback_action) { gui_main_video_close(); }