GtkWidget* ctk_drop_down_menu_new(guint flags) { GObject *object; CtkDropDownMenu *d; object = g_object_new(CTK_TYPE_DROP_DOWN_MENU, NULL); d = CTK_DROP_DOWN_MENU(object); d->flags = flags; d->values = NULL; d->num_entries = 0; d->current_selected_item = -1; if (flags & CTK_DROP_DOWN_MENU_FLAG_READWRITE) { d->combo_box = ctk_combo_box_text_new_with_entry(); g_signal_connect(G_OBJECT(gtk_bin_get_child(GTK_BIN(d->combo_box))), "changed", G_CALLBACK(ctk_drop_down_menu_changed), (gpointer) d); } else { d->combo_box = ctk_combo_box_text_new(); g_signal_connect(G_OBJECT(d->combo_box), "changed", G_CALLBACK(changed), (gpointer) d); } gtk_box_set_spacing(GTK_BOX(d), 0); gtk_box_pack_start(GTK_BOX(d), d->combo_box, FALSE, FALSE, 0); return GTK_WIDGET(d); } /* ctk_drop_down_menu_new() */
static void changed(GtkWidget *combo_box, gpointer user_data) { CtkDropDownMenu *d = CTK_DROP_DOWN_MENU(user_data); g_signal_emit(G_OBJECT(d), __signals[DROP_DOWN_MENU_CHANGED_SIGNAL], 0); } /* changed() */
GtkWidget* ctk_drop_down_menu_new(guint flags) { GObject *object; CtkDropDownMenu *d; object = g_object_new(CTK_TYPE_DROP_DOWN_MENU, NULL); d = CTK_DROP_DOWN_MENU(object); d->flags = flags; d->values = NULL; d->num_entries = 0; d->option_menu = gtk_option_menu_new(); d->menu = gtk_menu_new(); gtk_option_menu_set_menu(GTK_OPTION_MENU(d->option_menu), d->menu); gtk_box_set_spacing(GTK_BOX(d), 0); gtk_box_pack_start(GTK_BOX(d), d->option_menu, FALSE, FALSE, 0); g_signal_connect(G_OBJECT(d->option_menu), "changed", G_CALLBACK(changed), (gpointer) d); return GTK_WIDGET(d); } /* ctk_drop_down_menu_new() */
static void set_sync_format_menu(CtkGvoSync *ctk_gvo_sync) { gint val = get_current_sync_format(ctk_gvo_sync); ctk_drop_down_menu_set_current_value (CTK_DROP_DOWN_MENU(ctk_gvo_sync->sync_format_menu), val); }
static void ctk_drop_down_menu_free(GObject *object) { CtkDropDownMenu *d; d = CTK_DROP_DOWN_MENU(object); g_free(d->values); } /* ctk_drop_down_menu_free() */
GObject *ctk_drop_down_menu_change_object(GtkWidget* widget) { CtkDropDownMenu *d = CTK_DROP_DOWN_MENU(widget); if (d->flags & CTK_DROP_DOWN_MENU_FLAG_READWRITE) { return G_OBJECT(gtk_bin_get_child(GTK_BIN(d->combo_box))); } else { return G_OBJECT(d->combo_box); } } /* ctk_drop_down_menu_change_object() */
static void ctk_drop_down_menu_changed(GtkEditable *editable, gpointer user_data) { int i; CtkDropDownMenu *d = CTK_DROP_DOWN_MENU(user_data); const gchar *str = gtk_entry_get_text(GTK_ENTRY(editable)); for (i = 0; i < d->num_entries; i++) { if (strcmp(d->values[i].glist_item, str) == 0) { d->current_selected_item = i; break; } } g_signal_emit(G_OBJECT(d), __signals[DROP_DOWN_MENU_CHANGED_SIGNAL], 0); }
/***** * * Signal handler - User selected a clock set from the clock menu. * */ static void clock_menu_changed(GtkWidget *widget, gpointer user_data) { CtkClocks *ctk_object = CTK_CLOCKS(user_data); CtkDropDownMenu *menu = CTK_DROP_DOWN_MENU(widget); gint history; /* Sync to allow user to modify the clocks */ history = ctk_drop_down_menu_get_current_value(menu); switch (history) { default: /* Fall through */ case 0: /* 2D */ sync_gui_to_modify_clocks(ctk_object, CLOCKS_2D); break; case 1: /* 3D */ sync_gui_to_modify_clocks(ctk_object, CLOCKS_3D); break; } } /* clock_menu_changed() */
GtkWidget* ctk_gvo_sync_new(NvCtrlAttributeHandle *handle, GtkWidget *parent_window, CtkConfig *ctk_config, CtkEvent *ctk_event, CtkGvo *gvo_parent) { GObject *object; CtkGvoSync *ctk_gvo_sync; GtkWidget *frame; GtkWidget *hbox; GtkWidget *label; GtkWidget *alignment; GtkWidget *button; GtkWidget *table, *menu; gint val, i; NVCTRLAttributeValidValuesRec valid; ReturnStatus ret; gint row; const char *help_text; /* make sure we have a handle */ g_return_val_if_fail(handle != NULL, NULL); /* create and initialize the object */ object = g_object_new(CTK_TYPE_GVO_SYNC, NULL); ctk_gvo_sync = CTK_GVO_SYNC(object); ctk_gvo_sync->handle = handle; ctk_gvo_sync->parent_window = parent_window; ctk_gvo_sync->ctk_config = ctk_config; ctk_gvo_sync->ctk_event = ctk_event; ctk_gvo_sync->gvo_parent = gvo_parent; /* Query the current GVO state */ if ( !query_init_gvo_sync_state(ctk_gvo_sync) ) { // Free the object g_object_ref(object); gtk_object_sink(GTK_OBJECT(object)); g_object_unref(object); return NULL; } /* set container properties for the widget */ gtk_box_set_spacing(GTK_BOX(object), 10); /* banner */ hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0); ctk_gvo_sync->banner_box = hbox; /* * Sync options */ frame = gtk_frame_new("Sync Options"); ctk_gvo_sync->frame = frame; gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0); table = gtk_table_new(6, 2, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 0); gtk_table_set_col_spacings(GTK_TABLE(table), 0); gtk_container_add(GTK_CONTAINER(frame), table); /* input video format */ label = gtk_label_new("Input Video Format: "); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); hbox = gtk_hbox_new(FALSE, 5); ctk_gvo_sync->input_video_format_text_entry = gtk_entry_new(); ctk_config_set_tooltip(ctk_config, ctk_gvo_sync->input_video_format_text_entry, __input_video_format_help); gtk_entry_set_width_chars (GTK_ENTRY(ctk_gvo_sync->input_video_format_text_entry), max_input_video_format_text_entry_length()); gtk_widget_set_sensitive(ctk_gvo_sync->input_video_format_text_entry, FALSE); update_input_video_format_text_entry(ctk_gvo_sync); gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->input_video_format_text_entry, TRUE, TRUE, 0); /* Input video format detect button */ button = gtk_toggle_button_new_with_label("Detect"); alignment = gtk_alignment_new(1, 1, 0, 0); gtk_container_add(GTK_CONTAINER(alignment), button); ctk_gvo_sync->input_video_format_detect_button = button; ctk_config_set_tooltip(ctk_config, button, __input_video_format_detect_help); g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(detect_input_toggled), ctk_gvo_sync); gtk_box_pack_start(GTK_BOX(hbox), alignment, FALSE, FALSE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, TABLE_PADDING, TABLE_PADDING); /* Composite Termination */ if (ctk_gvo_sync->caps & NV_CTRL_GVO_CAPABILITIES_COMPOSITE_TERMINATION) { button = gtk_check_button_new_with_label("Enable Composite Termination"); ctk_config_set_tooltip(ctk_config, button, __composite_termination_help); alignment = gtk_alignment_new(1, 1, 0, 0); gtk_container_add(GTK_CONTAINER(alignment), button); gtk_table_attach(GTK_TABLE(table), alignment, 0, 2, 2, 3, GTK_FILL | GTK_EXPAND, GTK_FILL, TABLE_PADDING, TABLE_PADDING); ctk_gvo_sync->composite_termination_button = button; init_composite_termination(ctk_gvo_sync); g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(composite_termination_toggled), ctk_gvo_sync); row = 3; } else { ctk_gvo_sync->composite_termination_button = NULL; row = 2; } /* Sync Mode */ menu = start_menu("Sync Mode: ", table, row); ctk_drop_down_menu_append_item(CTK_DROP_DOWN_MENU(menu), "Free Running", NV_CTRL_GVO_SYNC_MODE_FREE_RUNNING); ctk_drop_down_menu_append_item(CTK_DROP_DOWN_MENU(menu), "GenLock", NV_CTRL_GVO_SYNC_MODE_GENLOCK); ctk_drop_down_menu_append_item(CTK_DROP_DOWN_MENU(menu), "FrameLock", NV_CTRL_GVO_SYNC_MODE_FRAMELOCK); finish_menu(menu, table, row); row++; ctk_gvo_sync->sync_mode_menu = menu; ctk_drop_down_menu_set_tooltip(ctk_config, CTK_DROP_DOWN_MENU(menu), __sync_mode_help); ctk_drop_down_menu_set_current_value (CTK_DROP_DOWN_MENU(ctk_gvo_sync->sync_mode_menu), ctk_gvo_sync->sync_mode); g_signal_connect(G_OBJECT(ctk_gvo_sync->sync_mode_menu), "changed", G_CALLBACK(sync_mode_changed), (gpointer) ctk_gvo_sync); /* Sync Format */ menu = start_menu("Sync Format: ", table, row); for (i = 0; syncFormatNames[i].name; i++) { ctk_drop_down_menu_append_item(CTK_DROP_DOWN_MENU(menu), syncFormatNames[i].name, syncFormatNames[i].format); } finish_menu(menu, table, row); row++; ctk_gvo_sync->sync_format_menu = menu; ctk_drop_down_menu_set_tooltip(ctk_config, CTK_DROP_DOWN_MENU(menu), __sync_format_help); init_sync_format_menu(ctk_gvo_sync); g_signal_connect(G_OBJECT(ctk_gvo_sync->sync_format_menu), "changed", G_CALLBACK(sync_format_changed), (gpointer) ctk_gvo_sync); /* Sync Status */ label = gtk_label_new("Sync Status:"); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); ctk_gvo_sync->sync_lock_status_text = gtk_label_new(""); update_sync_lock_status_text(ctk_gvo_sync); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->sync_lock_status_text, FALSE, FALSE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, row, row+1, GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, TABLE_PADDING, TABLE_PADDING); row++; /* * Synchronization Skew (Delay/Advance) */ /* NV_CTRL_GVO_SYNC_DELAY_PIXELS */ ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GVO_SYNC_DELAY_PIXELS, &valid); if ((ret == NvCtrlSuccess) && (valid.type == ATTRIBUTE_TYPE_RANGE)) { ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_SYNC_DELAY_PIXELS, &val); if (ret != NvCtrlSuccess) val = 0; if (ctk_gvo_sync->caps & NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW) { label = gtk_label_new("HSync Advance:"); help_text = __hsync_advance_help; } else { label = gtk_label_new("HSync Delay:"); help_text = __hsync_delay_help; } gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); ctk_gvo_sync->hsync_delay_spin_button = gtk_spin_button_new_with_range(valid.u.range.min, valid.u.range.max, 1); ctk_config_set_tooltip(ctk_config, ctk_gvo_sync->hsync_delay_spin_button, help_text); gtk_spin_button_set_value (GTK_SPIN_BUTTON(ctk_gvo_sync->hsync_delay_spin_button), val); g_signal_connect(G_OBJECT(ctk_gvo_sync->hsync_delay_spin_button), "value-changed", G_CALLBACK(hsync_delay_changed), ctk_gvo_sync); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->hsync_delay_spin_button, FALSE, FALSE, 0); label = gtk_label_new("(pixels)"); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, row, row+1, GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, TABLE_PADDING, TABLE_PADDING); row++; } /* NV_CTRL_GVO_SYNC_DELAY_LINES */ ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GVO_SYNC_DELAY_LINES, &valid); if ((ret == NvCtrlSuccess) && (valid.type == ATTRIBUTE_TYPE_RANGE)) { ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_SYNC_DELAY_LINES, &val); if (ret != NvCtrlSuccess) val = 0; if (ctk_gvo_sync->caps & NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW) { label = gtk_label_new("VSync Advance:"); help_text = __vsync_advance_help; } else { label = gtk_label_new("VSync Delay:"); help_text = __vsync_delay_help; } gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); ctk_gvo_sync->vsync_delay_spin_button = gtk_spin_button_new_with_range(valid.u.range.min, valid.u.range.max, 1); ctk_config_set_tooltip(ctk_config, ctk_gvo_sync->vsync_delay_spin_button, help_text); gtk_spin_button_set_value (GTK_SPIN_BUTTON(ctk_gvo_sync->vsync_delay_spin_button), val); g_signal_connect(G_OBJECT(ctk_gvo_sync->vsync_delay_spin_button), "value-changed", G_CALLBACK(vsync_delay_changed), ctk_gvo_sync); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->vsync_delay_spin_button, FALSE, FALSE, 0); label = gtk_label_new("(lines)"); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, row, row+1, GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, TABLE_PADDING, TABLE_PADDING); row++; } /* create the watch cursor (for use when the "Detect" button is toggled" */ ctk_gvo_sync->wait_cursor = gdk_cursor_new(GDK_WATCH); /* Set UI sensitivity */ update_gvo_sync_sensitivity(ctk_gvo_sync); /* Start listening for events */ register_for_gvo_sync_events(ctk_gvo_sync); /* show the page */ gtk_widget_show_all(GTK_WIDGET(object)); return GTK_WIDGET(object); } /* ctk_gvo_sync_new() */
static void gvo_sync_event_received(GtkObject *object, gpointer arg1, gpointer user_data) { CtkEventStruct *event_struct = (CtkEventStruct *) arg1; CtkGvoSync *ctk_gvo_sync = CTK_GVO_SYNC(user_data); GtkWidget *widget; gint attribute = event_struct->attribute; gint value = event_struct->value; gboolean update_sync_format = FALSE; switch (attribute) { case NV_CTRL_GVO_SYNC_MODE: ctk_gvo_sync->sync_mode = value; widget = ctk_gvo_sync->sync_mode_menu; g_signal_handlers_block_by_func(G_OBJECT(widget), G_CALLBACK(sync_mode_changed), (gpointer) ctk_gvo_sync); ctk_drop_down_menu_set_current_value (CTK_DROP_DOWN_MENU(widget), value); g_signal_handlers_unblock_by_func(G_OBJECT(widget), G_CALLBACK(sync_mode_changed), (gpointer) ctk_gvo_sync); post_sync_mode_menu_changed(ctk_gvo_sync, value); break; case NV_CTRL_GVO_SYNC_SOURCE: ctk_gvo_sync->sync_source = value; update_sync_format = TRUE; break; case NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE: ctk_gvo_sync->comp_mode = value; update_sync_format = TRUE; break; case NV_CTRL_GVO_SYNC_DELAY_PIXELS: widget = ctk_gvo_sync->hsync_delay_spin_button; if (widget) { g_signal_handlers_block_by_func(G_OBJECT(widget), G_CALLBACK(hsync_delay_changed), (gpointer) ctk_gvo_sync); gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), value); g_signal_handlers_unblock_by_func(G_OBJECT(widget), G_CALLBACK(hsync_delay_changed), (gpointer) ctk_gvo_sync); } break; case NV_CTRL_GVO_SYNC_DELAY_LINES: widget = ctk_gvo_sync->vsync_delay_spin_button; if (widget) { g_signal_handlers_block_by_func(G_OBJECT(widget), G_CALLBACK(vsync_delay_changed), (gpointer) ctk_gvo_sync); gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), value); g_signal_handlers_unblock_by_func(G_OBJECT(widget), G_CALLBACK(vsync_delay_changed), (gpointer) ctk_gvo_sync); } break; case NV_CTRL_GVO_COMPOSITE_TERMINATION: widget = ctk_gvo_sync->composite_termination_button; if (widget) { g_signal_handlers_block_by_func (G_OBJECT(widget), G_CALLBACK(composite_termination_toggled), ctk_gvo_sync); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), value); g_signal_handlers_unblock_by_func (G_OBJECT(widget), G_CALLBACK(composite_termination_toggled), ctk_gvo_sync); post_composite_termination_toggled(ctk_gvo_sync, value); } break; } /* Update the sync format menu */ if (update_sync_format) { widget = ctk_gvo_sync->sync_format_menu; g_signal_handlers_block_by_func(G_OBJECT(widget), G_CALLBACK(sync_format_changed), (gpointer) ctk_gvo_sync); set_sync_format_menu(ctk_gvo_sync); g_signal_handlers_unblock_by_func(G_OBJECT(widget), G_CALLBACK(sync_format_changed), (gpointer) ctk_gvo_sync); post_sync_format_menu_changed(ctk_gvo_sync); } } /* gvo_sync_event_received() */
/***** * * Syncs the gui to properly display the correct clocks the user wants to * modify, or has modified with another NV_CONTROL client. * */ static void sync_gui_to_modify_clocks(CtkClocks *ctk_object, int which_clocks) { GtkRange *gtk_range; GtkAdjustment *gtk_adjustment_gpu; GtkAdjustment *gtk_adjustment_mem; ReturnStatus ret; int clk_values; int default_clk_values; NVCTRLAttributeValidValuesRec clk_ranges; CtkDropDownMenu *menu; menu = CTK_DROP_DOWN_MENU(ctk_object->clock_menu); /* Obtain the current value and range of the desired clocks */ switch (which_clocks) { case CLOCKS_2D: ret = NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_GPU_2D_CLOCK_FREQS, &clk_values); if ( ret != NvCtrlSuccess ) return; ret = NvCtrlGetValidAttributeValues(ctk_object->handle, NV_CTRL_GPU_2D_CLOCK_FREQS, &clk_ranges); if ( ret != NvCtrlSuccess ) return; break; case CLOCKS_3D: ret = NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_GPU_3D_CLOCK_FREQS, &clk_values); if ( ret != NvCtrlSuccess ) return; ret = NvCtrlGetValidAttributeValues(ctk_object->handle, NV_CTRL_GPU_3D_CLOCK_FREQS, &clk_ranges); if ( ret != NvCtrlSuccess ) return; break; case CLOCKS_NONE: default: return; } /* See if the clocks were modified */ ret = NvCtrlGetAttribute(ctk_object->handle, which_clocks==CLOCKS_2D? NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS: NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS, &default_clk_values); ctk_object->clocks_modified = ((ret == NvCtrlSuccess) && (default_clk_values != clk_values)); if ( ctk_object->clocks_being_modified != which_clocks ) { ctk_object->clocks_moved = False; } ctk_object->clocks_being_modified = which_clocks; /* Make sure the dropdown reflects the right clock set */ g_signal_handlers_block_by_func(G_OBJECT(ctk_object->clock_menu), G_CALLBACK(clock_menu_changed), (gpointer) ctk_object); ctk_drop_down_menu_set_current_value(menu, (which_clocks==CLOCKS_2D)?0:1); g_signal_handlers_unblock_by_func(G_OBJECT(ctk_object->clock_menu), G_CALLBACK(clock_menu_changed), (gpointer) ctk_object); /* Make GPU and Memory clocks reflect the right range/values */ gtk_range = GTK_RANGE(CTK_SCALE(ctk_object->gpu_clk_scale)->gtk_scale); gtk_adjustment_gpu = GTK_ADJUSTMENT(gtk_range->adjustment); g_signal_handlers_block_by_func(G_OBJECT(gtk_adjustment_gpu), G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); gtk_range_set_range(gtk_range, GET_GPU_CLOCK(clk_ranges.u.range.min), GET_GPU_CLOCK(clk_ranges.u.range.max)); g_signal_handlers_unblock_by_func(G_OBJECT(gtk_adjustment_gpu), G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); gtk_range = GTK_RANGE(CTK_SCALE(ctk_object->mem_clk_scale)->gtk_scale); gtk_adjustment_mem = GTK_ADJUSTMENT(gtk_range->adjustment); g_signal_handlers_block_by_func(G_OBJECT(gtk_adjustment_mem), G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); gtk_range_set_range(gtk_range, GET_MEM_CLOCK(clk_ranges.u.range.min), GET_MEM_CLOCK(clk_ranges.u.range.max)); set_clocks_value(ctk_object, clk_values, which_clocks); g_signal_handlers_unblock_by_func(G_OBJECT(gtk_adjustment_mem), G_CALLBACK(adjustment_value_changed), (gpointer) ctk_object); /* Update the gui sensitivity */ sync_gui_sensitivity(ctk_object); } /* sync_gui_to_modify_clocks() */