/* * Sweep, a sound wave editor. * * Copyright (C) 2000 Conrad Parker * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Thu Oct 22 2000 - Added 1:1 and Normal zooms from * Steve Harris */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include "view.h" #include "about_dialog.h" #include "sample.h" #include "callbacks.h" #include "channelops.h" #include "interface.h" #include "print.h" #include "param.h" #include "record.h" #include "sample-display.h" #include "file_dialogs.h" #include "question_dialogs.h" #include "driver.h" #include "notes.h" #include "db_ruler.h" #include "time_ruler.h" #include "cursors.h" #include "head.h" #include "view_pixmaps.h" /*#define DEBUG*/ #define USER_GTKRC /* #define SCROLL_SMOOTHLY */ /* Default initial dimensions. * * Golden ratio. Oath. * (sqrt(5)-1)/2 = 0.61803398874989484820 * 2/(sqrt(5)-1) = 1.61803398874989484820 * * Keep width:height ratio equal to one of these * for pleasing dimensions. */ #define VIEW_MIN_WIDTH 197 #define VIEW_MAX_WIDTH 1034 #define VIEW_DEFAULT_HEIGHT_PER_CHANNEL 320 #define DEFAULT_MIN_ZOOM 8 #define NO_TIME "" #define NOREADY(w) \ (view->noready_widgets = g_list_append (view->noready_widgets, (w))) #define NOMODIFY(w) \ (view->nomodify_widgets = g_list_append (view->nomodify_widgets, (w))) #define NOALLOC(w) \ (view->noalloc_widgets = g_list_append (view->noalloc_widgets, (w))) #ifdef HAVE_LIBSAMPLERATE void samplerate_dialog_new_cb (GtkWidget * widget, gpointer data); #endif static GtkWidget * create_view_menu_item(GtkWidget * menu, gchar * label, gchar * accel_path, sw_view *view,gpointer callback, gboolean nomodify, guint accel_key, GdkModifierType accel_mods, gpointer user_data); void view_set_vzoom (sw_view * view, sw_audio_t low, sw_audio_t high); extern GList * plugins; extern GdkCursor * sweep_cursors[]; extern GtkRecentManager *recent_manager; extern GtkStyle * style_wb; extern GtkStyle * style_LCD; extern GtkStyle * style_light_grey; extern GtkStyle * style_green_grey; extern GtkStyle * style_red_grey; extern GtkStyle * style_dark_grey; /* Global */ sw_view * last_tmp_view = NULL; /* last used tmp_view */ /* proc_instance: * a type for applying a procedure to a sample */ typedef struct _sw_proc_instance sw_proc_instance; struct _sw_proc_instance { sw_procedure * proc; sw_view * view; }; static sw_proc_instance * sw_proc_instance_new (sw_procedure * proc, sw_view * view) { sw_proc_instance * pi; /* XXX: where to clean this up? */ pi = g_malloc (sizeof (sw_proc_instance)); pi->proc = proc; pi->view = view; return pi; } static void apply_procedure_cb (GtkWidget * widget, gpointer data) { sw_proc_instance * pi = (sw_proc_instance *)data; sw_procedure * proc = pi->proc; sw_sample * sample = pi->view->sample; sw_param_set pset; if (proc->nr_params == 0) { pset = NULL; proc->apply (sample, pset, proc->custom_data); } else { pset = sw_param_set_new (proc); if (proc->suggest) proc->suggest (sample, pset, proc->custom_data); create_param_set_adjuster (proc, pi->view, pset); } } static void create_proc_menuitem (sw_procedure * proc, sw_view * view, GtkWidget * submenu, GtkAccelGroup * accel_group) { sw_proc_instance * pi; GtkWidget * menuitem; pi = sw_proc_instance_new (proc, view); menuitem = gtk_menu_item_new_with_label(_(proc->name)); gtk_menu_append(GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(apply_procedure_cb), pi); gtk_widget_show(menuitem); /* these accels are not editable */ /* gtk_widget_add_accelerator (menuitem, "activate", accel_group, proc->accel_key, proc->accel_mods, GTK_ACCEL_VISIBLE); */ } static GtkWidget * create_proc_menu (sw_view * view, GtkAccelGroup * accel_group) { GtkWidget * menu, * submenu, * menuitem = NULL, * label, * hbox; GList * gl; sw_procedure * proc; gboolean use_submenus = FALSE; gint i = 0, li = 0; gchar first_name[32], last_name[32]; gchar * title; menu = gtk_menu_new (); if (g_list_length (plugins) > 10) { use_submenus = TRUE; } submenu = menu; if (plugins) /*strncpy (first_name, ((sw_procedure *)plugins->data)->name, 4);*/ sscanf (_(((sw_procedure *)plugins->data)->name), "%s", first_name); /* Filter plugins */ for (gl = plugins; gl; gl = gl->next) { proc = (sw_procedure *)gl->data; if (use_submenus && ((i % 10) == 0)) { if (menuitem) { hbox = gtk_hbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER(menuitem), hbox); gtk_widget_show (hbox); title = g_strdup_printf ("%s ... %s", first_name, last_name); label = gtk_label_new (title); gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0); /*menuitem = gtk_menu_item_new_with_label (title);*/ gtk_widget_show (label); /*strncpy (first_name, proc->name, 4);*/ sscanf (_(proc->name), "%s", first_name); li = i; } menuitem = gtk_menu_item_new (); gtk_menu_append (GTK_MENU(menu), menuitem); gtk_widget_show (menuitem); submenu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), submenu); } create_proc_menuitem (proc, view, submenu, accel_group); /*strncpy (last_name, proc->name, 4);*/ sscanf (_(proc->name), "%s", last_name); i++; } if (menuitem) { hbox = gtk_hbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER(menuitem), hbox); gtk_widget_show (hbox); label = gtk_label_new (g_strdup_printf ("%s ... %s", first_name, last_name)); gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show (label); } return menu; } static void view_store_cb (GtkWidget * widget, gpointer data); static void view_retrieve_cb (GtkWidget * widget, gpointer data); static GtkWidget * view_refresh_channelops_menu (sw_view * view) { GtkWidget * submenu, * menuitem = NULL; GList * gl; int old_channels, channels; GtkAccelGroup *accel_group; channels = view->sample->sounddata->format->channels; if (view->channelops_submenu != NULL) { old_channels = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(view->channelops_submenu), "default")); /* If there's no need to change the submenu, don't */ if ((old_channels == channels) || (old_channels > 2 && channels > 2)) { return view->channelops_submenu; } } /* Remove references to old channelops widgets from sensitivity updates */ for (gl = view->channelops_widgets; gl; gl = gl->next) { view->nomodify_widgets = g_list_remove (view->nomodify_widgets, gl->data); } g_list_free (view->channelops_widgets); view->channelops_widgets = NULL; /* Create the new channelops submenu */ submenu = gtk_menu_new (); accel_group = GTK_ACCEL_GROUP(g_object_get_data(G_OBJECT(view->window), "accel_group")); gtk_menu_set_accel_group (GTK_MENU (submenu), accel_group); g_object_set_data (G_OBJECT(submenu), "default", GINT_TO_POINTER(channels)); if (channels == 1) { menuitem = create_view_menu_item (submenu, _("Duplicate to stereo"), "/Sample/Channels/Duplicate to stereo", view, dup_stereo_cb, TRUE, 0, 0, view); view->channelops_widgets = g_list_append (view->channelops_widgets, menuitem); menuitem = create_view_menu_item (submenu, _("Duplicate to multichannel"), "/Channels/Duplicate to multichannel", view, dup_channels_dialog_new_cb, TRUE, 0, 0, view); view->channelops_widgets = g_list_append (view->channelops_widgets, menuitem); } if (channels == 2) { menuitem = create_view_menu_item (submenu, _("Swap left and right"), "/Sample/Channels/Swap left and right", view, stereo_swap_cb, TRUE, 0, 0, view); view->channelops_widgets = g_list_append (view->channelops_widgets, menuitem); menuitem = create_view_menu_item (submenu, _("Remove left channel"), "/Sample/Channels/Remove left channel", view, remove_left_cb, TRUE, 0, 0, view); view->channelops_widgets = g_list_append (view->channelops_widgets, menuitem); menuitem = create_view_menu_item (submenu, _("Remove right channel"), "/Sample/Channels/Remove right channel", view, remove_right_cb, TRUE, 0, 0, view); view->channelops_widgets = g_list_append (view->channelops_widgets, menuitem); } if (channels > 1) { menuitem = create_view_menu_item (submenu, _("Mix down to mono"), "/Sample/Channels/Mix down to mono", view, mono_mixdown_cb, TRUE, 0, 0, view); view->channelops_widgets = g_list_append (view->channelops_widgets, menuitem); } menuitem = create_view_menu_item (submenu, _("Add/Remove channels"), "/Sample/Channels/Add/Remove channels", view, channels_dialog_new_cb, TRUE, 0, 0, view); view->channelops_widgets = g_list_append (view->channelops_widgets, menuitem); gtk_menu_item_set_submenu (GTK_MENU_ITEM(view->channelops_menuitem), submenu); view->channelops_submenu = submenu; return submenu; } /* * Convenience function to Create and setup individual menuitems */ static GtkWidget * create_view_menu_item(GtkWidget * menu, gchar * label, gchar * accel_path, sw_view *view,gpointer callback, gboolean nomodify, guint accel_key, GdkModifierType accel_mods, gpointer user_data) { GtkWidget * menuitem; menuitem = gtk_menu_item_new_with_label(label); /* register accel path enabling runtime changes by the user */ gtk_menu_item_set_accel_path (GTK_MENU_ITEM(menuitem), accel_path); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(callback), user_data); /* register default key binding (if one is supplied */ if (accel_key) gtk_accel_map_add_entry (accel_path, accel_key, accel_mods); if (nomodify) NOMODIFY(menuitem); gtk_widget_show(menuitem); return menuitem; } /* * Populate a GtkMenu or GtkMenubar m */ static GtkAccelGroup * create_view_menu (sw_view * view, GtkWidget * m) { GtkWidget * menuitem; GtkWidget * submenu, *subsubmenu; GtkAccelGroup *accel_group; SampleDisplay * s = SAMPLE_DISPLAY(view->display); #define MENU_APPEND(w,c) \ if (GTK_IS_MENU_BAR(w)) { \ gtk_menu_bar_append(GTK_MENU_BAR(w), c); \ } else if (GTK_IS_MENU(w)) { \ gtk_menu_append(GTK_MENU(w), c); \ } /* Create a GtkAccelGroup and add it to the window. */ accel_group = gtk_accel_group_new(); g_object_set_data(G_OBJECT(view->window), "accel_group", accel_group); /* File */ menuitem = gtk_menu_item_new_with_label(_("File")); MENU_APPEND(m, menuitem); gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_set_accel_group (GTK_MENU (submenu), accel_group); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); create_view_menu_item (submenu, _("New ..."), "/File/New ...", view, sample_new_empty_cb, FALSE, GDK_n, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Open ..."), "/File/Open ...", view, sample_load_cb, FALSE, GDK_o, GDK_CONTROL_MASK, view->window); #if GTK_CHECK_VERSION (2, 10, 0) GtkWidget *recent_menu; GtkRecentFilter * filter; if (recent_manager != NULL) { recent_menu = gtk_recent_chooser_menu_new_for_manager(recent_manager); gtk_widget_show(recent_menu); g_signal_connect(G_OBJECT(recent_menu), "item-activated", G_CALLBACK(recent_chooser_menu_activated_cb), NULL); gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER(recent_menu), 20); gtk_recent_chooser_set_show_tips (GTK_RECENT_CHOOSER(recent_menu), TRUE); gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER(recent_menu), GTK_RECENT_SORT_MRU); filter = gtk_recent_filter_new(); gtk_recent_filter_add_application(filter, g_get_application_name()); gtk_recent_chooser_add_filter(GTK_RECENT_CHOOSER(recent_menu), filter); menuitem = gtk_menu_item_new_with_label(_("Open Recent")); gtk_menu_item_set_accel_path (GTK_MENU_ITEM(menuitem), "/File/Open Recent"); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), recent_menu); gtk_widget_show(GTK_WIDGET(menuitem)); } #endif create_view_menu_item (submenu, _("Save"), "/File/Save", view, sample_save_cb, TRUE, GDK_s, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Save As ..."), "/File/Save As ...", view, sample_save_as_cb, TRUE, 0, 0, view); create_view_menu_item (submenu, _("Revert"), "/File/Revert", view, sample_revert_cb, TRUE, 0, 0, view); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("Properties ..."), "/File/Properties ...", view, show_info_dialog_cb, FALSE, 0, 0, view); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("Close"), "/File/Close", view, view_close_cb, FALSE, GDK_w, GDK_CONTROL_MASK, s); create_view_menu_item (submenu, _("Quit"), "/File/Quit", view, exit_cb, FALSE, GDK_q, GDK_CONTROL_MASK, s); /* Edit */ menuitem = gtk_menu_item_new_with_label(_("Edit")); MENU_APPEND(m, menuitem); gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_set_accel_group (GTK_MENU (submenu), accel_group); gtk_menu_item_set_accel_path (GTK_MENU_ITEM(menuitem), "/Edit"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); menuitem = create_view_menu_item (submenu, _("Cancel"), "/Edit/Cancel", view, cancel_cb, FALSE, GDK_Escape, GDK_BUTTON1_MASK, view); NOREADY(menuitem); create_view_menu_item (submenu, _("Undo"), "/Edit/Undo", view, undo_cb, TRUE, GDK_z, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Redo"), "/Edit/Redo", view, redo_cb, TRUE, GDK_r, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Show history ..."), "/Edit/Show history ...", view, show_undo_dialog_cb, FALSE, 0, 0, view); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("Delete"), "/Edit/Delete", view, delete_cb, TRUE, 0, 0, view); create_view_menu_item (submenu, _("Cut"), "/Edit/Cut", view, cut_cb, TRUE, GDK_x, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Copy"), "/Edit/Copy", view, copy_cb, TRUE, GDK_c, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Clear"), "/Edit/Clear", view, clear_cb, TRUE, 0, 0, view); create_view_menu_item (submenu, _("Crop"), "/Edit/Crop", view, crop_cb, TRUE, 0, 0, view); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("Paste: Insert"), "/Edit/Paste: Insert", view, paste_cb, TRUE, GDK_v, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Paste: Mix"), "/Edit/Paste: Mix", view, paste_mix_cb, TRUE, GDK_m, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Paste: Crossfade"), "/Edit/Paste: Crossfade", view, paste_xfade_cb, TRUE, GDK_f, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Paste as New"), "/Edit/Paste as New", view, paste_as_new_cb, TRUE, GDK_e, GDK_CONTROL_MASK, view); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("Preview Cut/Cursor"), "/Edit/Preview Cut-Cursor", view, preview_cut_cb, FALSE, GDK_k, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("Pre-roll to Cursor"), "/Edit/Pre-roll to Cursor", view, preroll_cb, FALSE, GDK_k, GDK_SHIFT_MASK|GDK_CONTROL_MASK, view); /* Select */ menuitem = gtk_menu_item_new_with_label(_("Select")); MENU_APPEND(m, menuitem); gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_set_accel_group (GTK_MENU (submenu), accel_group); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); create_view_menu_item (submenu, _("Invert"), "/Select/Invert", view, select_invert_cb, TRUE, GDK_i, GDK_CONTROL_MASK, s); create_view_menu_item (submenu, _("All"), "/Select/All", view, select_all_cb, TRUE, GDK_a, GDK_CONTROL_MASK, s); create_view_menu_item (submenu, _("None"), "/Select/None", view, select_none_cb, TRUE, GDK_a, GDK_SHIFT_MASK|GDK_CONTROL_MASK, s); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("Halve"), "/Select/Halve", view, selection_halve_cb, TRUE, GDK_semicolon, GDK_BUTTON1_MASK, s); create_view_menu_item (submenu, _("Double"), "/Select/Double", view, selection_double_cb, TRUE, GDK_quoteright, GDK_BUTTON1_MASK, s); create_view_menu_item (submenu, _("Shift left"), "/Select/Shift left", view, select_shift_left_cb, TRUE, GDK_less, GDK_BUTTON1_MASK, s); create_view_menu_item (submenu, _("Shift right"), "/Select/Shift right", view, select_shift_right_cb, TRUE, GDK_greater, GDK_BUTTON1_MASK, s); /* View */ menuitem = gtk_menu_item_new_with_label(_("View")); MENU_APPEND(m, menuitem); gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_set_accel_group (GTK_MENU (submenu), accel_group); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); menuitem = gtk_check_menu_item_new_with_label(_("Autoscroll: follow playback cursor")); gtk_menu_item_set_accel_path(GTK_MENU_ITEM(menuitem), "/View/Autoscroll: follow playback cursor"); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menuitem), view->following); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(follow_toggle_cb), view); gtk_widget_show(menuitem); view->follow_checkmenu = menuitem; gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menuitem), view->following); view->follow_checkmenu = menuitem; menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("Center"), "/View/Center", view, zoom_center_cb, FALSE, GDK_slash, GDK_BUTTON1_MASK, s); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("Zoom in"), "/View/Zoom in", view, zoom_in_cb, FALSE, GDK_equal, GDK_BUTTON1_MASK, view); create_view_menu_item (submenu, _("Zoom out"), "/View/Zoom out", view, zoom_out_cb, FALSE, GDK_minus, GDK_BUTTON1_MASK, view); create_view_menu_item (submenu, _("Zoom to selection"), "/View/Zoom to selection", view, zoom_to_sel_cb, FALSE, 0, 0, s); create_view_menu_item (submenu, _("Zoom normal"), "/View/Zoom normal", view, zoom_norm_cb, FALSE, 0, 0, s); create_view_menu_item (submenu, _("Zoom all"), "/View/Zoom all", view, zoom_all_cb, FALSE, GDK_1, GDK_CONTROL_MASK, view); create_view_menu_item (submenu, _("1:1"), "/View/1:1", view, zoom_1to1_cb, FALSE, 0, 0, s); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); /* Store view */ menuitem = gtk_menu_item_new_with_label(_("Remember as")); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); subsubmenu = gtk_menu_new(); gtk_menu_set_accel_group (GTK_MENU (subsubmenu), accel_group); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), subsubmenu); #define REMEMBER_AS(title,index,accel_path) \ menuitem = gtk_menu_item_new_with_label ((title)); \ g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER((index))); \ gtk_menu_append (GTK_MENU(subsubmenu), menuitem); \ gtk_widget_show (menuitem); \ g_signal_connect (G_OBJECT(menuitem), "activate", \ G_CALLBACK(view_store_cb), view); \ gtk_menu_item_set_accel_path (GTK_MENU_ITEM(menuitem), accel_path); \ gtk_accel_map_add_entry (accel_path, \ GDK_KP_##index, GDK_CONTROL_MASK); REMEMBER_AS(_("Area 1"), 1, "/View/Remember As/Area 1"); REMEMBER_AS(_("Area 2"), 2, "/View/Remember As/Area 2"); REMEMBER_AS(_("Area 3"), 3, "/View/Remember As/Area 3"); REMEMBER_AS(_("Area 4"), 4, "/View/Remember As/Area 4"); REMEMBER_AS(_("Area 5"), 5, "/View/Remember As/Area 5"); REMEMBER_AS(_("Area 6"), 6, "/View/Remember As/Area 6"); REMEMBER_AS(_("Area 7"), 7, "/View/Remember As/Area 7"); REMEMBER_AS(_("Area 8"), 8, "/View/Remember As/Area 8"); REMEMBER_AS(_("Area 9"), 9, "/View/Remember As/Area 9"); REMEMBER_AS(_("Area 10"), 0, "/View/Remember As/Area 10"); /* Retrieve view */ menuitem = gtk_menu_item_new_with_label(_("Zoom to")); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); subsubmenu = gtk_menu_new(); gtk_menu_set_accel_group (GTK_MENU (subsubmenu), accel_group); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), subsubmenu); #define ZOOM_TO(title,index,accel_path) \ menuitem = gtk_menu_item_new_with_label ((title)); \ g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER((index))); \ gtk_menu_append (GTK_MENU(subsubmenu), menuitem); \ gtk_widget_show (menuitem); \ g_signal_connect (G_OBJECT(menuitem), "activate", \ G_CALLBACK(view_retrieve_cb), view); \ gtk_menu_item_set_accel_path (GTK_MENU_ITEM(menuitem), accel_path); \ gtk_accel_map_add_entry (accel_path, \ GDK_KP_##index, GDK_BUTTON1_MASK); ZOOM_TO(_("Area 1"), 1, "/View/Zoom To/Area 1"); ZOOM_TO(_("Area 2"), 2, "/View/Zoom To/Area 2"); ZOOM_TO(_("Area 3"), 3, "/View/Zoom To/Area 3"); ZOOM_TO(_("Area 4"), 4, "/View/Zoom To/Area 4"); ZOOM_TO(_("Area 5"), 5, "/View/Zoom To/Area 5"); ZOOM_TO(_("Area 6"), 6, "/View/Zoom To/Area 6"); ZOOM_TO(_("Area 7"), 7, "/View/Zoom To/Area 7"); ZOOM_TO(_("Area 8"), 8, "/View/Zoom To/Area 8"); ZOOM_TO(_("Area 9"), 9, "/View/Zoom To/Area 9"); ZOOM_TO(_("Area 10"), 0, "/View/Zoom To/Area 10"); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Color scheme")); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); subsubmenu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), subsubmenu); menuitem = gtk_menu_item_new_with_label (_("Decoder Red")); g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER(VIEW_COLOR_RED)); gtk_menu_append (GTK_MENU(subsubmenu), menuitem); gtk_widget_show (menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(sample_set_color_cb), view); menuitem = gtk_menu_item_new_with_label (_("Orangeboom")); g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER(VIEW_COLOR_ORANGE)); gtk_menu_append (GTK_MENU(subsubmenu), menuitem); gtk_widget_show (menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(sample_set_color_cb), view); menuitem = gtk_menu_item_new_with_label (_("Lame Yellow")); g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER(VIEW_COLOR_YELLOW)); gtk_menu_append (GTK_MENU(subsubmenu), menuitem); gtk_widget_show (menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(sample_set_color_cb), view); menuitem = gtk_menu_item_new_with_label (_("Coogee Bay Blue")); g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER(VIEW_COLOR_BLUE)); gtk_menu_append (GTK_MENU(subsubmenu), menuitem); gtk_widget_show (menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(sample_set_color_cb), view); menuitem = gtk_menu_item_new_with_label (_("Blackwattle")); g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER(VIEW_COLOR_BLACK)); gtk_menu_append (GTK_MENU(subsubmenu), menuitem); gtk_widget_show (menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(sample_set_color_cb), view); menuitem = gtk_menu_item_new_with_label (_("Frigid")); g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER(VIEW_COLOR_WHITE)); gtk_menu_append (GTK_MENU(subsubmenu), menuitem); gtk_widget_show (menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(sample_set_color_cb), view); menuitem = gtk_menu_item_new_with_label (_("Radar")); g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER(VIEW_COLOR_RADAR)); gtk_menu_append (GTK_MENU(subsubmenu), menuitem); gtk_widget_show (menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(sample_set_color_cb), view); menuitem = gtk_menu_item_new_with_label (_("Bluescreen")); g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER(VIEW_COLOR_BLUESCREEN)); gtk_menu_append (GTK_MENU(subsubmenu), menuitem); gtk_widget_show (menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(sample_set_color_cb), view); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("New View"), "/View/New View", view, view_new_cb, FALSE, 0, 0, s); /* Sample */ menuitem = gtk_menu_item_new_with_label(_("Sample")); MENU_APPEND(m, menuitem); gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_set_accel_group (GTK_MENU (submenu), accel_group); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); menuitem = gtk_menu_item_new_with_label (_("Channels")); gtk_menu_append (GTK_MENU(submenu), menuitem); gtk_widget_show (menuitem); view->channelops_menuitem = menuitem; view->channelops_submenu = NULL; view_refresh_channelops_menu (view); #ifdef HAVE_LIBSAMPLERATE create_view_menu_item (submenu, _("Resample ..."), "/Sample/Resample ...", view, samplerate_dialog_new_cb, TRUE, 0, 0, view); #endif menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); create_view_menu_item (submenu, _("Duplicate"), "/Sample/Duplicate", view, sample_new_copy_cb, TRUE, GDK_d, GDK_CONTROL_MASK, s); /* Filters */ menuitem = gtk_menu_item_new_with_label(_("Process")); MENU_APPEND(m, menuitem); gtk_widget_show(menuitem); submenu = create_proc_menu (view, accel_group); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); NOMODIFY(menuitem); /* Playback */ menuitem = gtk_menu_item_new_with_label(_("Playback")); MENU_APPEND(m, menuitem); gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_set_accel_group (GTK_MENU (submenu), accel_group); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); create_view_menu_item (submenu, _("Configure audio device ..."), "/Playback/Configure audio device ...", view, device_config_cb, FALSE, 0, 0, view); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Transport")); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); subsubmenu = gtk_menu_new(); gtk_menu_set_accel_group (GTK_MENU (subsubmenu), accel_group); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), subsubmenu); NOALLOC(menuitem); create_view_menu_item (subsubmenu, _("Go to start of file"), "/Playback/Transport/Go to start of file", view, goto_start_cb, FALSE, GDK_Home, GDK_CONTROL_MASK, view); create_view_menu_item (subsubmenu, _("Go to start of window"), "/Playback/Transport/Go to start of window", view, goto_start_of_view_cb, FALSE, GDK_Home, GDK_BUTTON1_MASK, view); create_view_menu_item (subsubmenu, _("Skip back"), "/Playback/Transport/Skip back", view, page_back_cb, FALSE, GDK_Page_Up, GDK_BUTTON1_MASK, view); create_view_menu_item (subsubmenu, _("Skip forward"), "/Playback/Transport/Skip forward", view, page_fwd_cb, FALSE, GDK_Page_Down, GDK_BUTTON1_MASK, view); create_view_menu_item (subsubmenu, _("Go to end of window"), "/Playback/Transport/Go to end of window", view, goto_end_of_view_cb, FALSE, GDK_End, GDK_BUTTON1_MASK, view); create_view_menu_item (subsubmenu, _("Go to end of file"), "/Playback/Transport/Go to end of file", view, goto_end_cb, FALSE, GDK_End, GDK_CONTROL_MASK, view); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); menuitem = create_view_menu_item (submenu, _("Play selection"), "/Playback/Transport/Play selection", view, play_view_sel_cb, FALSE, GDK_space, GDK_BUTTON1_MASK, view); NOALLOC(menuitem); menuitem = create_view_menu_item (submenu, _("Play sample"), "/Playback/Transport/Play sample", view, play_view_cb, FALSE, GDK_space, GDK_CONTROL_MASK, view); NOALLOC(menuitem); menuitem = gtk_menu_item_new_with_label(_("Play note")); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); subsubmenu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), subsubmenu); NOALLOC(menuitem); /* ** This sets up menu items and callbacks for all the note play ** and is quite a bit neater than the old stuff. */ noteplay_setup (subsubmenu, view, accel_group); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); menuitem = gtk_check_menu_item_new_with_label(_("Toggle monitoring")); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menuitem), view->sample->play_head->monitor); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(monitor_toggle_cb), view); gtk_menu_item_set_accel_path (GTK_MENU_ITEM(menuitem), "/Playback/Transport/Toggle monitoring"); gtk_widget_show(menuitem); view->monitor_checkmenu = menuitem; menuitem = gtk_check_menu_item_new_with_label(_("Toggle looping")); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menuitem), view->sample->play_head->looping); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(loop_toggle_cb), view); gtk_menu_item_set_accel_path (GTK_MENU_ITEM(menuitem), "/Playback/Transport/Toggle looping"); gtk_widget_show(menuitem); view->loop_checkmenu = menuitem; menuitem = gtk_check_menu_item_new_with_label(_("Toggle muting")); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menuitem), view->sample->play_head->mute); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(mute_toggle_cb), view); gtk_menu_item_set_accel_path (GTK_MENU_ITEM(menuitem), "/Playback/Transport/Toggle muting"); gtk_widget_show(menuitem); view->mute_checkmenu = menuitem; menuitem = gtk_check_menu_item_new_with_label(_("Toggle reverse playback")); gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menuitem), view->sample->play_head->reverse); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(playrev_toggle_cb), view); gtk_widget_show(menuitem); gtk_menu_item_set_accel_path (GTK_MENU_ITEM(menuitem), "/Playback/Transport/Toggle reverse playback"); gtk_accel_map_add_entry ("/Playback/Transport/Toggle reverse playback", GDK_quoteleft, GDK_BUTTON1_MASK); view->playrev_checkmenu = menuitem; menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); menuitem = create_view_menu_item (submenu, _("Pause"), "/Playback/Pause", view, pause_playback_cb, FALSE, 0, 0, view); NOALLOC(menuitem); menuitem = create_view_menu_item (submenu, _("Stop"), "/Playback/Stop", view, stop_playback_cb, FALSE, GDK_Return, GDK_BUTTON1_MASK, view); NOALLOC(menuitem); menuitem = gtk_menu_item_new_with_label (_("Help")); MENU_APPEND(m, menuitem); gtk_widget_show(menuitem); submenu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), submenu); menuitem = gtk_menu_item_new_with_label (_("About MP3 export...")); gtk_menu_append (GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(mp3_unsupported_dialog), NULL); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label (_("About Sweep ...")); gtk_menu_append (GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(about_dialog_create), NULL); gtk_widget_show(menuitem); return accel_group; } /* * create_context_menu_sel (view) * * Creates a context menu for operations on a selection */ static GtkWidget * create_context_menu_sel (sw_view * view) { GtkWidget * menu; GtkWidget * menuitem; GtkWidget * submenu; SampleDisplay * s = SAMPLE_DISPLAY(view->display); menu = gtk_menu_new (); /* Zoom */ menuitem = gtk_menu_item_new_with_label(_("Zoom to selection")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(zoom_to_sel_cb), s); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Zoom normal")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(zoom_norm_cb), s); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Zoom all")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(zoom_all_cb), view); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(menu), menuitem); gtk_widget_show(menuitem); /* Edit */ menuitem = gtk_menu_item_new_with_label(_("Edit")); gtk_menu_append (GTK_MENU(menu), menuitem); gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); NOMODIFY(menuitem); menuitem = gtk_menu_item_new_with_label(_("Cut")); gtk_menu_append(GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(cut_cb), view); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Copy")); gtk_menu_append(GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(copy_cb), view); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Clear")); gtk_menu_append(GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(clear_cb), view); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Crop")); gtk_menu_append(GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(crop_cb), view); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(submenu), menuitem); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Paste: Insert")); gtk_menu_append(GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(paste_cb), view); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Paste: Mix")); gtk_menu_append(GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(paste_mix_cb), view); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Paste: Crossfade")); gtk_menu_append(GTK_MENU(submenu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(paste_xfade_cb), view); gtk_widget_show(menuitem); /* Filters */ menuitem = gtk_menu_item_new_with_label(_("Process")); gtk_menu_append (GTK_MENU(menu), menuitem); gtk_widget_show(menuitem); submenu = create_proc_menu (view, NULL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); NOMODIFY(menuitem); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(menu), menuitem); gtk_widget_show(menuitem); /* Select */ menuitem = gtk_menu_item_new_with_label(_("Invert selection")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(select_invert_cb), s); gtk_widget_show(menuitem); NOMODIFY(menuitem); menuitem = gtk_menu_item_new_with_label(_("Select all")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(select_all_cb), s); gtk_widget_show(menuitem); NOMODIFY(menuitem); menuitem = gtk_menu_item_new_with_label(_("Select none")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(select_none_cb), s); gtk_widget_show(menuitem); NOMODIFY(menuitem); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(menu), menuitem); gtk_widget_show(menuitem); /* View */ menuitem = gtk_menu_item_new_with_label(_("New View")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(view_new_cb), s); gtk_widget_show(menuitem); return menu; } /* * create_context_menu_point (view) * * Creates a context menu for point (cursor) operations, ie. when * no selection is active */ static GtkWidget * create_context_menu_point (sw_view * view) { GtkWidget * menu; GtkWidget * menuitem; SampleDisplay * s = SAMPLE_DISPLAY(view->display); menu = gtk_menu_new (); /* Zoom */ menuitem = gtk_menu_item_new_with_label(_("Zoom normal")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(zoom_norm_cb), s); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new_with_label(_("Zoom all")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(zoom_all_cb), view); gtk_widget_show(menuitem); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(menu), menuitem); gtk_widget_show(menuitem); /* Edit */ menuitem = gtk_menu_item_new_with_label(_("Paste")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(paste_cb), view); gtk_widget_show(menuitem); NOMODIFY(menuitem); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(menu), menuitem); gtk_widget_show(menuitem); /* Select */ menuitem = gtk_menu_item_new_with_label(_("Select all")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(select_all_cb), s); gtk_widget_show(menuitem); NOMODIFY(menuitem); menuitem = gtk_menu_item_new(); /* Separator */ gtk_menu_append(GTK_MENU(menu), menuitem); gtk_widget_show(menuitem); /* View */ menuitem = gtk_menu_item_new_with_label(_("New View")); gtk_menu_append(GTK_MENU(menu), menuitem); g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(view_new_cb), s); gtk_widget_show(menuitem); return menu; } static gint view_destroy_cb (GtkWidget * widget, gpointer data) { sw_view * view = (sw_view *)data; sample_display_stop_marching_ants (SAMPLE_DISPLAY(view->display)); if (view->sample->op_progress_tag != -1) g_source_remove(view->sample->op_progress_tag); view->sample->op_progress_tag = -1; cancel_active_op (view->sample); sample_remove_view(view->sample, view); gtk_widget_destroy (GTK_WIDGET (view->display)); return (FALSE); } static void db_ruler_changed_cb (GtkWidget * widget, gpointer data) { GtkRuler * ruler = GTK_RULER(widget); sw_view * view = (sw_view *)data; view_set_vzoom (view, ruler->lower, ruler->upper); } static void view_refresh_db_rulers (sw_view * view) { int i, old_channels, new_channels; GtkWidget * vbox = view->db_rulers_vbox; GList * gl; GtkWidget * db_ruler; old_channels = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(vbox), "default")); new_channels = view->sample->sounddata->format->channels; if (old_channels == 0 || old_channels != new_channels) { for (gl = view->db_rulers; gl; gl = gl->next) { g_signal_handlers_disconnect_matched(GTK_OBJECT(view->window), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, gl->data); gtk_widget_destroy (GTK_WIDGET(gl->data)); } g_list_free (view->db_rulers); view->db_rulers = NULL; g_object_set_data (G_OBJECT(vbox), "default", GINT_TO_POINTER(new_channels)); for (i = 0; i < new_channels; i++) { db_ruler = db_ruler_new (); gtk_box_pack_start (GTK_BOX(vbox), db_ruler, TRUE, TRUE, 0); gtk_ruler_set_range (GTK_RULER(db_ruler), -1.0, 1.0, 0, 2.0); gtk_widget_show (db_ruler); g_signal_connect_swapped(GTK_OBJECT(view->window), "motion_notify_event", G_CALLBACK(GTK_WIDGET_GET_CLASS(db_ruler)->motion_notify_event), GTK_OBJECT (db_ruler)); g_signal_connect (G_OBJECT(db_ruler), "changed", G_CALLBACK(db_ruler_changed_cb), view); view->db_rulers = g_list_append (view->db_rulers, db_ruler); } } for (gl = view->db_rulers; gl; gl = gl->next) { db_ruler = GTK_WIDGET(gl->data); gtk_ruler_set_range (GTK_RULER(db_ruler), view->vlow, view->vhigh, 0, 2.0); } } static void view_rate_changed_cb (GtkWidget * widget, gpointer data) { sw_view * v = (sw_view *)data; sw_sample * s = v->sample; s->rate = 1.0 - GTK_ADJUSTMENT(v->rate_adj)->value/1000.0; } static void view_rate_zeroed_cb (GtkWidget * Widget, gpointer data) { sw_view * v = (sw_view *)data; sw_sample * s = v->sample; s->rate = 1.0; gtk_adjustment_set_value (GTK_ADJUSTMENT(v->rate_adj), 0.0); } static void view_gain_changed_cb (GtkWidget * widget, gpointer data) { sw_view * v = (sw_view *)data; head_set_gain (v->sample->play_head, GTK_ADJUSTMENT (v->gain_adj)->value / 10.0); } static void view_set_pos_indicator_cb (GtkWidget * widget, gpointer data) { char buf[16]; SampleDisplay * sd = SAMPLE_DISPLAY(data); sw_view * view = sd->view; if (sd->mouse_offset >= 0) { snprint_time (buf, sizeof (buf), frames_to_time (view->sample->sounddata->format, sd->mouse_offset)); gtk_label_set_text (GTK_LABEL(view->pos), buf); } else { gtk_label_set_text (GTK_LABEL(view->pos), NO_TIME); } } static gint menu_button_handler (GtkWidget * widget, GdkEvent * event) { GtkMenu * menu; GdkEventButton *event_button; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_MENU (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); menu = GTK_MENU (widget); if (event->type == GDK_BUTTON_PRESS) { event_button = (GdkEventButton *) event; gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event_button->button, event_button->time); return TRUE; } return FALSE; } #define VIEW_TOOLBAR_BUTTON SW_TOOLBAR_BUTTON #define VIEW_TOOLBAR_TOGGLE_BUTTON SW_TOOLBAR_TOGGLE_BUTTON #define VIEW_TOOLBAR_RADIO_BUTTON SW_TOOLBAR_RADIO_BUTTON static void scrub_clicked_cb (GtkWidget * widget, GdkEventButton * event, gpointer data) { sw_view * view = (sw_view *)data; int width; sw_framecount_t offset; width = widget->allocation.width; offset = view->start + (view->end - view->start) * event->x / width; sample_set_playmarker (view->sample, offset, TRUE); sample_set_scrubbing (view->sample, TRUE); } static void scrub_motion_cb (GtkWidget * widget, GdkEventMotion * event, gpointer data) { sw_view * view = (sw_view *)data; int width; sw_framecount_t offset; gdk_window_set_cursor (widget->window, sweep_cursors[SWEEP_CURSOR_NEEDLE]); if (event->state & (GDK_BUTTON1_MASK|GDK_BUTTON2_MASK|GDK_BUTTON3_MASK)) { width = widget->allocation.width; offset = view->start + (view->end - view->start) * event->x / width; sample_set_playmarker (view->sample, offset, TRUE); } } static void scrub_released_cb (GtkWidget * widget, GdkEventButton * event, gpointer data) { sw_view * view = (sw_view *)data; sample_set_scrubbing (view->sample, FALSE); } static void vzoom_clicked_cb (GtkWidget * widget, GdkEventButton * event, gpointer data) { /* sw_view * view = (sw_view *)data;*/ } static void vzoom_motion_cb (GtkWidget * widget, GdkEventMotion * event, gpointer data) { /* sw_view * view = (sw_view *)data;*/ } static void vzoom_released_cb (GtkWidget * widget, GdkEventButton * event, gpointer data) { /* sw_view * view = (sw_view *)data;*/ } sw_view * view_new(sw_sample * sample, sw_framecount_t start, sw_framecount_t end, gfloat gain) { sw_view * view; gint screen_width, screen_height; gint win_width, win_height; GtkWidget * window; GtkWidget * main_vbox; GtkWidget * table; GtkWidget * hbox; GtkWidget * vbox; GtkWidget * handlebox; GtkWidget * separator; GtkWidget * ebox; GtkWidget * time_ruler; GtkWidget * scrollbar; GtkWidget * rate_vbox; GtkObject * rate_adj; GtkWidget * rate_vscale; GtkWidget * lcdbox; GtkWidget * imagebox; GtkObject * gain_adj; GtkWidget * tool_hbox; GtkWidget * gain_hscale; GtkWidget * menu_button; GtkWidget * button; GtkWidget * arrow; GtkWidget * pixmap; GtkWidget * progress; GtkWidget * frame; GtkWidget * label; #ifdef DEVEL_CODE GtkWidget * notebook; #endif GtkAccelGroup * accel_group; GtkTooltips * tooltips; GList * zoom_combo_items; GtkWidget * zoom_combo; gfloat step = 1.0; view = g_malloc0 (sizeof(sw_view)); view->sample = sample; view->start = start; view->end = end; view->vlow = SW_AUDIO_T_MIN; view->vhigh = SW_AUDIO_T_MAX; /* view->gain = gain;*/ view->current_tool = TOOL_SELECT; view->repeater_tag = 0; view->following = TRUE; view->noready_widgets = NULL; view->nomodify_widgets = NULL; view->noalloc_widgets = NULL; view->channelops_widgets = NULL; screen_width = gdk_screen_width (); screen_height = gdk_screen_height (); if (sample->views == NULL) { win_height = screen_height / 4; } else { win_height = screen_height / 8; } win_width = (win_height * 2 * 1618) / 1000; win_height *= MIN (2, sample->sounddata->format->channels); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); sweep_set_window_icon (GTK_WINDOW(window)); gtk_window_set_default_size (GTK_WINDOW(window), win_width, win_height); view->window = window; g_signal_connect (G_OBJECT(window), "destroy", G_CALLBACK(view_destroy_cb), view); main_vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER(window), main_vbox); gtk_widget_show (main_vbox); handlebox = gtk_handle_box_new (); gtk_box_pack_start (GTK_BOX (main_vbox), handlebox, FALSE, TRUE, 0); gtk_widget_show (handlebox); view->menubar = gtk_menu_bar_new (); gtk_container_add (GTK_CONTAINER (handlebox), view->menubar); gtk_widget_show (view->menubar); /* file toolbar */ handlebox = gtk_handle_box_new (); gtk_handle_box_set_shadow_type (GTK_HANDLE_BOX(handlebox), GTK_SHADOW_NONE); gtk_box_pack_start (GTK_BOX (main_vbox), handlebox, FALSE, TRUE, 0); gtk_widget_show (handlebox); /* gtk_widget_set_style (handlebox, style_dark_grey);*/ hbox = gtk_hbox_new (FALSE, 8); gtk_container_add (GTK_CONTAINER (handlebox), hbox); gtk_widget_show (hbox); gtk_widget_set_size_request (hbox, -1, 26); separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 2); gtk_widget_show (separator); /* File op buttons */ tool_hbox = gtk_hbox_new (TRUE, 2); gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0); gtk_widget_show (tool_hbox); button = create_pixmap_button (window, new_xpm, _("New ..."), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (sample_new_empty_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); button = create_pixmap_button (window, open_xpm, _("Open ..."), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (sample_load_cb), NULL, NULL, window); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); button = create_pixmap_button (window, save_xpm, _("Save"), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (sample_save_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); button = create_pixmap_button (window, saveas_xpm, _("Save as ..."), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (sample_save_as_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 2); gtk_widget_show (separator); /* Edit buttons */ tool_hbox = gtk_hbox_new (TRUE, 2); gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0); gtk_widget_show (tool_hbox); button = create_pixmap_button (window, cut_xpm, _("Cut selection to clipboard"), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (cut_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); button = create_pixmap_button (window, copy_xpm, _("Copy selection to clipboard"), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (copy_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); button = create_pixmap_button (window, paste_xpm, _("Paste: insert clipboard at cursor position"), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (paste_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); button = create_pixmap_button (window, pastemix_xpm, _("Paste: mix clipboard in from cursor position"), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (paste_mix_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); button = create_pixmap_button (window, pastexfade_xpm, _("Paste: fade clipboard in from cursor position"), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (paste_xfade_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 2); gtk_widget_show (separator); button = create_pixmap_button (window, crop_xpm, _("Crop"), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (crop_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 2); gtk_widget_show (separator); /* Undo/Redo */ tool_hbox = gtk_hbox_new (TRUE, 2); gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0); gtk_widget_show (tool_hbox); button = create_pixmap_button (window, undo_xpm, _("Undo"), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (undo_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); button = create_pixmap_button (window, redo_xpm, _("Redo"), NULL, VIEW_TOOLBAR_BUTTON, G_CALLBACK (redo_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOMODIFY(button); separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 4); gtk_widget_show (separator); /* TOOLS */ ebox = gtk_event_box_new (); gtk_box_pack_start (GTK_BOX (hbox), ebox, FALSE, FALSE, 0); gtk_widget_show (ebox); gtk_widget_set_style (ebox, style_light_grey); tool_hbox = gtk_hbox_new (TRUE, 4); gtk_container_add (GTK_CONTAINER(ebox), tool_hbox); gtk_widget_show (tool_hbox); view->tool_buttons = NULL; button = create_pixmap_button (window, hand_xpm, _("Hand tool"), style_light_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (view_set_tool_cb), NULL, NULL, view); g_object_set_data (G_OBJECT(button), "default", GINT_TO_POINTER(TOOL_HAND)); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, FALSE, 0); gtk_widget_show (button); view->tool_buttons = g_list_append (view->tool_buttons, button); button = create_pixmap_button (window, select_xpm, _("Selector tool"), style_light_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (view_set_tool_cb), NULL, NULL, view); g_object_set_data (G_OBJECT(button), "default", GINT_TO_POINTER(TOOL_SELECT)); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, FALSE, 0); gtk_widget_show (button); view->tool_buttons = g_list_append (view->tool_buttons, button); NOMODIFY(button); button = create_pixmap_button (window, scrub_xpm, _("\"Scrubby\" the scrub tool"), style_light_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (view_set_tool_cb), NULL, NULL, view); g_object_set_data (G_OBJECT(button), "default", GINT_TO_POINTER(TOOL_SCRUB)); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, FALSE, 0); gtk_widget_show (button); view->tool_buttons = g_list_append (view->tool_buttons, button); #ifdef DEVEL_CODE /* Pencil & Noise -- these need undos */ button = create_pixmap_button (window, pencil_xpm, _("Pencil tool"), style_light_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (view_set_tool_cb), NULL, NULL, view); g_object_set_data (G_OBJECT(button), "default", GINT_TO_POINTER(TOOL_PENCIL)); gtk_box_pack_start (GTK_BOX (tool_hbox), button, TRUE, TRUE, 0); gtk_widget_show (button); view->tool_buttons = g_list_append (view->tool_buttons, button); button = create_pixmap_button (window, spraycan_xpm, _("Noise tool"), style_light_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (view_set_tool_cb), NULL, NULL, view); g_object_set_data (G_OBJECT(button), "default", GINT_TO_POINTER(TOOL_NOISE)); gtk_box_pack_start (GTK_BOX (tool_hbox), button, TRUE, TRUE, 0); gtk_widget_show (button); view->tool_buttons = g_list_append (view->tool_buttons, button); #endif separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 4); gtk_widget_show (separator); /* ZOOM */ tool_hbox = gtk_hbox_new (FALSE, 2); gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0); gtk_widget_show (tool_hbox); gtk_widget_set_style (tool_hbox, style_dark_grey); /* Zoom in */ button = create_pixmap_button (window, zoom_in_xpm, _("Zoom in"), NULL, VIEW_TOOLBAR_BUTTON, NULL, G_CALLBACK (zoom_in_pressed_cb), G_CALLBACK (repeater_released_cb), view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); /* Zoom out */ button = create_pixmap_button (window, zoom_out_xpm, _("Zoom out"), NULL, VIEW_TOOLBAR_BUTTON, NULL, G_CALLBACK (zoom_out_pressed_cb), G_CALLBACK (repeater_released_cb), view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); /* Zoom combo */ zoom_combo_items = NULL; zoom_combo_items = g_list_append (zoom_combo_items, "All"); zoom_combo_items = g_list_append (zoom_combo_items, "01:00:00.000"); zoom_combo_items = g_list_append (zoom_combo_items, "00:30:00.000"); zoom_combo_items = g_list_append (zoom_combo_items, "00:05:00.000"); zoom_combo_items = g_list_append (zoom_combo_items, "00:01:00.000"); zoom_combo_items = g_list_append (zoom_combo_items, "00:00:30.000"); zoom_combo_items = g_list_append (zoom_combo_items, "00:00:15.000"); zoom_combo_items = g_list_append (zoom_combo_items, "00:00:05.000"); zoom_combo_items = g_list_append (zoom_combo_items, "00:00:01.000"); zoom_combo_items = g_list_append (zoom_combo_items, "00:00:00.500"); zoom_combo_items = g_list_append (zoom_combo_items, "00:00:00.100"); zoom_combo_items = g_list_append (zoom_combo_items, "00:00:00.010"); zoom_combo_items = g_list_append (zoom_combo_items, "00:00:00.001"); zoom_combo = gtk_combo_new (); /* connect hack_max_combo_width_cb to the theme change signal so zoom_combo is * kept at an appropriate size regardless of font or theme changes. * * replace with gtk_entry_set_width_chars() when GTK+-2.6 is used by mainstream distro's */ g_signal_connect (G_OBJECT(GTK_COMBO(zoom_combo)->entry), "style_set", G_CALLBACK(hack_max_combo_width_cb), NULL); gtk_combo_set_popdown_strings (GTK_COMBO(zoom_combo), zoom_combo_items); gtk_combo_set_value_in_list (GTK_COMBO(zoom_combo), FALSE, TRUE); /* unfortunately we can't just edit the zoom value, because the entry * reports every keystroke as a change, and not the 'enter' key. */ gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO(zoom_combo)->entry), TRUE); /*gtk_widget_set_style (GTK_COMBO(zoom_combo)->button, style_dark_grey);*/ g_signal_connect (G_OBJECT(GTK_COMBO(zoom_combo)->entry), "changed", G_CALLBACK(zoom_combo_changed_cb), view); tooltips = gtk_tooltips_new (); gtk_tooltips_set_tip (tooltips, GTK_COMBO(zoom_combo)->button, _("Visible length"), NULL); view->zoom_combo = zoom_combo; gtk_box_pack_start (GTK_BOX (tool_hbox), view->zoom_combo, FALSE, FALSE, 0); gtk_widget_show (zoom_combo); button = create_pixmap_button (window, scroll_xpm, _("Autoscroll: follow playback cursor"), NULL, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (follow_toggled_cb), NULL, NULL, view); gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_widget_set_style (button, style_light_grey); gtk_signal_handler_block_by_data (GTK_OBJECT(button), view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), view->following); g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); view->follow_toggle = button; #ifdef DEVEL_CODE button = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX(main_vbox), button, FALSE, TRUE, 0); gtk_widget_show (button); /* notebook */ notebook = gtk_notebook_new (); gtk_box_pack_start (GTK_BOX(main_vbox), notebook, TRUE, TRUE, 0); gtk_widget_show (notebook); gtk_widget_set_style (notebook, style_light_grey); gtk_container_set_border_width (GTK_CONTAINER(notebook), 0); if (TRUE) { gtk_notebook_set_show_tabs (GTK_NOTEBOOK(notebook), TRUE); } #endif /* main table */ table = gtk_table_new (3, 3, FALSE); gtk_table_set_col_spacing (GTK_TABLE(table), 0, 1); gtk_table_set_col_spacing (GTK_TABLE(table), 1, 2); gtk_table_set_row_spacing (GTK_TABLE(table), 0, 1); gtk_table_set_row_spacing (GTK_TABLE(table), 1, 2); gtk_container_set_border_width (GTK_CONTAINER(table), 2); #ifdef DEVEL_CODE label = gtk_label_new (g_basename(sample->pathname)); gtk_notebook_append_page (GTK_NOTEBOOK(notebook), table, label); #else gtk_box_pack_start (GTK_BOX(main_vbox), table, TRUE, TRUE, 0); #endif gtk_widget_show (table); /* menu button */ menu_button = gtk_button_new (); gtk_table_attach (GTK_TABLE(table), menu_button, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (menu_button); arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE); gtk_container_add (GTK_CONTAINER (menu_button), arrow); gtk_widget_show (arrow); /* time_ruler */ ebox = gtk_event_box_new (); gtk_table_attach (GTK_TABLE(table), ebox, 1, 2, 0, 1, GTK_EXPAND|GTK_FILL|GTK_SHRINK, GTK_FILL, 0, 0); g_signal_connect (G_OBJECT(ebox), "button-press-event", G_CALLBACK(scrub_clicked_cb), view); g_signal_connect (G_OBJECT(ebox), "motion-notify-event", G_CALLBACK(scrub_motion_cb), view); g_signal_connect (G_OBJECT(ebox), "button-release-event", G_CALLBACK(scrub_released_cb), view); gtk_widget_show (ebox); time_ruler = time_ruler_new (); gtk_container_add (GTK_CONTAINER(ebox), time_ruler); gtk_ruler_set_range (GTK_RULER(time_ruler), start, end, start, end); time_ruler_set_format (TIME_RULER(time_ruler), sample->sounddata->format); gtk_widget_show (time_ruler); view->time_ruler = time_ruler; /* tmp GTK__GET_CLASS (object) */ g_signal_connect_swapped (GTK_OBJECT (table), "motion_notify_event", G_CALLBACK(GTK_WIDGET_GET_CLASS(time_ruler)->motion_notify_event), GTK_OBJECT (time_ruler)); /* db_ruler */ ebox = gtk_event_box_new (); gtk_table_attach (GTK_TABLE(table), ebox, 0, 1, 1, 2, GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0); g_signal_connect (G_OBJECT(ebox), "button-press-event", G_CALLBACK(vzoom_clicked_cb), view); g_signal_connect (G_OBJECT(ebox), "motion-notify-event", G_CALLBACK(vzoom_motion_cb), view); g_signal_connect (G_OBJECT(ebox), "button-release-event", G_CALLBACK(vzoom_released_cb), view); gtk_widget_show (ebox); tooltips = gtk_tooltips_new (); gtk_tooltips_set_tip (tooltips, ebox, _("Vertical zoom [Shift + Arrow Up/Down]"), NULL); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER(ebox), vbox); gtk_widget_show (vbox); view->db_rulers_vbox = vbox; view->db_rulers = NULL; view_refresh_db_rulers (view); /* display */ view->display = sample_display_new(); gtk_table_attach (GTK_TABLE(table), view->display, 1, 2, 1, 2, GTK_EXPAND|GTK_FILL|GTK_SHRINK, GTK_EXPAND|GTK_FILL|GTK_SHRINK, 0, 0); sample_display_set_view(SAMPLE_DISPLAY(view->display), view); g_signal_connect (G_OBJECT(view->display), "selection-changed", G_CALLBACK(sd_sel_changed_cb), view); g_signal_connect (G_OBJECT(view->display), "window-changed", G_CALLBACK(sd_win_changed_cb), view); gtk_widget_show(view->display); /* rate adjuster */ rate_vbox = gtk_vbox_new (FALSE, 0); gtk_table_attach (GTK_TABLE(table), rate_vbox, 2, 3, 1, 2, GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0); gtk_widget_show (rate_vbox); label = gtk_label_new ("+10%"); gtk_box_pack_start (GTK_BOX(rate_vbox), label, FALSE, FALSE, 0); gtk_widget_show (label); rate_adj = gtk_adjustment_new (0.0, /* value */ -100.0, /* lower */ 100.0, /* upper */ 2.5, /* step incr */ 20.0, /* page incr */ 0.0 /* page size */ ); /* view->rate = 1.0;*/ view->rate_adj = rate_adj; rate_vscale = gtk_vscale_new (GTK_ADJUSTMENT(rate_adj)); gtk_box_pack_start (GTK_BOX(rate_vbox), rate_vscale, TRUE, TRUE, 0); gtk_scale_set_draw_value (GTK_SCALE(rate_vscale), FALSE); gtk_range_set_update_policy (GTK_RANGE(rate_vscale), GTK_UPDATE_CONTINUOUS); gtk_widget_show (rate_vscale); g_signal_connect (G_OBJECT(rate_adj), "value_changed", G_CALLBACK(view_rate_changed_cb), view); label = gtk_label_new ("-10%"); gtk_box_pack_start (GTK_BOX(rate_vbox), label, FALSE, FALSE, 0); gtk_widget_show (label); button = gtk_button_new_with_label ("0%"); gtk_box_pack_start (GTK_BOX(rate_vbox), button, FALSE, FALSE, 0); gtk_widget_show (button); g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(view_rate_zeroed_cb), view); /* scrollbar */ step = ((gfloat)(end - start)) / 10.0; if (step < 1.0) step = 1.0; view->adj = gtk_adjustment_new((gfloat)start, /* value */ (gfloat)0.0, /* start */ (gfloat)sample->sounddata->nr_frames, /* end */ step, /* step_incr */ (gfloat)(end-start), /* page_incr */ (gfloat)(end-start) /* page_size */ ); g_signal_connect (G_OBJECT(view->adj), "value-changed", G_CALLBACK(adj_value_changed_cb), view); g_signal_connect (G_OBJECT(view->adj), "changed", G_CALLBACK(adj_changed_cb), view); scrollbar = gtk_hscrollbar_new(GTK_ADJUSTMENT(view->adj)); gtk_table_attach (GTK_TABLE(table), scrollbar, 1, 2, 2, 3, GTK_EXPAND|GTK_FILL|GTK_SHRINK, GTK_FILL, 0, 0); gtk_widget_show(scrollbar); /* playback toolbar */ handlebox = gtk_handle_box_new (); gtk_box_pack_start (GTK_BOX (main_vbox), handlebox, FALSE, TRUE, 0); gtk_widget_show (handlebox); gtk_widget_set_style (handlebox, style_light_grey); hbox = gtk_hbox_new (FALSE, 8); gtk_container_add (GTK_CONTAINER (handlebox), hbox); gtk_widget_show (hbox); gtk_widget_set_usize (hbox, -1, 24); /* Record */ tool_hbox = gtk_hbox_new (TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0); gtk_widget_show (tool_hbox); button = create_pixmap_button (window, record_dialog_xpm, _("Record ..."), style_red_grey, VIEW_TOOLBAR_BUTTON, G_CALLBACK (show_rec_dialog_cb), NULL, NULL, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOALLOC(button); #define PLAYPOS_LABEL #ifdef PLAYPOS_LABEL frame = gtk_frame_new (NULL); gtk_widget_set_style (frame, style_light_grey); gtk_box_pack_start (GTK_BOX(hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); lcdbox = gtk_event_box_new (); gtk_widget_set_style (lcdbox, style_LCD); gtk_container_add (GTK_CONTAINER(frame), lcdbox); gtk_widget_show (lcdbox); tooltips = gtk_tooltips_new (); gtk_tooltips_set_tip (tooltips, lcdbox, _("Cursor position (indicator)"), NULL); tool_hbox = gtk_hbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER(lcdbox), tool_hbox); gtk_widget_show (tool_hbox); imagebox = gtk_vbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX(tool_hbox), imagebox, FALSE, FALSE, 0); gtk_widget_show (imagebox); pixmap = create_widget_from_xpm (window, upleft_xpm); gtk_widget_show (pixmap); gtk_box_pack_start (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0); pixmap = create_widget_from_xpm (window, lowleft_xpm); gtk_widget_show (pixmap); gtk_box_pack_end (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0); label = gtk_label_new ("00:00:00.000"); gtk_box_pack_start (GTK_BOX(tool_hbox), label, TRUE, TRUE, 0); gtk_widget_show (label); view->play_pos = label; imagebox = gtk_vbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX(tool_hbox), imagebox, FALSE, FALSE, 0); gtk_widget_show (imagebox); pixmap = create_widget_from_xpm (window, upright_xpm); gtk_widget_show (pixmap); gtk_box_pack_start (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0); pixmap = create_widget_from_xpm (window, lowright_xpm); gtk_widget_show (pixmap); gtk_box_pack_end (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0); #else entry = gtk_entry_new (); gtk_entry_set_text (GTK_ENTRY(entry), "00:00:00.000"); gtk_entry_set_editable (GTK_ENTRY(entry), FALSE); gtk_widget_set_style (entry, style_LCD); gtk_box_pack_start (GTK_BOX(hbox), entry, TRUE, TRUE, 0); gtk_widget_show (entry); view->play_pos = entry; #endif tool_hbox = gtk_hbox_new (TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0); gtk_widget_show (tool_hbox); /* Play reverse */ button = create_pixmap_button (window, playrev_xpm, _("Reverse mode playback (toggle)"), style_green_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (playrev_toggled_cb), NULL, NULL, view); g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), view->sample->play_head->reverse); g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); view->playrev_toggle = button; /* Loop */ button = create_pixmap_button (window, loop_xpm, _("Loop mode playback (toggle)"), style_green_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (loop_toggled_cb), NULL, NULL, view); g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), view->sample->play_head->looping); g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); view->loop_toggle = button; /* Play */ tool_hbox = gtk_hbox_new (TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, TRUE, TRUE, 0); gtk_widget_show (tool_hbox); button = create_pixmap_button (window, playpaus_xpm, /* _("Play all / Pause [Ctrl+Space / Enter]"),*/ _("Play all / Pause"), style_green_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (play_view_button_cb), NULL, NULL, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOALLOC(button); view->play_toggle = button; /* Play selection */ button = create_pixmap_button (window, playpsel_xpm, /*_("Play selection / Pause [Space / Enter]"),*/ _("Play selection / Pause"), style_green_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (play_view_sel_button_cb), NULL, NULL, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOALLOC(button); view->play_sel_toggle = button; /* Stop */ button = create_pixmap_button (window, stop_xpm, /*_("Stop playback [Space]"),*/ _("Stop playback"), style_green_grey, VIEW_TOOLBAR_BUTTON, G_CALLBACK (stop_playback_cb), NULL, NULL, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOALLOC(button); /* Beginning */ tool_hbox = gtk_hbox_new (TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0); gtk_widget_show (tool_hbox); button = create_pixmap_button (window, prevtrk_xpm, _("Go to beginning"), style_green_grey, VIEW_TOOLBAR_BUTTON, G_CALLBACK (goto_start_cb), NULL, NULL, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOALLOC(button); /* Rewind */ button = create_pixmap_button (window, rew_xpm, _("Rewind"), style_green_grey, VIEW_TOOLBAR_BUTTON, NULL, G_CALLBACK (rewind_pressed_cb), G_CALLBACK (repeater_released_cb), view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOALLOC(button); /* Fast forward */ button = create_pixmap_button (window, ff_xpm, _("Fast forward"), style_green_grey, VIEW_TOOLBAR_BUTTON, NULL, G_CALLBACK (ffwd_pressed_cb), G_CALLBACK (repeater_released_cb), view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOALLOC(button); /* End */ button = create_pixmap_button (window, nexttrk_xpm, _("Go to the end"), style_green_grey, VIEW_TOOLBAR_BUTTON, G_CALLBACK (goto_end_cb), NULL, NULL, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); NOALLOC(button); /* gain */ tool_hbox = gtk_hbox_new (FALSE, 2); gtk_widget_show (tool_hbox); button = create_pixmap_button (window, mute_xpm, _("Muted playback (toggle)"), style_green_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (mute_toggled_cb), NULL, NULL, view); g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), view->sample->play_head->mute); g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); gtk_widget_show (button); view->mute_toggle = button; pixmap = create_widget_from_xpm (window, vol_xpm); gtk_box_pack_start (GTK_BOX (tool_hbox), pixmap, FALSE, FALSE, 0); gtk_widget_show (pixmap); tooltips = gtk_tooltips_new (); gtk_tooltips_set_tip (tooltips, pixmap, _("Playback gain slider (volume)"), NULL); gain_adj = gtk_adjustment_new (view->sample->play_head->gain*10.0,/* value */ 0.0, /* lower */ 10.0, /* upper */ 0.17, /* step incr */ 1.6, /* page incr */ 0.0 /* page size */ ); view->gain_adj = gain_adj; gain_hscale = gtk_hscale_new (GTK_ADJUSTMENT(gain_adj)); gtk_scale_set_draw_value (GTK_SCALE(gain_hscale), FALSE); gtk_range_set_update_policy (GTK_RANGE(gain_hscale), GTK_UPDATE_CONTINUOUS); gtk_widget_show (gain_hscale); tooltips = gtk_tooltips_new (); gtk_tooltips_set_tip (tooltips, gain_hscale, _("Playback gain slider (volume)"), NULL); gtk_widget_set_style (gain_hscale, style_green_grey); g_signal_connect (G_OBJECT(gain_adj), "value_changed", G_CALLBACK(view_gain_changed_cb), view); gtk_box_pack_start (GTK_BOX(tool_hbox), gain_hscale, TRUE, TRUE, 0); /* Monitor */ button = create_pixmap_button (window, headphones_xpm, _("Monitor (toggle)"), style_green_grey, VIEW_TOOLBAR_TOGGLE_BUTTON, G_CALLBACK (monitor_toggled_cb), NULL, NULL, view); g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), view->sample->play_head->monitor); g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_box_pack_start (GTK_BOX (tool_hbox), button, TRUE, TRUE, 0); gtk_widget_show (button); view->monitor_toggle = button; NOALLOC(button); /* SYNC */ button = gtk_button_new_with_label (_("SYNC")); gtk_widget_set_style (button, style_green_grey); gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0); /*gtk_widget_show (button);*/ NOALLOC(button); gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, TRUE, TRUE, 0); /* Status line */ hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); /* position indicator */ frame = gtk_frame_new (NULL); gtk_box_pack_start (GTK_BOX(hbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); tool_hbox = gtk_hbox_new (FALSE, 2); gtk_container_add (GTK_CONTAINER(frame), tool_hbox); gtk_widget_show (tool_hbox); pixmap = create_widget_from_xpm (window, mouse_xpm); gtk_box_pack_start (GTK_BOX(tool_hbox), pixmap, FALSE, FALSE, 0); gtk_widget_show (pixmap); label = gtk_label_new (NO_TIME); gtk_box_pack_start (GTK_BOX(tool_hbox), label, FALSE, FALSE, 0); /* connect hack_max_label_width_cb to the theme change signal so label is * kept at an appropriate size regardless of font or theme changes. * * replace with gtk_label_set_width_chars() when GTK+-2.6 is used by mainstream distro's */ g_signal_connect (G_OBJECT(label), "style_set", G_CALLBACK(hack_max_label_width_cb), NULL); gtk_widget_show (label); view->pos = label; /* progress bar */ frame = gtk_frame_new (NULL); gtk_box_pack_start (GTK_BOX(hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); tool_hbox = gtk_hbox_new (FALSE, 2); gtk_container_add (GTK_CONTAINER(frame), tool_hbox); gtk_widget_show (tool_hbox); progress = gtk_progress_bar_new (); gtk_box_pack_start (GTK_BOX(tool_hbox), progress, TRUE, TRUE, 0); gtk_progress_set_show_text (GTK_PROGRESS(progress), TRUE); gtk_widget_show (progress); view->progress = progress; button = gtk_button_new_with_label (_("Cancel")); gtk_box_pack_start (GTK_BOX(tool_hbox), button, FALSE, FALSE, 0); gtk_widget_show (button); g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(cancel_cb), view); NOREADY(button); /* status */ frame = gtk_frame_new (NULL); gtk_box_pack_start (GTK_BOX(hbox), frame, FALSE, TRUE, 0); gtk_widget_show (frame); tool_hbox = gtk_hbox_new (FALSE, 2); gtk_container_add (GTK_CONTAINER(frame), tool_hbox); gtk_widget_show (tool_hbox); label = gtk_label_new ("Sweep " VERSION); gtk_box_pack_start (GTK_BOX(tool_hbox), label, FALSE, FALSE, 0); gtk_widget_show (label); view->status = label; button = gtk_button_new (); gtk_box_pack_start (GTK_BOX(tool_hbox), button, FALSE, FALSE, 0); gtk_widget_show (button); g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(show_info_dialog_cb), view); pixmap = create_widget_from_xpm (window, info_xpm); gtk_container_add (GTK_CONTAINER(button), pixmap); gtk_widget_show (pixmap); /* Had to wait until view->display was created before * setting the menus up */ view->menu = gtk_menu_new (); accel_group = create_view_menu (view, view->menu); gtk_window_add_accel_group (GTK_WINDOW(view->window), accel_group); create_view_menu (view, view->menubar); view->menu_sel = create_context_menu_sel (view); view->menu_point = create_context_menu_point (view); g_signal_connect_swapped (G_OBJECT(menu_button), "button_press_event", G_CALLBACK(menu_button_handler), G_OBJECT(view->menu)); /* Had to wait till view->display was created to set these up */ g_signal_connect (G_OBJECT(view->display), "mouse-offset-changed", G_CALLBACK(view_set_pos_indicator_cb), view->display); if (sample->sounddata->sels) sample_display_start_marching_ants (SAMPLE_DISPLAY(view->display)); view_refresh_title(view); view_default_status(view); view_refresh_tool_buttons (view); view_refresh_edit_mode (view); gtk_widget_show(window); view_zoom_normal (view); return view; } sw_view * view_new_all (sw_sample * sample, gfloat gain) { return view_new(sample, 0, sample->sounddata->nr_frames, gain); } void view_popup_context_menu (sw_view * view, guint button, guint32 activate_time) { GtkWidget * menu; if (view->sample->sounddata->sels == NULL) { menu = view->menu_point; } else { menu = view->menu_sel; } gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, button, activate_time); } /* * view_set_ends (v, start, end) * * set the endpoints shown by this view. */ void view_set_ends (sw_view * view, sw_framecount_t start, sw_framecount_t end) { GtkAdjustment * adj = GTK_ADJUSTMENT(view->adj); GtkWidget * entry; sw_framecount_t orig_length; sw_time_t length; gchar buf[16]; gfloat step; /* Clamp view to within bounds of sample */ orig_length = end - start; if(end > view->sample->sounddata->nr_frames) { end = view->sample->sounddata->nr_frames; start = end - orig_length; } if(start < 0) start = 0; /* Update duration displayed in zoom combo */ length = frames_to_time (view->sample->sounddata->format, end-start); snprint_time (buf, sizeof (buf), length); entry = GTK_COMBO(view->zoom_combo)->entry; g_signal_handlers_block_matched (G_OBJECT(entry), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); gtk_entry_set_text (GTK_ENTRY(entry), buf); g_signal_handlers_unblock_matched (G_OBJECT(entry), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); /* This check used to be at at the start of this function, but by * putting it down here we ensure the zoom combo displays the correct * length, and not a string like "All". */ if (start == view->start && end == view->end) return; /* Update main scrollbar */ step = ((gfloat)(end - start)) / 10.0; if (step < 1.0) step = 1.0; adj->value = (gfloat)start; adj->step_increment = step; adj->page_increment = (gfloat)(end - start); adj->page_size = (gfloat)(end - start); gtk_adjustment_changed(adj); /* Update ruler */ gtk_ruler_set_range (GTK_RULER(view->time_ruler), start, end, start, end); /* Update title etc. */ view_refresh_title(view); view_refresh_display(view); } void view_set_vzoom (sw_view * view, sw_audio_t low, sw_audio_t high) { sw_audio_t length; length = high - low; if (length > 2.0) { low = -1.0; high = 1.0; } else if (low < -1.0) { low = -1.0; high = low + length; } else if (high > 1.0) { high = 1.0; low = high - length; } view->vlow = low; view->vhigh = high; view_refresh_db_rulers (view); view_refresh_display (view); } void view_vzoom_in (sw_view * view, double ratio) { sw_audio_t oz, z; sw_audio_t nhigh, nlow; oz = view->vhigh - view->vlow; z = (sw_audio_t)((gdouble)oz / ratio); nlow = view->vlow + (oz - z)/2; nhigh = nlow + z; view_set_vzoom (view, nlow, nhigh); } void view_vzoom_out (sw_view * view, double ratio) { sw_audio_t oz, z; sw_audio_t nhigh, nlow; oz = view->vhigh - view->vlow; z = (sw_audio_t)((gdouble)oz * ratio); nlow = view->vlow + (oz - z)/2; nhigh = nlow + z; view_set_vzoom (view, nlow, nhigh); } static void view_clamp_to_offset (sw_view * view, sw_framecount_t * start, sw_framecount_t * end, sw_framecount_t offset) { sw_framecount_t length, width, nr_frames; length = *end - *start; width = SAMPLE_DISPLAY(view->display)->width; nr_frames = view->sample->sounddata->nr_frames; #ifdef SCROLL_SMOOTHLY if (!view->sample->play_head->scrubbing) { #else if (offset < *start || offset > *end) { #endif if (offset > nr_frames - length/2) { *start = nr_frames - length; *end = nr_frames; } else if (offset < length/2) { *start = 0; *end = length; } else if (length <= width * 8) { *start = offset - length/2; *end = *start + length; } else { #ifdef SCROLL_SMOOTHLY *start = offset - length/2; *end = *start + length; #else if (view->sample->play_head->reverse) { *end = offset; *start = *end - length; } else { *start = offset; *end = *start + length; } #endif } } } void view_zoom_to_playmarker (sw_view * view) { sw_framecount_t start, end; g_assert (view->following); start = view->start; end = view->end; view_clamp_to_offset (view, &start, &end, view->sample->user_offset); view_set_ends (view, start, end); } void view_zoom_to_offset (sw_view * view, sw_framecount_t offset) { sw_framecount_t start, end; start = view->start; end = view->end; view_clamp_to_offset (view, &start, &end, offset); view_set_ends (view, start, end); } void view_center_on (sw_view * view, sw_framecount_t offset) { sw_framecount_t vlen2; vlen2 = (view->end - view->start) / 2; view_set_ends (view, offset - vlen2, offset + vlen2); } void view_zoom_normal (sw_view * view) { sw_framecount_t length; length = MIN (view->sample->sounddata->nr_frames, SAMPLE_DISPLAY(view->display)->width * 1024); view_zoom_length (view, length); view_center_on (view, view->sample->user_offset); } void view_zoom_length (sw_view * view, sw_framecount_t length) { sw_framecount_t center; center = (view->end + view->start) / 2; view_set_ends (view, center - length/2, center + length/2); } void view_zoom_in (sw_view * view, double ratio) { sw_framecount_t nstart, nend, nlength, olength, offset, nr_frames; gboolean do_following; SampleDisplay * sd = SAMPLE_DISPLAY(view->display); olength = view->end - view->start; nlength = (sw_framecount_t)((double)olength / ratio); if(nlength <= DEFAULT_MIN_ZOOM) return; offset = view->sample->user_offset; /* zoom centred on the play marker if its visible, otherwise on * the middle of the view */ do_following = (view->following && offset >= view->start && offset <= view->end); if (do_following) { nr_frames = view->sample->sounddata->nr_frames; if (offset >= view->start && offset < view->end) { nstart = offset - (offset - view->start) / ratio; } else { nstart = offset - nlength/2; } if (nstart > nr_frames - nlength) { nstart = nr_frames - nlength; } else if (nstart < 0) { nstart = 0; } } else { nstart = view->start + (olength - nlength)/2; } sample_display_set_cursor(sd, sweep_cursors[SWEEP_CURSOR_ZOOM_IN]); nend = nstart+nlength; /* if (view->following) { view_clamp_to_playmarker (view, &nstart, &nend); } */ view_set_ends(view, nstart, nend); } void view_zoom_out (sw_view * view, double ratio) { sw_framecount_t nstart, nend, nlength, olength, offset, nr_frames; gboolean do_following; SampleDisplay * sd = SAMPLE_DISPLAY(view->display); olength = view->end - view->start; nlength = (sw_framecount_t)((double)olength * ratio); if (nlength < 0) return; /* sw_framecount_t multiplication overflow */ offset = view->sample->user_offset; /* zoom centred on the play marker if it's visible, otherwise on * the middle of the view */ do_following = (view->following && offset >= view->start && offset <= view->end); if (do_following) { nr_frames = view->sample->sounddata->nr_frames; if (offset >= view->start && offset < view->end) { nstart = offset - (offset - view->start) * ratio; } else { nstart = offset - nlength/2; } if (nstart > nr_frames - nlength) { nstart = nr_frames - nlength; } else if (nstart < 0) { nstart = 0; } } else { if (nlength > olength) { nstart = view->start - (nlength - olength)/2; } else { nstart = view->start + (olength - nlength)/2; } } if (nstart == view->start && (nstart+nlength) == view->end) return; sample_display_set_cursor(sd, sweep_cursors[SWEEP_CURSOR_ZOOM_OUT]); nend = nstart + nlength; view_set_ends(view, nstart, nend); } void view_zoom_to_sel (sw_view * view) { GList * gl; sw_sel * sel; gint sel_min, sel_max; if(!view->sample->sounddata->sels) return; gl = view->sample->sounddata->sels; sel = (sw_sel *)gl->data; sel_min = sel->sel_start; if (gl->next) for (gl = gl->next; gl->next; gl = gl->next); sel = (sw_sel *)gl->data; sel_max = sel->sel_end; view_set_ends(view, sel_min, sel_max); } void view_zoom_left (sw_view * view) { GtkAdjustment * adj = GTK_ADJUSTMENT(view->adj); adj->value -= adj->page_size; if(adj->value < adj->lower) { adj->value = adj->lower; } gtk_adjustment_value_changed (GTK_ADJUSTMENT(adj)); } void view_zoom_right (sw_view * view) { GtkAdjustment * adj = GTK_ADJUSTMENT(view->adj); adj->value += adj->page_size; if(adj->value > adj->upper) { adj->value = adj->upper; } gtk_adjustment_value_changed (GTK_ADJUSTMENT(adj)); } void view_zoom_all (sw_view * view) { sw_sample * s; s = view->sample; view_set_ends(view, 0, s->sounddata->nr_frames); } static void view_store_cb (GtkWidget * widget, gpointer data) { sw_view * view = (sw_view *)data; sw_sample * sample = view->sample; gint slot; slot = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(widget), "default")); if (slot < 0 || slot > 9) return; sample->stored_views[slot].start = view->start; sample->stored_views[slot].end = view->end; sample_set_tmp_message (sample, _("Remembered as area %d"), slot); } static void view_retrieve_cb (GtkWidget * widget, gpointer data) { sw_view * view = (sw_view *)data; sw_sample * sample = view->sample; gint slot; sw_framecount_t start, end; slot = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(widget), "default")); if (slot < 0 || slot > 9) return; start = sample->stored_views[slot].start; end = sample->stored_views[slot].end; if (start == end) { sample_set_tmp_message (sample, _("No area remembered as %d"), slot); } else { view_set_ends (view, start, end); sample_set_tmp_message (sample, _("Zoomed to area %d"), slot); } } void view_refresh_edit_mode (sw_view * view) { GList * gl; GtkWidget * w; if (view->sample == NULL) return; switch (view->sample->edit_mode) { case SWEEP_EDIT_MODE_READY: for (gl = view->noready_widgets; gl; gl = gl->next) { w = (GtkWidget *)gl->data; gtk_widget_set_sensitive (w, FALSE); } for (gl = view->nomodify_widgets; gl; gl = gl->next) { w = (GtkWidget *)gl->data; gtk_widget_set_sensitive (w, TRUE); } for (gl = view->noalloc_widgets; gl; gl = gl->next) { w = (GtkWidget *)gl->data; gtk_widget_set_sensitive (w, TRUE); } if (view->sample->tmp_message_active) { view_set_tmp_message (view, view->sample->last_tmp_message); } else { view_set_progress_ready (view); } break; case SWEEP_EDIT_MODE_META: case SWEEP_EDIT_MODE_FILTER: for (gl = view->noready_widgets; gl; gl = gl->next) { w = (GtkWidget *)gl->data; gtk_widget_set_sensitive (w, TRUE); } for (gl = view->nomodify_widgets; gl; gl = gl->next) { w = (GtkWidget *)gl->data; gtk_widget_set_sensitive (w, FALSE); } for (gl = view->noalloc_widgets; gl; gl = gl->next) { w = (GtkWidget *)gl->data; gtk_widget_set_sensitive (w, TRUE); } break; case SWEEP_EDIT_MODE_ALLOC: for (gl = view->noready_widgets; gl; gl = gl->next) { w = (GtkWidget *)gl->data; gtk_widget_set_sensitive (w, TRUE); } for (gl = view->nomodify_widgets; gl; gl = gl->next) { w = (GtkWidget *)gl->data; gtk_widget_set_sensitive (w, FALSE); } for (gl = view->noalloc_widgets; gl; gl = gl->next) { w = (GtkWidget *)gl->data; gtk_widget_set_sensitive (w, FALSE); } break; default: g_assert_not_reached (); break; } } void view_refresh_playmode (sw_view * view) { sw_head * head = view->sample->play_head; gboolean playing, playing_sel; g_mutex_lock (head->head_mutex); playing = head->going && !head->restricted; playing_sel = head->going && head->restricted; g_mutex_unlock (head->head_mutex); g_signal_handlers_block_matched (GTK_OBJECT(view->play_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(view->play_toggle), playing); g_signal_handlers_unblock_matched (GTK_OBJECT(view->play_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); g_signal_handlers_block_matched (GTK_OBJECT(view->play_sel_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(view->play_sel_toggle), playing_sel); g_signal_handlers_unblock_matched (GTK_OBJECT(view->play_sel_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); /* If we're stopped, don't show the play line any more */ view_refresh_display (view); view_refresh_offset_indicators (view); } void view_refresh_offset_indicators (sw_view * view) { SampleDisplay * sd = SAMPLE_DISPLAY(view->display); sw_sample * sample = view->sample; sw_framecount_t offset; static int rate_limit = 0; char buf[16]; offset = (sample->play_head->going ? (sw_framecount_t)sample->play_head->offset : sample->user_offset); snprint_time (buf, sizeof (buf), frames_to_time (sample->sounddata->format, offset)); /* cheesy rate limiter. ugly in operation. limits pango damage */ if (rate_limit >= 3) { rate_limit=0; #ifdef PLAYPOS_LABEL gtk_label_set_text (GTK_LABEL(view->play_pos), buf); #else gtk_entry_set_text (GTK_ENTRY(view->play_pos), buf); #endif } ++rate_limit; sample_display_refresh_play_marker (sd); sample_display_refresh_user_marker (sd); if (view->following) { view_zoom_to_offset (view, offset); } } void view_refresh_rec_offset_indicators (sw_view * view) { SampleDisplay * sd = SAMPLE_DISPLAY(view->display); sample_display_refresh_rec_marker (sd); } /* format string can include %p (current percentage) or %v (current value) */ void view_set_progress_text (sw_view * view, gchar * text) { if (view == NULL) return; gtk_progress_set_format_string (GTK_PROGRESS(view->progress), text); } void view_set_progress_percent (sw_view * view, gint percent) { if (view == NULL) return; gtk_progress_set_percentage (GTK_PROGRESS(view->progress), (gfloat)percent/100.0); } void view_set_tmp_message (sw_view * view, gchar * message) { if (view == NULL) return; gtk_progress_set_format_string (GTK_PROGRESS(view->progress), message); gtk_progress_set_percentage (GTK_PROGRESS(view->progress), 0.0); } void view_set_progress_ready (sw_view * view) { gchar buf[64]; if (view == NULL) return; snprintf (buf, sizeof (buf), "%s%s - %s", view->sample->modified ? "*" : "", g_basename (view->sample->pathname), view->sample->play_head->scrubbing ? _("Scrub!") : _("Ready")); gtk_progress_set_format_string (GTK_PROGRESS(view->progress), buf); gtk_progress_set_percentage (GTK_PROGRESS(view->progress), 0.0); } void view_set_following (sw_view * view, gboolean following) { view->following = following; g_signal_handlers_block_matched (GTK_OBJECT(view->follow_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(view->follow_toggle), view->following); g_signal_handlers_unblock_matched (GTK_OBJECT(view->follow_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); g_signal_handlers_block_matched (GTK_OBJECT(view->follow_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(view->follow_checkmenu), view->following); g_signal_handlers_unblock_matched (GTK_OBJECT(view->follow_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); if (view->following) { view_zoom_to_playmarker (view); } } static void view_close_ok_cb (GtkWidget * widget, gpointer data) { sw_view * view = (sw_view *)data; gtk_widget_destroy(view->window); memset (view, 0, sizeof (*view)); g_free(view); } void view_close (sw_view * view) { sw_sample * sample = view->sample; char buf[256]; if (sample->modified && g_list_length (sample->views) == 1) { snprintf (buf, sizeof (buf), _("%s has been modified. Close anyway?"), g_basename (sample->pathname)); question_dialog_new (sample, _("File modified"), buf, _("Close"), _("Don't close"), G_CALLBACK (view_close_ok_cb), view, NULL, NULL, SWEEP_EDIT_MODE_ALLOC); } else { view_close_ok_cb (NULL, view); } } void view_volume_increase (sw_view * view) { GtkAdjustment * adj = GTK_ADJUSTMENT(view->gain_adj); adj->value += 0.1; if (adj->value >= 1.0) adj->value = 1.0; gtk_adjustment_value_changed (adj); } void view_volume_decrease (sw_view * view) { GtkAdjustment * adj = GTK_ADJUSTMENT(view->gain_adj); adj->value -= 0.1; if (adj->value <= 0.0) adj->value = 0.0; gtk_adjustment_value_changed (adj); } void view_refresh_title (sw_view * view) { char buf[256]; sw_sample * s = (sw_sample *)view->sample; if (s->sounddata->nr_frames > 0) { snprintf(buf, sizeof (buf), "%s%s %0d%% - Sweep " VERSION, s->modified ? _("*") : "", s->pathname ? g_basename (s->pathname) : _("Untitled"), s->progress_percent); } else { snprintf(buf, sizeof (buf), "%s%s %s - Sweep " VERSION, s->modified ? _("*") : "", s->pathname ? g_basename (s->pathname) : _("Untitled"), _("Empty")); } gtk_window_set_title (GTK_WINDOW(view->window), buf); } void view_default_status (sw_view * view) { sw_sample * s = (sw_sample *)view->sample; sw_sounddata * sounddata = s->sounddata; char byte_buf[16]; char time_buf[16]; char chan_buf[16]; char buf [256]; snprint_bytes (byte_buf, sizeof (byte_buf), frames_to_bytes (sounddata->format, sounddata->nr_frames)); snprint_time (time_buf, sizeof (time_buf), frames_to_time (sounddata->format, sounddata->nr_frames)); switch (s->sounddata->format->channels) { case 1: snprintf (chan_buf, sizeof (chan_buf), _("Mono")); break; case 2: snprintf (chan_buf, sizeof (chan_buf), _("Stereo")); break; default: snprintf (chan_buf, sizeof (chan_buf), "%d %s", s->sounddata->format->channels, _("channels")); break; } snprintf (buf, sizeof (buf), "%dHz %s [%s]", s->sounddata->format->rate, chan_buf, time_buf); gtk_label_set_text (GTK_LABEL(view->status), buf); } void view_refresh_tool_buttons (sw_view * v) { GList * gl; GtkWidget * button; sw_tool_t tool; for (gl = v->tool_buttons; gl; gl = gl->next) { button = (GtkWidget *)gl->data; tool = (sw_tool_t) g_object_get_data (G_OBJECT(button), "default"); g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, v); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), (tool == v->current_tool)); g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, v); } } void view_refresh_hruler (sw_view * v) { gtk_ruler_set_range (GTK_RULER(v->time_ruler), v->start, v->end, v->start, v->end); time_ruler_set_format (TIME_RULER(v->time_ruler), v->sample->sounddata->format); } void view_refresh_display (sw_view * v) { SampleDisplay * sd = SAMPLE_DISPLAY(v->display); sample_display_refresh(sd); } void view_refresh_adjustment (sw_view * v) { GtkAdjustment * adj = GTK_ADJUSTMENT(v->adj); gboolean changed = FALSE; adj->upper = (gfloat)v->sample->sounddata->nr_frames; if (adj->page_size > (gfloat)v->sample->sounddata->nr_frames) { adj->page_size = (gfloat)v->sample->sounddata->nr_frames; adj->value = 0; changed = TRUE; } if (adj->value > adj->upper - adj->page_size) { adj->value = adj->upper - adj->page_size; changed = TRUE; } if (adj->page_increment == 0) { adj->page_increment = (gfloat)(v->end - v->start); changed = TRUE; } if (adj->page_size == 0) { adj->page_size = (gfloat)(v->end - v->start); changed = TRUE; } if (changed) gtk_adjustment_changed (adj); } void view_refresh_looping (sw_view * view) { g_signal_handlers_block_matched (GTK_OBJECT(view->loop_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(view->loop_toggle), view->sample->play_head->looping); g_signal_handlers_unblock_matched (GTK_OBJECT(view->loop_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); g_signal_handlers_block_matched (GTK_OBJECT(view->loop_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(view->loop_checkmenu), view->sample->play_head->looping); g_signal_handlers_unblock_matched (GTK_OBJECT(view->loop_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); } void view_refresh_playrev (sw_view * view) { g_signal_handlers_block_matched (GTK_OBJECT(view->playrev_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(view->playrev_toggle), view->sample->play_head->reverse); g_signal_handlers_unblock_matched (GTK_OBJECT(view->playrev_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); g_signal_handlers_block_matched (GTK_OBJECT(view->playrev_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(view->playrev_checkmenu), view->sample->play_head->reverse); g_signal_handlers_unblock_matched (GTK_OBJECT(view->playrev_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); } void view_refresh_mute (sw_view * view) { g_signal_handlers_block_matched (GTK_OBJECT(view->mute_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(view->mute_toggle), view->sample->play_head->mute); g_signal_handlers_unblock_matched (GTK_OBJECT(view->mute_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); g_signal_handlers_block_matched (GTK_OBJECT(view->mute_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(view->mute_checkmenu), view->sample->play_head->mute); g_signal_handlers_unblock_matched (GTK_OBJECT(view->mute_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); } void view_refresh_monitor (sw_view * view) { g_signal_handlers_block_matched (GTK_OBJECT(view->monitor_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(view->monitor_toggle), view->sample->play_head->monitor); g_signal_handlers_unblock_matched (GTK_OBJECT(view->monitor_toggle), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); g_signal_handlers_block_matched (GTK_OBJECT(view->monitor_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(view->monitor_checkmenu), view->sample->play_head->monitor); g_signal_handlers_unblock_matched (GTK_OBJECT(view->monitor_checkmenu), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, view); } void view_fix_adjustment (sw_view * v) { GtkAdjustment * adj = GTK_ADJUSTMENT(v->adj); adj->value = (gfloat)v->start; adj->lower = (gfloat)0.0; adj->upper = (gfloat)v->sample->sounddata->nr_frames; adj->page_increment = (gfloat)(v->end - v->start); adj->page_size = (gfloat)(v->end - v->start); gtk_adjustment_changed (adj); } void view_refresh (sw_view * v) { view_refresh_adjustment (v); view_refresh_title (v); view_default_status (v); view_refresh_display (v); view_refresh_offset_indicators (v); view_refresh_tool_buttons (v); view_refresh_looping (v); view_refresh_playrev (v); view_refresh_channelops_menu (v); view_refresh_db_rulers (v); } void view_sink_last_tmp_view (void) { if (!last_tmp_view) return; sample_display_sink_tmp_sel(SAMPLE_DISPLAY(last_tmp_view->display)); } void view_clear_last_tmp_view (void) { if (!last_tmp_view) return; sample_display_clear_sel(SAMPLE_DISPLAY(last_tmp_view->display)); }