static gboolean register_link_events(InfoEntry *entry)
{
    CtkDisplayDevice *ctk_object = entry->ctk_object;

    g_signal_connect(G_OBJECT(ctk_object->ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_FLATPANEL_LINK),
                     G_CALLBACK(callback_link_changed),
                     (gpointer) entry);

    g_signal_connect(G_OBJECT(ctk_object->ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_DISPLAYPORT_LINK_RATE),
                     G_CALLBACK(callback_link_changed),
                     (gpointer) entry);

    return TRUE;
}
static gboolean register_refresh_rate_events(InfoEntry *entry)
{
    CtkDisplayDevice *ctk_object = entry->ctk_object;

    g_signal_connect(G_OBJECT(ctk_object->ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_REFRESH_RATE),
                     G_CALLBACK(callback_refresh_rate_changed),
                     (gpointer) entry);
    return TRUE;
}
static void register_for_gvo_sync_events(CtkGvoSync *ctk_gvo_sync)
{
    g_signal_connect(G_OBJECT(ctk_gvo_sync->ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GVO_SYNC_MODE),
                     G_CALLBACK(gvo_sync_event_received),
                     (gpointer) ctk_gvo_sync);

    g_signal_connect(G_OBJECT(ctk_gvo_sync->ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GVO_SYNC_SOURCE),
                     G_CALLBACK(gvo_sync_event_received),
                     (gpointer) ctk_gvo_sync);

    g_signal_connect(G_OBJECT(ctk_gvo_sync->ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE),
                     G_CALLBACK(gvo_sync_event_received),
                     (gpointer) ctk_gvo_sync);

    g_signal_connect(G_OBJECT(ctk_gvo_sync->ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GVO_SYNC_DELAY_PIXELS),
                     G_CALLBACK(gvo_sync_event_received),
                     (gpointer) ctk_gvo_sync);

    g_signal_connect(G_OBJECT(ctk_gvo_sync->ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GVO_SYNC_DELAY_LINES),
                     G_CALLBACK(gvo_sync_event_received),
                     (gpointer) ctk_gvo_sync);

    g_signal_connect(G_OBJECT(ctk_gvo_sync->ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GVO_COMPOSITE_TERMINATION),
                     G_CALLBACK(gvo_sync_event_received),
                     (gpointer) ctk_gvo_sync);

} /* register_for_gvo_sync_events() */
GtkWidget* ctk_image_sliders_new(NvCtrlAttributeHandle *handle,
                                 CtkConfig *ctk_config, CtkEvent *ctk_event,
                                 GtkWidget *reset_button,
                                 char *name)
{
    CtkImageSliders *ctk_image_sliders;

    GObject *object;

    GtkWidget *frame;
    GtkWidget *vbox;
    ReturnStatus status;
    gint val;

    /*
     * now that we know that we will have atleast one attribute,
     * create the object
     */

    object = g_object_new(CTK_TYPE_IMAGE_SLIDERS, NULL);
    if (!object) return NULL;

    ctk_image_sliders = CTK_IMAGE_SLIDERS(object);
    ctk_image_sliders->handle = handle;
    ctk_image_sliders->ctk_config = ctk_config;
    ctk_image_sliders->ctk_event = ctk_event;
    ctk_image_sliders->reset_button = reset_button;
    ctk_image_sliders->name = name;

    /* create the frame and vbox */

    frame = gtk_frame_new(NULL);
    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
    gtk_container_add(GTK_CONTAINER(frame), vbox);
    gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
    ctk_image_sliders->frame = frame;

    /* Digital Vibrance */

    ctk_image_sliders->digital_vibrance =
        add_scale(ctk_config,
                  NV_CTRL_DIGITAL_VIBRANCE, "Digital Vibrance",
                  __digital_vibrance_help, G_TYPE_INT,
                  0, /* default value */
                  ctk_image_sliders);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_DIGITAL_VIBRANCE),
                     G_CALLBACK(scale_value_received),
                     (gpointer) ctk_image_sliders);

    gtk_box_pack_start(GTK_BOX(vbox), ctk_image_sliders->digital_vibrance,
                       TRUE, TRUE, 0);

    /* Image Sharpening */

    status = NvCtrlGetAttribute(ctk_image_sliders->handle,
                                NV_CTRL_IMAGE_SHARPENING_DEFAULT,
                                &val);
    if (status != NvCtrlSuccess) {
        val = 0;
    }

    ctk_image_sliders->image_sharpening =
        add_scale(ctk_config,
                  NV_CTRL_IMAGE_SHARPENING, "Image Sharpening",
                  __image_sharpening_help, G_TYPE_INT, val, ctk_image_sliders);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_IMAGE_SHARPENING),
                     G_CALLBACK(scale_value_received),
                     (gpointer) ctk_image_sliders);

    gtk_box_pack_start(GTK_BOX(vbox), ctk_image_sliders->image_sharpening,
                       TRUE, TRUE, 0);

    gtk_widget_show_all(GTK_WIDGET(object));

    /* update the GUI */

    ctk_image_sliders_setup(ctk_image_sliders);

    return GTK_WIDGET(object);

} /* ctk_image_sliders_new() */
Exemple #5
0
GtkWidget* ctk_ecc_new(CtrlTarget *ctrl_target,
                       CtkConfig *ctk_config,
                       CtkEvent *ctk_event)
{
    GObject *object;
    CtkEcc *ctk_ecc;
    GtkWidget *hbox, *hbox2, *vbox, *hsep, *hseparator, *table;
    GtkWidget *banner, *label, *eventbox;
    int64_t sbit_error;
    int64_t aggregate_sbit_error;
    int64_t dbit_error;
    int64_t aggregate_dbit_error;
    gint ecc_config_supported;
    gint val, row = 0;
    gboolean sbit_error_available;
    gboolean aggregate_sbit_error_available;
    gboolean dbit_error_available;
    gboolean aggregate_dbit_error_available;
    gboolean ecc_enabled;
    gboolean ecc_default_status;
    ReturnStatus ret;
    gchar *ecc_enabled_string;
    gchar *str = NULL;

    /* make sure we have a handle */

    g_return_val_if_fail((ctrl_target != NULL) &&
                         (ctrl_target->h != NULL), NULL);

    /*
     * check if ECC support available.
     */

    ret = NvCtrlGetAttribute(ctrl_target,
                             NV_CTRL_GPU_ECC_SUPPORTED,
                             &val);
    if (ret != NvCtrlSuccess || val != NV_CTRL_GPU_ECC_SUPPORTED_TRUE) {
        return NULL;
    }

    /* create the CtkEcc object */

    object = g_object_new(CTK_TYPE_ECC, NULL);

    ctk_ecc = CTK_ECC(object);
    ctk_ecc->ctrl_target = ctrl_target;
    ctk_ecc->ctk_config = ctk_config;
    ctk_ecc->ecc_toggle_warning_dlg_shown = FALSE;

    sbit_error_available = TRUE;
    dbit_error_available = TRUE;
    aggregate_sbit_error_available = TRUE;
    aggregate_dbit_error_available = TRUE;

    sbit_error = 0;
    dbit_error = 0;
    aggregate_sbit_error = 0;
    aggregate_dbit_error = 0;

    /* Query ECC Status */

    ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_ECC_STATUS,
                             &val);
    if (ret != NvCtrlSuccess || val == NV_CTRL_GPU_ECC_STATUS_DISABLED) {
        ecc_enabled = FALSE;
        ecc_enabled_string = "Disabled";
    } else {
        ecc_enabled = TRUE;
        ecc_enabled_string = "Enabled";
    }
    ctk_ecc->ecc_enabled = ecc_enabled;

    /* Query ECC Configuration */

    ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_ECC_CONFIGURATION,
                             &val);
    if (ret != NvCtrlSuccess ||
            val == NV_CTRL_GPU_ECC_CONFIGURATION_DISABLED) {
        ctk_ecc->ecc_configured = FALSE;
    } else {
        ctk_ecc->ecc_configured = TRUE;
    }

    /* get default status */
    ret = NvCtrlGetAttribute(ctrl_target,
                             NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION,
                             &val);
    if (ret != NvCtrlSuccess ||
            val == NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_DISABLED) {
        ecc_default_status = FALSE;
    } else {
        ecc_default_status = TRUE;
    }

    /* Query ECC errors */

    ret = NvCtrlGetAttribute64(ctrl_target,
                               NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS,
                               &sbit_error);
    if (ret != NvCtrlSuccess) {
        sbit_error_available = FALSE;
    }
    ret = NvCtrlGetAttribute64(ctrl_target,
                               NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS,
                               &dbit_error);
    if (ret != NvCtrlSuccess) {
        dbit_error_available = FALSE;
    }
    ret = NvCtrlGetAttribute64(ctrl_target,
                               NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS,
                               &aggregate_sbit_error);
    if (ret != NvCtrlSuccess) {
        aggregate_sbit_error_available = FALSE;
    }
    ret = NvCtrlGetAttribute64(ctrl_target,
                               NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS,
                               &aggregate_dbit_error);
    if (ret != NvCtrlSuccess) {
        aggregate_dbit_error_available = FALSE;
    }
    ctk_ecc->sbit_error_available = sbit_error_available;
    ctk_ecc->aggregate_sbit_error_available = aggregate_sbit_error_available;
    ctk_ecc->dbit_error_available = dbit_error_available;
    ctk_ecc->aggregate_dbit_error_available = aggregate_dbit_error_available;
    /* Query ECC configuration supported */

    ret = NvCtrlGetAttribute(ctrl_target,
                             NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED,
                             &ecc_config_supported);
    if (ret != NvCtrlSuccess) {
        ecc_config_supported = 0;
    }

    /* set container properties for the CtkEcc widget */

    gtk_box_set_spacing(GTK_BOX(ctk_ecc), 5);

    /* banner */

    banner = ctk_banner_image_new(BANNER_ARTWORK_GPU);
    gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);

    vbox = gtk_vbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(object), vbox, TRUE, TRUE, 0);

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

    label = gtk_label_new("ECC Status");
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hseparator = gtk_hseparator_new();
    gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);

    table = gtk_table_new(1, 2, FALSE);
    gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
    gtk_table_set_row_spacings(GTK_TABLE(table), 3);
    gtk_table_set_col_spacings(GTK_TABLE(table), 15);
    gtk_container_set_border_width(GTK_CONTAINER(table), 5);

    /* ECC Status */
    hbox2 = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox2, 0, 1, row, row+1,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

    label = gtk_label_new("ECC:");
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);

    eventbox = gtk_event_box_new();
    gtk_table_attach(GTK_TABLE(table), eventbox, 1, 2, row, row+1,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

    label = gtk_label_new(ecc_enabled_string);
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_container_add(GTK_CONTAINER(eventbox), label);
    ctk_config_set_tooltip(ctk_config, eventbox, __ecc_status_help);
    ctk_ecc->status = label;

    row += 3;

    /* Add ECC Errors */

    if (sbit_error_available && dbit_error_available) {
        ctk_ecc->sbit_error =
            add_table_int_row(ctk_config, table, __sbit_error_help,
                              "Single-bit ECC Errors:", sbit_error,
                              row, ecc_enabled);
        row += 1; // add vertical padding between rows

        ctk_ecc->dbit_error =
            add_table_int_row(ctk_config, table, __dbit_error_help,
                              "Double-bit ECC Errors:", dbit_error,
                              row, ecc_enabled);
        row += 3; // add vertical padding between rows
    }

    if (aggregate_sbit_error_available && aggregate_dbit_error_available) {
        ctk_ecc->aggregate_sbit_error =
            add_table_int_row(ctk_config, table, __aggregate_sbit_error_help,
                              "Aggregate Single-bit ECC Errors:",
                              aggregate_sbit_error, row, ecc_enabled);
        row += 1; // add vertical padding between rows

        ctk_ecc->aggregate_dbit_error =
            add_table_int_row(ctk_config, table, __aggregate_dbit_error_help,
                              "Aggregate Double-bit ECC Errors:",
                              aggregate_dbit_error, row, ecc_enabled);
    }

    /* ECC configuration settings */

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

    label = gtk_label_new("ECC Configuration");
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hsep = gtk_hseparator_new();
    gtk_box_pack_start(GTK_BOX(hbox), hsep, TRUE, TRUE, 5);

    hbox2 = gtk_hbox_new(FALSE, 0);
    ctk_ecc->configuration_status =
        gtk_check_button_new_with_label("Enable ECC");
    gtk_box_pack_start(GTK_BOX(hbox2),
                       ctk_ecc->configuration_status, FALSE, FALSE, 0);
    gtk_container_set_border_width(GTK_CONTAINER(hbox2), 5);
    gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctk_ecc->configuration_status),
                                 ctk_ecc->ecc_configured);
    ctk_config_set_tooltip(ctk_config, ctk_ecc->configuration_status,
                           __configuration_status_help);
    g_signal_connect(G_OBJECT(ctk_ecc->configuration_status), "clicked",
                     G_CALLBACK(ecc_config_button_toggled),
                     (gpointer) ctk_ecc);
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GPU_ECC_CONFIGURATION),
                     G_CALLBACK(ecc_configuration_update_received),
                     (gpointer) ctk_ecc);
    gtk_widget_set_sensitive(ctk_ecc->configuration_status, ecc_config_supported);

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(ctk_ecc), hbox, FALSE, FALSE, 0);

    /* Add buttons */

    if (sbit_error_available && dbit_error_available) {
        ctk_ecc->clear_button = gtk_button_new_with_label("Clear ECC Errors");
        gtk_box_pack_end(GTK_BOX(hbox), ctk_ecc->clear_button, FALSE, FALSE, 0);
        ctk_config_set_tooltip(ctk_config, ctk_ecc->clear_button,
                               __clear_button_help);
        gtk_widget_set_sensitive(ctk_ecc->clear_button, ecc_enabled);
        g_signal_connect(G_OBJECT(ctk_ecc->clear_button), "clicked",
                         G_CALLBACK(clear_ecc_errors_button_clicked),
                         (gpointer) ctk_ecc);
    }

    if (aggregate_sbit_error_available && aggregate_dbit_error_available) {
        ctk_ecc->clear_aggregate_button =
            gtk_button_new_with_label("Clear Aggregate ECC Errors");
        gtk_box_pack_end(GTK_BOX(hbox), ctk_ecc->clear_aggregate_button,
                         FALSE, FALSE, 0);
        ctk_config_set_tooltip(ctk_config, ctk_ecc->clear_button,
                               __clear_aggregate_button_help);
        gtk_widget_set_sensitive(ctk_ecc->clear_aggregate_button, ecc_enabled);
        g_signal_connect(G_OBJECT(ctk_ecc->clear_aggregate_button),
                         "clicked",
                         G_CALLBACK(clear_aggregate_ecc_errors_button_clicked),
                         (gpointer) ctk_ecc);
    }

    ctk_ecc->reset_default_config_button =
        gtk_button_new_with_label("Reset Default Configuration");
    eventbox = gtk_event_box_new();
    gtk_container_add(GTK_CONTAINER(eventbox),
                      ctk_ecc->reset_default_config_button);
    gtk_box_pack_end(GTK_BOX(hbox), eventbox, FALSE, FALSE, 5);
    ctk_config_set_tooltip(ctk_config, ctk_ecc->reset_default_config_button,
                           __reset_default_config_button_help);
    gtk_widget_set_sensitive(ctk_ecc->reset_default_config_button,
                             ecc_config_supported &&
                             (ecc_enabled != ecc_default_status));
    g_signal_connect(G_OBJECT(ctk_ecc->reset_default_config_button),
                     "clicked",
                     G_CALLBACK(reset_default_config_button_clicked),
                     (gpointer) ctk_ecc);

    /* Register a timer callback to update Ecc status info */
    str = g_strdup_printf("ECC Settings (GPU %d)",
                          NvCtrlGetTargetId(ctrl_target));

    ctk_config_add_timer(ctk_ecc->ctk_config,
                         DEFAULT_UPDATE_ECC_STATUS_INFO_TIME_INTERVAL,
                         str,
                         (GSourceFunc) update_ecc_info,
                         (gpointer) ctk_ecc);

    g_free(str);

    gtk_widget_show_all(GTK_WIDGET(ctk_ecc));

    update_ecc_info(ctk_ecc);

    return GTK_WIDGET(ctk_ecc);
}
GtkWidget* ctk_dithering_controls_new(NvCtrlAttributeHandle *handle,
                                      CtkConfig *ctk_config,
                                      CtkEvent *ctk_event,
                                      GtkWidget *reset_button,
                                      char *name)
{
    GObject *object;
    CtkDitheringControls *ctk_dithering_controls;
    GtkWidget *frame, *vbox, *hbox, *label;
    GtkWidget *menu, *table, *menu_item = NULL, *separator;

    /* create the object */
    object = g_object_new(CTK_TYPE_DITHERING_CONTROLS, NULL);
    if (!object) {
        return NULL;
    }

    ctk_dithering_controls = CTK_DITHERING_CONTROLS(object);
    ctk_dithering_controls->handle = handle;
    ctk_dithering_controls->ctk_config = ctk_config;
    ctk_dithering_controls->reset_button = reset_button;
    ctk_dithering_controls->name = strdup(name);

    /* create main dithering box & frame */

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, FRAME_PADDING);
    ctk_dithering_controls->dithering_controls_box = hbox;

    frame = gtk_frame_new("Dithering Controls");
    gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);

    table = gtk_table_new(5, 4, FALSE);
    gtk_container_add(GTK_CONTAINER(frame), table);
    gtk_table_set_row_spacings(GTK_TABLE(table), 5);
    gtk_table_set_col_spacings(GTK_TABLE(table), 15);
    gtk_container_set_border_width(GTK_CONTAINER(table), 5);

    /* Build Dithering widgets & pack them in table */
    /* dropdown list for dithering configuration */
    menu = gtk_menu_new();

    menu_item = gtk_menu_item_new_with_label("Auto");
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    menu_item = gtk_menu_item_new_with_label("Enabled");
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    menu_item = gtk_menu_item_new_with_label("Disabled");
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    ctk_dithering_controls->dithering_config_menu = gtk_option_menu_new();
    gtk_option_menu_set_menu
        (GTK_OPTION_MENU(ctk_dithering_controls->dithering_config_menu),
         menu);
    ctk_config_set_tooltip(ctk_config, 
                           ctk_dithering_controls->dithering_config_menu, 
                           __dithering_config_help);

    g_signal_connect(G_OBJECT(ctk_dithering_controls->dithering_config_menu),
                     "changed", G_CALLBACK(dithering_config_menu_changed),
                     (gpointer) ctk_dithering_controls);

    /* Packing label & dropdown */
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 0, 1,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

    label = gtk_label_new("Dithering: ");
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    gtk_box_pack_start(GTK_BOX(hbox),
                       ctk_dithering_controls->dithering_config_menu,
                       FALSE, FALSE, 0);

    /* Build CurrentDithering widget  */
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 2, 3, 0, 1,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    label = gtk_label_new("Current Dithering: ");
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 3, 4, 0, 1,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    label = gtk_label_new(NULL);
    ctk_dithering_controls->dithering_config_txt = label;
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    /* H-bar 1 */
    vbox = gtk_vbox_new(FALSE, 0);
    separator = gtk_hseparator_new();
    gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), vbox, 0, 4, 1, 2,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

    /* dropdown list for dithering modes - populated in setup */
    ctk_dithering_controls->dithering_mode_menu = gtk_option_menu_new();
    ctk_config_set_tooltip(ctk_config, 
                           ctk_dithering_controls->dithering_mode_menu, 
                           __dithering_mode_help);

    g_signal_connect(G_OBJECT(ctk_dithering_controls->dithering_mode_menu),
                     "changed", G_CALLBACK(dithering_mode_menu_changed),
                     (gpointer) ctk_dithering_controls);


    /* pack the label & drop down */
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 2, 3,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    label = gtk_label_new("Mode: ");
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hbox = gtk_hbox_new(FALSE, 0);
    ctk_dithering_controls->dithering_mode_box = hbox;
    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 2, 3,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    gtk_box_pack_start(GTK_BOX(hbox),
                       ctk_dithering_controls->dithering_mode_menu,
                       FALSE, FALSE, 0);

    /* Build CurrentMode widget  */
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 2, 3, 2, 3,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    label = gtk_label_new("Current Mode: ");
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 3, 4, 2, 3,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    label = gtk_label_new(NULL);
    ctk_dithering_controls->dithering_mode_txt = label;
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    /* H-bar 2 */
    vbox = gtk_vbox_new(FALSE, 0);
    separator = gtk_hseparator_new();
    gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), vbox, 0, 4, 3, 4,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

    /* dithering depth */
    menu = gtk_menu_new();

    menu_item = gtk_menu_item_new_with_label("Auto");
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    menu_item = gtk_menu_item_new_with_label("6 bpc");
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    menu_item = gtk_menu_item_new_with_label("8 bpc");
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    ctk_dithering_controls->dithering_depth_menu = gtk_option_menu_new();
    gtk_option_menu_set_menu
        (GTK_OPTION_MENU(ctk_dithering_controls->dithering_depth_menu),
         menu);
    ctk_config_set_tooltip(ctk_config, 
                           ctk_dithering_controls->dithering_depth_menu, 
                           __dithering_depth_help);

    g_signal_connect(G_OBJECT(ctk_dithering_controls->dithering_depth_menu),
                     "changed", G_CALLBACK(dithering_depth_menu_changed),
                     (gpointer) ctk_dithering_controls);

    /* Packing label & dropdown */
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 4, 5,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

    label = gtk_label_new("Depth: ");
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hbox = gtk_hbox_new(FALSE, 0);
    ctk_dithering_controls->dithering_depth_box = hbox;
    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 4, 5,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    gtk_box_pack_start(GTK_BOX(hbox),
                       ctk_dithering_controls->dithering_depth_menu,
                       FALSE, FALSE, 0);

    /* Build CurrentDitheringDepth widget  */
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 2, 3, 4, 5,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    label = gtk_label_new("Current Depth: ");
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 3, 4, 4, 5,
                     GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
    label = gtk_label_new(NULL);
    ctk_dithering_controls->dithering_depth_txt = label;
    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    gtk_widget_show_all(GTK_WIDGET(object));

    ctk_dithering_controls_setup(ctk_dithering_controls);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_DITHERING),
                     G_CALLBACK(dithering_update_received),
                     (gpointer) ctk_dithering_controls);
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_DITHERING_MODE),
                     G_CALLBACK(dithering_update_received),
                     (gpointer) ctk_dithering_controls);
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_DITHERING_DEPTH),
                     G_CALLBACK(dithering_update_received),
                     (gpointer) ctk_dithering_controls);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING),
                     G_CALLBACK(dithering_update_received),
                     (gpointer) ctk_dithering_controls);
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING_MODE),
                     G_CALLBACK(dithering_update_received),
                     (gpointer) ctk_dithering_controls);
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING_DEPTH),
                     G_CALLBACK(dithering_update_received),
                     (gpointer) ctk_dithering_controls);

    return GTK_WIDGET(object);

} /* ctk_dithering_controls_new() */
GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle,
                                      CtkConfig *ctk_config,
                                      CtkEvent *ctk_event,
                                      unsigned int display_device_mask,
                                      char *name)
{
    GObject *object;
    CtkDisplayDeviceDfp *ctk_display_device_dfp;
    GtkWidget *banner;
    GtkWidget *frame;
    GtkWidget *hbox, *vbox, *tmpbox;
    GtkWidget *eventbox;

    GtkWidget *button;
    GtkWidget *radio0;
    GtkWidget *radio1;
    GtkWidget *radio2;
    GtkWidget *alignment;
    
    GtkWidget *table;
    ReturnStatus ret1, ret2;
    gint val_target, val_method;

    object = g_object_new(CTK_TYPE_DISPLAY_DEVICE_DFP, NULL);
    if (!object) return NULL;

    ctk_display_device_dfp = CTK_DISPLAY_DEVICE_DFP(object);
    ctk_display_device_dfp->handle = handle;
    ctk_display_device_dfp->ctk_event = ctk_event;
    ctk_display_device_dfp->ctk_config = ctk_config;
    ctk_display_device_dfp->display_device_mask = display_device_mask;
    ctk_display_device_dfp->name = g_strdup(name);

    /* cache the default scaling target & method values */
    ret1 =
        NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle,
                                  ctk_display_device_dfp->display_device_mask,
                                  NV_CTRL_GPU_SCALING_DEFAULT_TARGET,
                                  &val_target);
    ret2 =
        NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle,
                                  ctk_display_device_dfp->display_device_mask,
                                  NV_CTRL_GPU_SCALING_DEFAULT_METHOD,
                                  &val_method);

    if (ret1 != NvCtrlSuccess || ret2 != NvCtrlSuccess ||
        val_target == NV_CTRL_GPU_SCALING_TARGET_INVALID ||
        val_method == NV_CTRL_GPU_SCALING_METHOD_INVALID) {
        val_target = NV_CTRL_GPU_SCALING_TARGET_FLATPANEL_BEST_FIT;
        val_method = NV_CTRL_GPU_SCALING_METHOD_STRETCHED;
    }

    ctk_display_device_dfp->default_scaling_target = val_target;
    ctk_display_device_dfp->default_scaling_method = val_method;

    gtk_box_set_spacing(GTK_BOX(object), 10);

    /* banner */

    banner = ctk_banner_image_new(BANNER_ARTWORK_DFP);
    gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);
    
    /*
     * create the reset button (which we need while creating the
     * controls in this page so that we can set the button's
     * sensitivity), though we pack it at the bottom of the page
     */

    ctk_display_device_dfp->reset_button =
        gtk_button_new_with_label("Reset Hardware Defaults");

    alignment = gtk_alignment_new(1, 1, 0, 0);
    gtk_container_add(GTK_CONTAINER(alignment),
                      ctk_display_device_dfp->reset_button);
    gtk_box_pack_end(GTK_BOX(object), alignment, TRUE, TRUE, 0);

    g_signal_connect(G_OBJECT(ctk_display_device_dfp->reset_button),
                     "clicked", G_CALLBACK(reset_button_clicked),
                     (gpointer) ctk_display_device_dfp);
    
    ctk_config_set_tooltip(ctk_config, ctk_display_device_dfp->reset_button,
                           "The Reset Hardware Defaults button restores "
                           "the DFP settings to their default values.");

    /* create the hbox to store dfp info, scaling */

    hbox = gtk_hbox_new(FALSE, FRAME_PADDING);
    gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, FRAME_PADDING);

    /* DFP info */

    frame = gtk_frame_new("Flat Panel Information");
    gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
    
    /*
     * insert a vbox between the frame and the widgets, so that the
     * widgets don't expand to fill all of the space within the
     * frame
     */
    
    tmpbox = gtk_vbox_new(FALSE, 5);
    gtk_container_add(GTK_CONTAINER(frame), tmpbox);
    
    /* Make the txt widgets that will get updated */
    ctk_display_device_dfp->txt_chip_location = gtk_label_new("");
    ctk_display_device_dfp->txt_link = gtk_label_new("");
    ctk_display_device_dfp->txt_signal = gtk_label_new("");
    ctk_display_device_dfp->txt_native_resolution = gtk_label_new("");
    ctk_display_device_dfp->txt_best_fit_resolution = gtk_label_new("");
    ctk_display_device_dfp->txt_frontend_resolution = gtk_label_new("");
    ctk_display_device_dfp->txt_backend_resolution = gtk_label_new("");
    ctk_display_device_dfp->txt_refresh_rate = gtk_label_new("");

    /* Add information widget lines */
    {
        typedef struct {
            GtkWidget *label;
            GtkWidget *txt;
            const gchar *tooltip;
        } TextLineInfo;

        TextLineInfo lines[] = {
            {
                gtk_label_new("Chip location:"),
                ctk_display_device_dfp->txt_chip_location,
                NULL
            },
            {
                gtk_label_new("Connection link:"),
                ctk_display_device_dfp->txt_link,
                NULL
            },
            {
                gtk_label_new("Signal:"),
                ctk_display_device_dfp->txt_signal,
                NULL
            },
            {
                gtk_label_new("Native Resolution:"),
                ctk_display_device_dfp->txt_native_resolution,
                __native_res_help,
            },
            {
                gtk_label_new("Best Fit Resolution:"),
                ctk_display_device_dfp->txt_best_fit_resolution,
                __best_fit_res_help,
            },
            {
                gtk_label_new("Frontend Resolution:"),
                ctk_display_device_dfp->txt_frontend_resolution,
                __frontend_res_help,
            },
            {
                gtk_label_new("Backend Resolution:"),
                ctk_display_device_dfp->txt_backend_resolution,
                __backend_res_help,
            },
            {
                gtk_label_new("Refresh Rate:"),
                ctk_display_device_dfp->txt_refresh_rate,
                __refresh_rate_help,
            },
            { NULL, NULL, NULL }
        };
        int i;

        GtkRequisition req;
        int max_width;

        /* Compute max width of lables and setup text alignments */
        max_width = 0;
        for (i = 0; lines[i].label; i++) {
            gtk_misc_set_alignment(GTK_MISC(lines[i].label), 0.0f, 0.5f);
            gtk_misc_set_alignment(GTK_MISC(lines[i].txt), 0.0f, 0.5f);

            gtk_widget_size_request(lines[i].label, &req);
            if (max_width < req.width) {
                max_width = req.width;
            }
        }

        /* Pack labels */
        for (i = 0; lines[i].label; i++) {
            GtkWidget *tmphbox;

            /* Add separators */
            if (i == 3 || i == 5 || i == 7) {
                GtkWidget *separator = gtk_hseparator_new();
                gtk_box_pack_start(GTK_BOX(tmpbox), separator,
                                   FALSE, FALSE, 0);
            }

            /* Set the label's width */
            gtk_widget_set_size_request(lines[i].label, max_width, -1);

            /* add the widgets for this line */
            tmphbox = gtk_hbox_new(FALSE, 5);
            gtk_box_pack_start(GTK_BOX(tmphbox), lines[i].label,
                               FALSE, TRUE, 5);
            gtk_box_pack_start(GTK_BOX(tmphbox), lines[i].txt,
                               FALSE, TRUE, 5);

            /* Include tooltips */
            if (!lines[i].tooltip) {
                gtk_box_pack_start(GTK_BOX(tmpbox), tmphbox, FALSE, FALSE, 0);
            } else {
                eventbox = gtk_event_box_new();
                gtk_container_add(GTK_CONTAINER(eventbox), tmphbox);
                ctk_config_set_tooltip(ctk_config, eventbox, lines[i].tooltip);
                gtk_box_pack_start(GTK_BOX(tmpbox), eventbox, FALSE, FALSE, 0);
            }
        }
    }

    
    /* Flat Panel Scaling */
    
    frame = gtk_frame_new("Flat Panel Scaling");
    eventbox = gtk_event_box_new();
    gtk_container_add(GTK_CONTAINER(eventbox), frame);
    gtk_box_pack_start(GTK_BOX(hbox), eventbox, FALSE, FALSE, 0);
    ctk_display_device_dfp->scaling_frame = eventbox;
    
    ctk_config_set_tooltip(ctk_config, eventbox, __scaling_help);

    vbox = gtk_vbox_new(FALSE, FRAME_PADDING);
    gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
    gtk_container_add(GTK_CONTAINER(frame), vbox);

    button = gtk_check_button_new_with_label("Force Full GPU Scaling");
    ctk_display_device_dfp->scaling_gpu_button = button;
    ctk_config_set_tooltip(ctk_config, button, __force_gpu_scaling_help);

    gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);

    table = gtk_table_new(1, 2, FALSE);
    gtk_table_set_row_spacings(GTK_TABLE(table), 6);
    gtk_table_set_col_spacings(GTK_TABLE(table), 15);
    
    gtk_container_set_border_width(GTK_CONTAINER(table), 5);
    
    ctk_display_device_dfp->txt_scaling = 
        add_table_row(table, 0,
                      0, 0.5, "Scaling:",
                      0, 0.5,  "");

    gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);

    frame = gtk_frame_new("GPU Scaling Method");
    gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
    vbox = gtk_vbox_new(FALSE, FRAME_PADDING);
    gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
    gtk_container_add(GTK_CONTAINER(frame), vbox);

    g_signal_connect(G_OBJECT(button), "toggled",
                     G_CALLBACK(dfp_scaling_changed),
                     (gpointer) ctk_display_device_dfp);
    
    radio0 = make_scaling_radio_button
        (ctk_display_device_dfp, vbox, NULL, "Stretched",
         NV_CTRL_GPU_SCALING_METHOD_STRETCHED);
    
    radio1 = make_scaling_radio_button
        (ctk_display_device_dfp, vbox, radio0, "Centered",
         NV_CTRL_GPU_SCALING_METHOD_CENTERED);
    
    radio2 = make_scaling_radio_button
        (ctk_display_device_dfp, vbox, radio1, "Aspect Ratio Scaled",
         NV_CTRL_GPU_SCALING_METHOD_ASPECT_SCALED);
    
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GPU_SCALING),
                     G_CALLBACK(dfp_update_received),
                     (gpointer) ctk_display_device_dfp);

    /* pack the color controls */

    ctk_display_device_dfp->color_controls =
        ctk_color_controls_new(handle, ctk_config, ctk_event,
                                   ctk_display_device_dfp->reset_button,
                                   display_device_mask, name);

    if (ctk_display_device_dfp->color_controls) {
        gtk_box_pack_start(GTK_BOX(object),
                           ctk_display_device_dfp->color_controls,
                           FALSE, FALSE, 0);
    }

    /* pack the dithering controls */

    ctk_display_device_dfp->dithering_controls =
        ctk_dithering_controls_new(handle, ctk_config, ctk_event,
                                   ctk_display_device_dfp->reset_button,
                                   display_device_mask, name);

    if (ctk_display_device_dfp->dithering_controls) {
        gtk_box_pack_start(GTK_BOX(object),
                           ctk_display_device_dfp->dithering_controls,
                           FALSE, FALSE, 0);
    }

    /* pack the image sliders */
    
    ctk_display_device_dfp->image_sliders =
        ctk_image_sliders_new(handle, ctk_config, ctk_event,
                              ctk_display_device_dfp->reset_button,
                              display_device_mask, name);
    if (ctk_display_device_dfp->image_sliders) {
        gtk_box_pack_start(GTK_BOX(object),
                           ctk_display_device_dfp->image_sliders,
                           FALSE, FALSE, 0);
    }

    /* pack the EDID button */

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
    ctk_display_device_dfp->edid_box = hbox;
    
    /* show the page */

    gtk_widget_show_all(GTK_WIDGET(object));

    /* Update the GUI */

    update_display_enabled_flag(ctk_display_device_dfp->handle,
                                &ctk_display_device_dfp->display_enabled,
                                ctk_display_device_dfp->display_device_mask);

    ctk_display_device_dfp_setup(ctk_display_device_dfp);
    
    /* handle enable/disable events on the display device */

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
                     G_CALLBACK(enabled_displays_received),
                     (gpointer) ctk_display_device_dfp);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GPU_SCALING_ACTIVE),
                     G_CALLBACK(info_update_received),
                     (gpointer) ctk_display_device_dfp);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_DFP_SCALING_ACTIVE),
                     G_CALLBACK(info_update_received),
                     (gpointer) ctk_display_device_dfp);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_FRONTEND_RESOLUTION),
                     G_CALLBACK(info_update_received),
                     (gpointer) ctk_display_device_dfp);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION),
                     G_CALLBACK(info_update_received),
                     (gpointer) ctk_display_device_dfp);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_BACKEND_RESOLUTION),
                     G_CALLBACK(info_update_received),
                     (gpointer) ctk_display_device_dfp);
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_REFRESH_RATE),
                     G_CALLBACK(info_update_received),
                     (gpointer) ctk_display_device_dfp);

    return GTK_WIDGET(object);

} /* ctk_display_device_dfp_new() */
GtkWidget* ctk_display_device_new(CtrlTarget *ctrl_target,
                                  CtkConfig *ctk_config,
                                  CtkEvent *ctk_event,
                                  CtkEvent *ctk_event_gpu,
                                  char *name,
                                  char *typeBaseName,
                                  ParsedAttribute *p)
{
    GObject *object;
    CtkDisplayDevice *ctk_object;
    GtkWidget *banner;
    GtkWidget *hbox, *tmpbox;

    GtkWidget *alignment;
    GtkWidget *notebook;
    GtkWidget *nbox;
    GtkWidget *align;
    GtkWidget *label;
    GtkWidget *hseparator;
    GtkWidget *button;
    gchar *str;
    int i;

    object = g_object_new(CTK_TYPE_DISPLAY_DEVICE, NULL);
    if (!object) return NULL;

    ctk_object = CTK_DISPLAY_DEVICE(object);
    ctk_object->ctrl_target = ctrl_target;
    ctk_object->ctk_event = ctk_event;
    ctk_object->ctk_event_gpu = ctk_event_gpu;
    ctk_object->ctk_config = ctk_config;
    ctk_object->name = g_strdup(name);
    ctk_object->color_correction_available = FALSE;

    gtk_box_set_spacing(GTK_BOX(object), 10);

    /* Banner */

    if (strcmp(typeBaseName, "CRT") == 0) {
        banner = ctk_banner_image_new(BANNER_ARTWORK_CRT);
    } else {
        banner = ctk_banner_image_new(BANNER_ARTWORK_DFP);
    }
    gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);

    /* Create tabbed notebook for widget */

    notebook = gtk_notebook_new();
    gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
    gtk_box_pack_start(GTK_BOX(object), notebook, TRUE, TRUE, 0);

    /* Create first tab for device info */

    nbox = gtk_vbox_new(FALSE, FRAME_PADDING);
    gtk_container_set_border_width(GTK_CONTAINER(nbox), FRAME_PADDING);
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), nbox,
                             gtk_label_new("Information"));


    /* Device info */

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(nbox), hbox, FALSE, FALSE, 0);

    label = gtk_label_new("Display Device Information");
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hseparator = gtk_hseparator_new();
    gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);


    /* create the hbox to store device info */

    hbox = gtk_hbox_new(FALSE, FRAME_PADDING);
    gtk_box_pack_start(GTK_BOX(nbox), hbox, FALSE, FALSE, FRAME_PADDING);

    /*
     * insert a vbox between the frame and the widgets, so that the
     * widgets don't expand to fill all of the space within the
     * frame
     */

    tmpbox = gtk_vbox_new(FALSE, FRAME_PADDING);
    gtk_container_set_border_width(GTK_CONTAINER(tmpbox), FRAME_PADDING);
    gtk_container_add(GTK_CONTAINER(hbox), tmpbox);

    /* Create and add the information widgets */

    ctk_object->num_info_entries = ARRAY_LEN(__info_entry_data);
    ctk_object->info_entries = calloc(ctk_object->num_info_entries,
                                      sizeof(InfoEntry));
    if (!ctk_object->info_entries) {
        ctk_object->num_info_entries = 0;
    }

    for (i = 0; i < ctk_object->num_info_entries; i++) {
        InfoEntryData *entryData = __info_entry_data+i;
        InfoEntry *entry = ctk_object->info_entries+i;
        gchar *str;

        entry->ctk_object = ctk_object;
        str = g_strconcat(entryData->str, ":", NULL);
        entry->label = gtk_label_new(str);
        g_free(str);

        entry->txt = gtk_label_new("");

        gtk_misc_set_alignment(GTK_MISC(entry->label), 0.0f, 0.5f);
        gtk_misc_set_alignment(GTK_MISC(entry->txt), 0.0f, 0.5f);

        ctk_config_set_tooltip(ctk_config,
                               entry->label,
                               *(entryData->tooltip));
        ctk_config_set_tooltip(ctk_config,
                               entry->txt,
                               *(entryData->tooltip));

        entry->hbox = gtk_hbox_new(FALSE, FRAME_PADDING);
        gtk_box_pack_start(GTK_BOX(entry->hbox), entry->label,
                           FALSE, TRUE, FRAME_PADDING);
        gtk_box_pack_start(GTK_BOX(entry->hbox), entry->txt,
                           FALSE, TRUE, FRAME_PADDING);

        gtk_box_pack_start(GTK_BOX(tmpbox), entry->hbox, FALSE, FALSE, 0);
    }

    /* pack the EDID button */

    ctk_object->edid = ctk_edid_new(ctrl_target,
                                    ctk_object->ctk_config,
                                    ctk_object->ctk_event,
                                    ctk_object->name);

    hbox = gtk_hbox_new(FALSE, 0);
    align = gtk_alignment_new(0, 1, 1, 1);
    gtk_container_add(GTK_CONTAINER(align), hbox);
    gtk_box_pack_end(GTK_BOX(nbox), align, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), ctk_object->edid, TRUE, TRUE, 0);

    /*
     * Create layout for second tab for controls but don't add the tab until we
     * make sure it's required
     */

    nbox = gtk_vbox_new(FALSE, FRAME_PADDING);
    gtk_container_set_border_width(GTK_CONTAINER(nbox), FRAME_PADDING);

    /* pack the reset button */

    button = gtk_button_new_with_label("Reset Hardware Defaults");
    str = ctk_help_create_reset_hardware_defaults_text(typeBaseName,
                                                       name);
    ctk_config_set_tooltip(ctk_config, button, str);
    ctk_object->reset_button = button;

    alignment = gtk_alignment_new(1, 1, 0, 0);
    gtk_container_add(GTK_CONTAINER(alignment), button);
    gtk_box_pack_end(GTK_BOX(nbox), alignment, FALSE, FALSE, 0);

    /* pack the color controls */

    ctk_object->color_controls =
        ctk_color_controls_new(ctrl_target, ctk_config, ctk_event,
                               ctk_object->reset_button, name);

    if (ctk_object->color_controls) {
        gtk_box_pack_start(GTK_BOX(nbox), ctk_object->color_controls,
                           FALSE, FALSE, 0);
    }

    /* pack the dithering controls */

    ctk_object->dithering_controls =
        ctk_dithering_controls_new(ctrl_target, ctk_config, ctk_event,
                                   ctk_object->reset_button, name);

    if (ctk_object->dithering_controls) {
        gtk_box_pack_start(GTK_BOX(nbox), ctk_object->dithering_controls,
                           FALSE, FALSE, 0);
    }

    /* pack the image sliders */

    ctk_object->image_sliders =
        ctk_image_sliders_new(ctrl_target, ctk_config, ctk_event,
                              ctk_object->reset_button, name);
    if (ctk_object->image_sliders) {
        gtk_box_pack_start(GTK_BOX(nbox), ctk_object->image_sliders,
                           FALSE, FALSE, 0);
    }

    /* If no controls are created, don't add a controls tab */

    if (ctk_object->color_controls ||
        ctk_object->dithering_controls ||
        ctk_object->image_sliders) {
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), nbox,
                                 gtk_label_new("Controls"));
    }

    /*
     * Show all widgets on this page so far. After this, the color correction
     * tab and other widgets can control their own visibility.
     */

    gtk_widget_show_all(GTK_WIDGET(object));

    /* add the color correction tab if RandR is available */

    add_color_correction_tab(ctk_object, ctk_config, ctk_event, notebook, p);

    /* Update the GUI */

    display_device_setup(ctk_object);

    /* Listen to events */

    g_signal_connect(G_OBJECT(ctk_object->reset_button),
                     "clicked", G_CALLBACK(reset_button_clicked),
                     (gpointer) ctk_object);

    g_signal_connect(G_OBJECT(ctk_event_gpu),
                     CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
                     G_CALLBACK(enabled_displays_received),
                     (gpointer) ctk_object);

    for (i = 0; i < ctk_object->num_info_entries; i++) {
        InfoEntryData *entryData = __info_entry_data+i;
        InfoEntry *entry = ctk_object->info_entries+i;

        if (entryData->register_events_func) {
            entryData->register_events_func(entry);
        }
    }

    return GTK_WIDGET(object);

} /* ctk_display_device_new() */
GtkWidget* ctk_xvideo_new(NvCtrlAttributeHandle *handle,
                          CtkConfig *ctk_config,
                          CtkEvent *ctk_event)
{
    GObject *object;
    CtkXVideo *ctk_xvideo;
    GtkWidget *banner;
    GtkWidget *frame;
    GtkWidget *alignment;
    GtkWidget *hbox;
    GtkWidget *label;
    GtkWidget *vbox;
    GtkWidget *button;
    int sync_mask;
    int xv_overlay_present, xv_texture_present, xv_blitter_present;
    ReturnStatus ret;

    /*
     * before we do anything else, determine if any of the Xv adapters
     * are present
     */
    
    ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_EXT_XV_OVERLAY_PRESENT,
                             &xv_overlay_present);
    
    if (ret != NvCtrlSuccess) xv_overlay_present = FALSE;
    
    ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_EXT_XV_TEXTURE_PRESENT,
                             &xv_texture_present);

    if (ret != NvCtrlSuccess) xv_texture_present = FALSE;
    
    ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_EXT_XV_BLITTER_PRESENT,
                             &xv_blitter_present);
    
    if (ret != NvCtrlSuccess) xv_blitter_present = FALSE;
    
    if (!xv_overlay_present && !xv_texture_present && !xv_blitter_present) {
        return NULL;
    }
    
    
    /* create the XVideo widget */
    
    object = g_object_new(CTK_TYPE_XVIDEO, NULL);
    ctk_xvideo = CTK_XVIDEO(object);
    
    ctk_xvideo->handle = handle;
    ctk_xvideo->ctk_config = ctk_config;
    ctk_xvideo->active_attributes = 0;
    
    gtk_box_set_spacing(GTK_BOX(ctk_xvideo), 10);
    
    
    /* Create button, but don't pack it, yet */

    label = gtk_label_new("Reset Hardware Defaults");
    hbox = gtk_hbox_new(FALSE, 0);
    button = gtk_button_new();

    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 15);
    gtk_container_add(GTK_CONTAINER(button), hbox);
    
    g_signal_connect(G_OBJECT(button), "clicked",
                     G_CALLBACK(reset_defaults), (gpointer) ctk_xvideo);
    
    ctk_config_set_tooltip(ctk_config, button, __reset_button_help);
    
    /* Video film banner */
    
    banner = ctk_banner_image_new(BANNER_ARTWORK_XVIDEO);
    gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);

    
    /* XVideo Overlay sliders */
    
    if (xv_overlay_present) {
        
        frame = gtk_frame_new("Video Overlay Adaptor");
        gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
        
        vbox = gtk_vbox_new(FALSE, 5);
        gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
        gtk_container_add(GTK_CONTAINER(frame), vbox);
        
        ctk_xvideo->overlay_saturation =
            create_slider(ctk_xvideo, vbox, button, "Saturation",
                          __xv_overlay_saturation_help,
                          NV_CTRL_ATTR_XV_OVERLAY_SATURATION,
                          __XV_OVERLAY_SATURATION);
        
        ctk_xvideo->overlay_contrast =
            create_slider(ctk_xvideo, vbox, button, "Contrast",
                          __xv_overlay_contrast_help,
                          NV_CTRL_ATTR_XV_OVERLAY_CONTRAST,
                          __XV_OVERLAY_CONTRAST);
        
        ctk_xvideo->overlay_brightness =
            create_slider(ctk_xvideo, vbox, button, "Brightness",
                          __xv_overlay_brightness_help,
                          NV_CTRL_ATTR_XV_OVERLAY_BRIGHTNESS,
                          __XV_OVERLAY_BRIGHTNESS);
        
        ctk_xvideo->overlay_hue =
            create_slider(ctk_xvideo, vbox, button, "Hue",
                          __xv_overlay_hue_help,
                          NV_CTRL_ATTR_XV_OVERLAY_HUE,
                          __XV_OVERLAY_HUE);
    }

    /* XVideo Texture */

    if (xv_texture_present) {
        
        frame = gtk_frame_new("Video Texture Adaptor");
        gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
        
        vbox = gtk_vbox_new(FALSE, 5);
        gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
        gtk_container_add(GTK_CONTAINER(frame), vbox);
        
        ctk_xvideo->texture_sync_to_blank =
            create_check_button(ctk_xvideo, vbox, button, "Sync to VBlank",
                                __xv_texture_sync_to_vblank_help,
                                NV_CTRL_ATTR_XV_TEXTURE_SYNC_TO_VBLANK,
                                __XV_TEXTURE_SYNC_TO_VBLANK);
        
        ctk_xvideo->texture_brightness =
            create_slider(ctk_xvideo, vbox, button, "Brightness",
                          __xv_texture_brightness_help,
                          NV_CTRL_ATTR_XV_TEXTURE_BRIGHTNESS,
                          __XV_TEXTURE_BRIGHTNESS);
        
        ctk_xvideo->texture_contrast =
            create_slider(ctk_xvideo, vbox, button, "Contrast",
                          __xv_texture_contrast_help,
                          NV_CTRL_ATTR_XV_TEXTURE_CONTRAST,
                          __XV_TEXTURE_CONTRAST);

        ctk_xvideo->texture_hue =
            create_slider(ctk_xvideo, vbox, button, "Hue",
                          __xv_texture_hue_help,
                          NV_CTRL_ATTR_XV_TEXTURE_HUE,
                          __XV_TEXTURE_HUE);
        
        ctk_xvideo->texture_saturation =
            create_slider(ctk_xvideo, vbox, button, "Saturation",
                          __xv_texture_saturation_help,
                          NV_CTRL_ATTR_XV_TEXTURE_SATURATION,
                          __XV_TEXTURE_SATURATION);
    
    }
    
    /* XVideo Blitter */

    if (xv_blitter_present) {

        frame = gtk_frame_new("Video Blitter Adaptor Settings");
        gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
        
        vbox = gtk_vbox_new(FALSE, 5);
        gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
        gtk_container_add(GTK_CONTAINER(frame), vbox);
        
        ctk_xvideo->blitter_sync_to_blank =
            create_check_button(ctk_xvideo,
                                vbox,
                                button,
                                "Sync to VBlank",
                                __xv_blitter_sync_to_vblank_help,
                                NV_CTRL_ATTR_XV_BLITTER_SYNC_TO_VBLANK,
                                __XV_BLITTER_SYNC_TO_VBLANK);

    }

    /* Sync to display selection */
    if (xv_texture_present || xv_blitter_present) {
        ret = NvCtrlGetAttribute(handle,
                                 NV_CTRL_XV_SYNC_TO_DISPLAY,
                                 &sync_mask);
        if (ret == NvCtrlSuccess) {
            int enabled;
            ret = NvCtrlGetAttribute(handle, 
                                     NV_CTRL_ENABLED_DISPLAYS,
                                     &enabled);
            if (ret == NvCtrlSuccess) {

                GtkWidget *radio[24], *prev_radio;
                int i, n, current = -1, mask;
                char *name, *type;
                gchar *name_str;
                frame = gtk_frame_new("Sync to this display device");
                gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);

                vbox = gtk_vbox_new(FALSE, 5);
                gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
                gtk_container_add(GTK_CONTAINER(frame), vbox);
                ctk_xvideo->xv_sync_to_display_button_box = vbox;

                for (n=0, i = 0; i < 24; i++) {

                    mask = 1 << i;
                    if (!(enabled & mask)) continue;

                    /* get the name of the display device */

                    ret = NvCtrlGetStringDisplayAttribute(handle, mask,
                                              NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
                                              &name);

                    if ((ret != NvCtrlSuccess) || (!name)) {
                        name = g_strdup("Unknown");
                    }

                    /* get the display device type */

                    type = display_device_mask_to_display_device_name(mask);

                    name_str = g_strdup_printf("%s (%s)", name, type);
                    XFree(name);
                    free(type);

                    if (n==0) {
                        prev_radio = NULL;
                    } else {
                        prev_radio = radio[n-1];
                    } 
                    radio[n] = xv_sync_to_display_radio_button_add(ctk_xvideo, 
                                                                   prev_radio,
                                                                   name_str,
                                                                   mask, n);
                    g_free(name_str);
                    ctk_config_set_tooltip(ctk_config, radio[n],
                                           __xv_sync_to_display_help);    

                    if (mask == sync_mask) {
                        current = n;
                    }

                    n++;
                    ctk_xvideo->active_attributes |= __XV_SYNC_TO_DISPLAY;
                }

                g_signal_connect(G_OBJECT(ctk_event),
                                 CTK_EVENT_NAME(NV_CTRL_XV_SYNC_TO_DISPLAY),
                                 G_CALLBACK(xv_sync_to_display_update_received),
                                 (gpointer) ctk_xvideo);
                g_signal_connect(G_OBJECT(ctk_event),
                                 CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
                                 G_CALLBACK(nv_ctrl_enabled_displays),
                                 (gpointer) ctk_xvideo);
                sensitize_radio_buttons(ctk_xvideo);

                if (current != -1)
                    xv_sync_to_display_update_radio_buttons(ctk_xvideo, current);

            }
        }
    }
    
    /* Reset button */

    sensitize_radio_buttons(ctk_xvideo);
    alignment = gtk_alignment_new(1, 1, 0, 0);
    gtk_container_add(GTK_CONTAINER(alignment), button);
    gtk_box_pack_start(GTK_BOX(object), alignment, TRUE, TRUE, 0);
    
    /* finally, show the widget */

    gtk_widget_show_all(GTK_WIDGET(ctk_xvideo));

    return GTK_WIDGET(ctk_xvideo);
    
} /* ctk_xvideo_new() */
Exemple #10
0
/*
 * ctk_xvideo_new() - constructor for the XVideo widget
 */
GtkWidget* ctk_xvideo_new(CtrlTarget *ctrl_target,
                          CtkConfig *ctk_config,
                          CtkEvent *ctk_event)
{
    GObject *object;
    CtkXVideo *ctk_xvideo;
    GtkWidget *banner;
    GtkWidget *frame;
    GtkWidget *alignment;
    GtkWidget *vbox;
    GtkWidget *hbox;
    GtkWidget *label;
    GtkWidget *hseparator;
    int xv_overlay_present, xv_texture_present, xv_blitter_present;
    int display_id;
    gboolean show_page;
    ReturnStatus ret;
    gchar *current_sync_name;

    /*
     * before we do anything else, determine if any of the Xv adapters
     * are present
     */

    ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_ATTR_EXT_XV_OVERLAY_PRESENT,
                             &xv_overlay_present);
    if (ret != NvCtrlSuccess) {
        xv_overlay_present = FALSE;
    }

    ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_ATTR_EXT_XV_TEXTURE_PRESENT,
                             &xv_texture_present);
    if (ret != NvCtrlSuccess) {
        xv_texture_present = FALSE;
    }

    ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_ATTR_EXT_XV_BLITTER_PRESENT,
                             &xv_blitter_present);
    if (ret != NvCtrlSuccess) {
        xv_blitter_present = FALSE;
    }

    if (!xv_overlay_present && !xv_texture_present && !xv_blitter_present) {
        return NULL;
    }

    /* If nothing to show, bail */

    show_page = FALSE;
    if (xv_texture_present || xv_blitter_present) {
        ret = NvCtrlGetAttribute(ctrl_target,
                                 NV_CTRL_XV_SYNC_TO_DISPLAY_ID,
                                 &display_id);
        if (ret == NvCtrlSuccess) {
            show_page = TRUE;
        }
    }

    if (!show_page) {
        return NULL;
    }


    /* create the XVideo widget */

    object = g_object_new(CTK_TYPE_XVIDEO, NULL);
    ctk_xvideo = CTK_XVIDEO(object);

    ctk_xvideo->ctrl_target = ctrl_target;
    ctk_xvideo->ctk_config = ctk_config;
    ctk_xvideo->active_attributes = 0;

    gtk_box_set_spacing(GTK_BOX(ctk_xvideo), 10);


    /* Video film banner */

    banner = ctk_banner_image_new(BANNER_ARTWORK_XVIDEO);
    gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);

    /* Top Label */

    hbox = gtk_hbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);

    label = gtk_label_new("Xvideo Settings");
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

    hseparator = gtk_hseparator_new();
    gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 0);

    /* Current Sync Value */

    ret = NvCtrlGetAttribute(ctrl_target,
                             NV_CTRL_CURRENT_XV_SYNC_TO_DISPLAY_ID,
                             &display_id);
    if (ret == NvCtrlSuccess) {
        hbox = gtk_hbox_new(FALSE, 5);
        gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 5);

        label = gtk_label_new("Currently synced to display:");
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
        label = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);

        current_sync_name = xv_sync_to_display_radio_button_label(ctk_xvideo,
                                                                  display_id);
        gtk_label_set_text(GTK_LABEL(label), current_sync_name);
        g_free(current_sync_name);

        ctk_xvideo->current_xv_sync_to_display_label = label;
    } else {
        ctk_xvideo->current_xv_sync_to_display_label = NULL;
    }

    /* Sync to display selection */

    frame = gtk_frame_new("Sync to this display device");
    gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);

    vbox = gtk_vbox_new(FALSE, 5);
    gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
    gtk_container_add(GTK_CONTAINER(frame), vbox);
    ctk_xvideo->xv_sync_to_display_button_box = vbox;

    xv_sync_to_display_rebuild_buttons(ctk_xvideo, FALSE);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_XV_SYNC_TO_DISPLAY_ID),
                     G_CALLBACK(xv_sync_to_display_id_handler),
                     (gpointer) ctk_xvideo);

    if (ctk_xvideo->current_xv_sync_to_display_label) {
        g_signal_connect(G_OBJECT(ctk_event),
                         CTK_EVENT_NAME(NV_CTRL_CURRENT_XV_SYNC_TO_DISPLAY_ID),
                         G_CALLBACK(current_xv_sync_to_display_id_handler),
                         (gpointer) ctk_xvideo);
    }

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
                     G_CALLBACK(enabled_displays_handler),
                     (gpointer) ctk_xvideo);


    alignment = gtk_alignment_new(1, 1, 0, 0);
    gtk_box_pack_start(GTK_BOX(object), alignment, TRUE, TRUE, 0);

    /* finally, show the widget */

    gtk_widget_show_all(GTK_WIDGET(ctk_xvideo));

    return GTK_WIDGET(ctk_xvideo);
}
GtkWidget* ctk_display_device_tv_new(NvCtrlAttributeHandle *handle,
                                     CtkConfig *ctk_config,
                                     CtkEvent *ctk_event,
                                     char *name)
{
    GObject *object;
    CtkDisplayDeviceTv *ctk_display_device_tv;
    GtkWidget *banner;
    GtkWidget *frame;
    GtkWidget *eventbox;
    GtkWidget *tmpbox;
    GtkWidget *hbox;
    GtkWidget *alignment;

    
    object = g_object_new(CTK_TYPE_DISPLAY_DEVICE_TV, NULL);
    if (!object) return NULL;
    
    ctk_display_device_tv = CTK_DISPLAY_DEVICE_TV(object);
    ctk_display_device_tv->handle = handle;
    ctk_display_device_tv->ctk_config = ctk_config;
    ctk_display_device_tv->ctk_event = ctk_event;
    ctk_display_device_tv->name = g_strdup(name);
    
    gtk_box_set_spacing(GTK_BOX(object), 10);
    
    /* banner */

    banner = ctk_banner_image_new(BANNER_ARTWORK_TV);
    gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);

    /* Information */

    frame = gtk_frame_new(NULL);
    gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
    ctk_display_device_tv->info_frame = frame;
    
    hbox = gtk_hbox_new(FALSE, FRAME_PADDING);
    gtk_container_set_border_width(GTK_CONTAINER(hbox), FRAME_PADDING);
    gtk_container_add(GTK_CONTAINER(frame), hbox);
    
    tmpbox = gtk_vbox_new(FALSE, 5);
    gtk_container_add(GTK_CONTAINER(hbox), tmpbox);
    
    ctk_display_device_tv->txt_encoder_name = gtk_label_new("");
    ctk_display_device_tv->txt_refresh_rate = gtk_label_new("");
    
    /* pack the Refresh Rate Label */
    {
        typedef struct {
            GtkWidget *label;
            GtkWidget *txt;
            const gchar *tooltip;
        } TextLineInfo;

        TextLineInfo lines[] = {
            {
                gtk_label_new("TV Encoder:"),
                ctk_display_device_tv->txt_encoder_name,
                __tv_encoder_name_help,
            },
            {
                gtk_label_new("TV Refresh Rate:"),
                ctk_display_device_tv->txt_refresh_rate,
                __tv_refresh_rate_help,
            },
            { NULL, NULL, NULL }
        };
        
        int i;
        GtkRequisition req;
        int max_width;

        /* Compute max width of lables and setup text alignments */
        max_width = 0;
        for (i = 0; lines[i].label; i++) {
            gtk_misc_set_alignment(GTK_MISC(lines[i].label), 0.0f, 0.5f);
            gtk_misc_set_alignment(GTK_MISC(lines[i].txt), 0.0f, 0.5f);
            gtk_widget_size_request(lines[i].label, &req);
            
            if (max_width < req.width) {
                max_width = req.width;
            }
        }

        /* Pack labels */
        for (i = 0; lines[i].label; i++) {
            GtkWidget *tmphbox;

            /* Add separators */
            
            if (i == 1) {
                GtkWidget *separator = gtk_hseparator_new();
                gtk_box_pack_start(GTK_BOX(tmpbox), separator,
                                   FALSE, FALSE, 0);
            }
            /* Set the label's width */
            gtk_widget_set_size_request(lines[i].label, max_width, -1);
            /* add the widgets for this line */
            tmphbox = gtk_hbox_new(FALSE, 5);
            gtk_box_pack_start(GTK_BOX(tmphbox), lines[i].label,
                               FALSE, TRUE, 5);
            gtk_box_pack_start(GTK_BOX(tmphbox), lines[i].txt,
                               FALSE, TRUE, 5);

            /* Include tooltips */
            if (!lines[i].tooltip) {
                gtk_box_pack_start(GTK_BOX(tmpbox), tmphbox, FALSE, FALSE, 0);
            } else {
                eventbox = gtk_event_box_new();
                gtk_container_add(GTK_CONTAINER(eventbox), tmphbox);
                ctk_config_set_tooltip(ctk_config, eventbox, lines[i].tooltip);
                gtk_box_pack_start(GTK_BOX(tmpbox), eventbox, FALSE, FALSE, 0);
            }
        }
    }
    
    /* NV_CTRL_REFRESH_RATE */
    
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_REFRESH_RATE),
                     G_CALLBACK(info_update_received),
                     (gpointer) ctk_display_device_tv);
    

    /* NV_CTRL_TV_OVERSCAN */

    ctk_display_device_tv->overscan =
        add_scale(ctk_display_device_tv, NV_CTRL_TV_OVERSCAN,
                  "TV OverScan", __tv_overscan_help);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_TV_OVERSCAN),
                     G_CALLBACK(value_received),
                     (gpointer) ctk_display_device_tv);
    
    /* NV_CTRL_TV_FLICKER_FILTER */

    ctk_display_device_tv->flicker_filter =
        add_scale(ctk_display_device_tv, NV_CTRL_TV_FLICKER_FILTER,
                  "TV Flicker Filter", __tv_flicker_filter_help);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_TV_FLICKER_FILTER),
                     G_CALLBACK(value_received),
                     (gpointer) ctk_display_device_tv);

    /* NV_CTRL_TV_BRIGHTNESS */

    ctk_display_device_tv->brightness =
        add_scale(ctk_display_device_tv, NV_CTRL_TV_BRIGHTNESS,
                  "TV Brightness", __tv_brightness_help);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_TV_BRIGHTNESS),
                     G_CALLBACK(value_received),
                     (gpointer) ctk_display_device_tv);

    /* NV_CTRL_TV_HUE */
    
    ctk_display_device_tv->hue =
        add_scale(ctk_display_device_tv, NV_CTRL_TV_HUE,
                  "TV Hue", __tv_hue_help);
    
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_TV_HUE),
                     G_CALLBACK(value_received),
                     (gpointer) ctk_display_device_tv);

    /* NV_CTRL_TV_CONTRAST */
    
    ctk_display_device_tv->contrast =
        add_scale(ctk_display_device_tv, NV_CTRL_TV_CONTRAST,
                  "TV Contrast", __tv_contrast_help);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_TV_CONTRAST),
                     G_CALLBACK(value_received),
                     (gpointer) ctk_display_device_tv);

    /* NV_CTRL_TV_SATURATION */
    
    ctk_display_device_tv->saturation =
        add_scale(ctk_display_device_tv, NV_CTRL_TV_SATURATION,
                  "TV Saturation", __tv_saturation_help);
    
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_TV_SATURATION),
                     G_CALLBACK(value_received),
                     (gpointer) ctk_display_device_tv);

    /* Create the reset button here so it can be used by the image sliders */

    ctk_display_device_tv->reset_button =
        gtk_button_new_with_label("Reset TV Hardware Defaults");
    
    /* create and pack the image sliders */
    
    ctk_display_device_tv->image_sliders =
        ctk_image_sliders_new(handle, ctk_config, ctk_event,
                              ctk_display_device_tv->reset_button,
                              name);
    if (ctk_display_device_tv->image_sliders) {
        gtk_box_pack_start(GTK_BOX(object),
                           ctk_display_device_tv->image_sliders,
                           FALSE, FALSE, 0);
    }
    
    /* reset button */

    g_signal_connect(G_OBJECT(ctk_display_device_tv->reset_button), "clicked",
                     G_CALLBACK(reset_button_clicked),
                     (gpointer) ctk_display_device_tv);
    
    alignment = gtk_alignment_new(1, 1, 0, 0);
    gtk_container_add(GTK_CONTAINER(alignment),
                      ctk_display_device_tv->reset_button);
    gtk_box_pack_end(GTK_BOX(object), alignment, TRUE, TRUE, 0);
    
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_TV_RESET_SETTINGS),
                     G_CALLBACK(value_received),
                     (gpointer) ctk_display_device_tv);
    
    ctk_config_set_tooltip(ctk_config, ctk_display_device_tv->reset_button,
                           ctk_help_create_reset_hardware_defaults_text("TV", name));

    /* EDID button box */

    ctk_display_device_tv->edid =
        ctk_edid_new(ctk_display_device_tv->handle,
                     ctk_display_device_tv->ctk_config,
                     ctk_display_device_tv->ctk_event,
                     ctk_display_device_tv->name);

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), ctk_display_device_tv->edid,
                       TRUE, TRUE, 0);

    /* finally, display the widget */

    gtk_widget_show_all(GTK_WIDGET(object));

    /* update the GUI */

    update_display_enabled_flag(ctk_display_device_tv->handle,
                                &ctk_display_device_tv->display_enabled);

    ctk_display_device_tv_setup(ctk_display_device_tv);
    
    /* handle enable/disable events on the display device */

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
                     G_CALLBACK(enabled_displays_received),
                     (gpointer) ctk_display_device_tv);
    
    return GTK_WIDGET(object);
    
} /* ctk_display_device_tv_new() */
Exemple #12
0
/*****
 *
 * Main CTK widget creation.
 *
 */
GtkWidget* ctk_clocks_new(NvCtrlAttributeHandle *handle,
                          CtkConfig *ctk_config,
                          CtkEvent *ctk_event)
{
    GObject *object;
    CtkClocks *ctk_object;
    GtkObject *adjustment;
    GtkWidget *alignment;
    GtkWidget *scale;
    CtkDropDownMenu *menu;

    GtkWidget *label;   

    GtkWidget *frame;
    GtkWidget *banner;
    GtkWidget *hbox;
    GtkWidget *vbox;


    ReturnStatus ret;  /* NvCtrlxxx function return value */
    int value, i = 0;
    int clocks_2D;
    NVCTRLAttributeValidValuesRec ranges_2D;
    NVCTRLAttributeValidValuesRec range_detection;
    int clocks_3D;
    NVCTRLAttributeValidValuesRec ranges_3D;

    Bool overclocking_enabled;
    Bool auto_detection_available = FALSE;
    Bool probing_optimal = FALSE;
    Bool can_access_2d_clocks;
    Bool can_access_3d_clocks;
   

    /* Make sure we have a handle */

    g_return_val_if_fail(handle != NULL, NULL);

    /* If we can't query the overclocking state, don't load the page */

    ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_OVERCLOCKING_STATE,
                             &value);
    if ( ret != NvCtrlSuccess )
        return NULL;
    overclocking_enabled =
        (value==NV_CTRL_GPU_OVERCLOCKING_STATE_MANUAL)?True:False;
   
    /* Check if overclocking is busy */
    
    if ( overclocking_enabled ) {
        ret = NvCtrlGetValidAttributeValues(handle,
                                 NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION,
                                 &range_detection);
        if ( ret == NvCtrlSuccess ) {
            ret = NvCtrlGetAttribute(handle,
                                     NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE,
                                     &value);
            if ( ret != NvCtrlSuccess )
                return NULL;
            probing_optimal =
                (value == NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_BUSY);
            auto_detection_available = TRUE;
        }
    }

    /* Can we access the 2D clocks? */

    can_access_2d_clocks = True;
    ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_2D_CLOCK_FREQS, &clocks_2D);
    if ( ret != NvCtrlSuccess )
        can_access_2d_clocks = False;
    ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GPU_2D_CLOCK_FREQS,
                                        &ranges_2D);
    if ( ret != NvCtrlSuccess )
        can_access_2d_clocks = False;

    /* Can we access the 3D clocks? */

    can_access_3d_clocks = True;
    ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_3D_CLOCK_FREQS, &clocks_3D);
    if ( ret != NvCtrlSuccess )
        can_access_3d_clocks = False;
    ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GPU_3D_CLOCK_FREQS,
                                        &ranges_3D);
    if ( ret != NvCtrlSuccess )
        can_access_3d_clocks = False;

    /* If we can't access either of the clocks, don't load the page */

    if ( !can_access_2d_clocks && !can_access_3d_clocks )
        return NULL;

    /* Create the ctk object */

    object = g_object_new(CTK_TYPE_CLOCKS, NULL);
    ctk_object = CTK_CLOCKS(object);

    /* Cache the handle and configuration */

    ctk_object->handle               = handle;
    ctk_object->ctk_config           = ctk_config;
    ctk_object->overclocking_enabled = overclocking_enabled;
    ctk_object->auto_detection_available  = auto_detection_available;
    ctk_object->probing_optimal      = probing_optimal;

    /* Create the Clock menu widget */

    menu = (CtkDropDownMenu *)
        ctk_drop_down_menu_new(CTK_DROP_DOWN_MENU_FLAG_READONLY);
    i = 0;
        
    if ( can_access_2d_clocks ) {
            ctk_drop_down_menu_append_item(menu, "2D Clock Frequencies", i++);
    }

    if ( can_access_3d_clocks ) {
            ctk_drop_down_menu_append_item(menu, "3D Clock Frequencies", i++);
    }
    
    ctk_object->clock_menu = GTK_WIDGET(menu);

    g_signal_connect(G_OBJECT(ctk_object->clock_menu), "changed",
                     G_CALLBACK(clock_menu_changed),
                     (gpointer) ctk_object);
    
    ctk_config_set_tooltip(ctk_config, ctk_object->clock_menu,
                           __clock_menu_help);

    gtk_widget_set_sensitive(ctk_object->clock_menu,
                             overclocking_enabled && !probing_optimal);
    
    /* Create the Graphics clock frequency slider widget */

    if ( can_access_2d_clocks ) {
        adjustment =
            gtk_adjustment_new(GET_GPU_CLOCK(clocks_2D),
                               GET_GPU_CLOCK(ranges_2D.u.range.min),
                               GET_GPU_CLOCK(ranges_2D.u.range.max),
                               1, 5, 0.0);
        ctk_object->clocks_being_modified = CLOCKS_2D;
    } else {
        adjustment =
            gtk_adjustment_new(GET_GPU_CLOCK(clocks_3D),
                               GET_GPU_CLOCK(ranges_3D.u.range.min),
                               GET_GPU_CLOCK(ranges_3D.u.range.max),
                               1, 5, 0.0);
        ctk_object->clocks_being_modified = CLOCKS_3D;
    }

    scale = ctk_scale_new(GTK_ADJUSTMENT(adjustment), "GPU (MHz)",
                          ctk_config, G_TYPE_INT);
    ctk_object->gpu_clk_scale = scale;
    
    g_signal_connect(adjustment, "value_changed",
                     G_CALLBACK(adjustment_value_changed),
                     (gpointer) ctk_object);

    ctk_config_set_tooltip(ctk_config,
                           CTK_SCALE(ctk_object->gpu_clk_scale)->gtk_scale,
                           __graphics_clock_help);

    gtk_widget_set_sensitive(ctk_object->gpu_clk_scale,
                             overclocking_enabled && !probing_optimal);

    /* Create the Memory clock frequency slider widget */
    
    if ( can_access_2d_clocks ) {
        adjustment =
            gtk_adjustment_new(GET_MEM_CLOCK(clocks_2D),
                               GET_MEM_CLOCK(ranges_2D.u.range.min),
                               GET_MEM_CLOCK(ranges_2D.u.range.max),
                               1, 5, 0.0);
    } else {
        adjustment =
            gtk_adjustment_new(GET_MEM_CLOCK(clocks_3D),
                               GET_MEM_CLOCK(ranges_3D.u.range.min),
                               GET_MEM_CLOCK(ranges_3D.u.range.max),
                               1, 5, 0.0);
    }

    scale = ctk_scale_new(GTK_ADJUSTMENT(adjustment), "Memory (MHz)",
                          ctk_config, G_TYPE_INT);
    ctk_object->mem_clk_scale = scale;
    
    g_signal_connect(adjustment, "value_changed",
                     G_CALLBACK(adjustment_value_changed),
                     (gpointer) ctk_object);
    
    ctk_config_set_tooltip(ctk_config,
                           CTK_SCALE(ctk_object->mem_clk_scale)->gtk_scale,
                           __mem_clock_help);

    gtk_widget_set_sensitive(ctk_object->mem_clk_scale,
                             overclocking_enabled && !probing_optimal);

    /* Create the Enable Overclocking checkbox widget */

    ctk_object->enable_checkbox =
        gtk_check_button_new_with_label("Enable Overclocking");

    gtk_toggle_button_set_active
        (GTK_TOGGLE_BUTTON(ctk_object->enable_checkbox),
         overclocking_enabled);

    gtk_widget_set_sensitive(ctk_object->enable_checkbox,
                             overclocking_enabled && !probing_optimal);

    g_signal_connect(G_OBJECT(ctk_object->enable_checkbox), "toggled",
                     G_CALLBACK(overclocking_state_toggled),
                     (gpointer) ctk_object);

    ctk_config_set_tooltip(ctk_config, ctk_object->enable_checkbox,
                           __enable_button_help);
    
    gtk_widget_set_sensitive(ctk_object->enable_checkbox, !probing_optimal);

    /* Create the Apply button widget */

    ctk_object->apply_button =
        gtk_button_new_with_label("Apply");

    g_signal_connect(G_OBJECT(ctk_object->apply_button), "clicked",
                     G_CALLBACK(apply_clocks_clicked),
                     (gpointer) ctk_object);
    
    ctk_config_set_tooltip(ctk_config, ctk_object->apply_button,
                           __apply_button_help);

    gtk_widget_set_sensitive(ctk_object->apply_button, False);
    
    /* Create the Auto Detect button widget */

    ctk_object->detect_button =
        gtk_button_new_with_label("Auto Detect");

    g_signal_connect(G_OBJECT(ctk_object->detect_button), "clicked",
                     G_CALLBACK(detect_clocks_clicked),
                     (gpointer) ctk_object);
    
    ctk_config_set_tooltip(ctk_config, ctk_object->detect_button,
                           __detect_button_help);
    
    if ( ctk_object->clocks_being_modified == CLOCKS_2D ) {
        gtk_widget_set_sensitive(ctk_object->detect_button, False);
    } else {
        gtk_widget_set_sensitive(ctk_object->detect_button,
                                 overclocking_enabled &&
                                 auto_detection_available && !probing_optimal);
    }

    /* Create the Reset hardware button widget */

    ctk_object->reset_button =
        gtk_button_new_with_label("Reset Hardware Defaults");

    g_signal_connect(G_OBJECT(ctk_object->reset_button), "clicked",
                     G_CALLBACK(reset_clocks_clicked),
                     (gpointer) ctk_object);
    
    ctk_config_set_tooltip(ctk_config, ctk_object->reset_button,
                           __reset_button_help);

    gtk_widget_set_sensitive(ctk_object->reset_button, False);

    /* Create the auto detect dialog */

    ctk_object->detect_dialog =
        gtk_dialog_new_with_buttons("Auto Detect Optimal 3D Clock Frequencies?",
                                    GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
                                    GTK_DIALOG_MODAL |  GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
                                    GTK_STOCK_OK,
                                    GTK_RESPONSE_ACCEPT,
                                    GTK_STOCK_CANCEL,
                                    GTK_RESPONSE_REJECT,
                                    NULL
                                    );
    
    label = gtk_label_new(__detect_confirm_msg);
    hbox = gtk_hbox_new(TRUE, 15);

    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 15);

    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(ctk_object->detect_dialog)->vbox),
                       hbox, FALSE, FALSE, 15);

    /*
     * Now that we've created all the widgets we care about, we're
     * ready to compose the panel
     */

    /* Set container properties of the ctk object */

    gtk_box_set_spacing(GTK_BOX(ctk_object), 10);

    banner = ctk_banner_image_new(BANNER_ARTWORK_CLOCK);
    gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);

    /* Add Overclocking checkbox */

    hbox = gtk_hbox_new(FALSE, 0);

    gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
    
    gtk_box_pack_start(GTK_BOX(hbox), ctk_object->enable_checkbox,
                       FALSE, FALSE, 0);

    /* Add Clock frequency frame */

    frame = gtk_frame_new("Clock Frequencies");
    vbox = gtk_vbox_new(FALSE, 0);
    hbox = gtk_hbox_new(FALSE, 0);
            
    gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
    
    gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
    gtk_container_add(GTK_CONTAINER(frame), vbox);
            
    
    gtk_box_pack_start(GTK_BOX(hbox), ctk_object->clock_menu,
                       FALSE, FALSE, 0);
    
    gtk_box_pack_start(GTK_BOX(vbox), hbox,
                       FALSE, FALSE, 5);

    gtk_box_pack_start(GTK_BOX(vbox), ctk_object->gpu_clk_scale,
                       FALSE, FALSE, 5);
            
    gtk_box_pack_start(GTK_BOX(vbox), ctk_object->mem_clk_scale,
                       FALSE, FALSE, 5);                
        
    /* Add the Apply, Auto Detect, and Reset buttons */

    hbox = gtk_hbox_new(FALSE, 5);

    gtk_box_pack_start(GTK_BOX(hbox), ctk_object->apply_button,
                       FALSE, FALSE, 0);
    gtk_container_add(GTK_CONTAINER(hbox), ctk_object->detect_button);
    gtk_container_add(GTK_CONTAINER(hbox), ctk_object->reset_button);
        
    alignment = gtk_alignment_new(1, 1, 0, 0);
    gtk_container_add(GTK_CONTAINER(alignment), hbox);
    gtk_box_pack_start(GTK_BOX(object), alignment, TRUE, TRUE, 0);

    /* Setup the initial gui state */
    
    sync_gui_to_modify_clocks(ctk_object, ctk_object->clocks_being_modified);
    
    /* Handle events from other NV-CONTROL clients */
    
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GPU_OVERCLOCKING_STATE),
                     G_CALLBACK(overclocking_state_received),
                     (gpointer) ctk_object);
    
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GPU_2D_CLOCK_FREQS),
                     G_CALLBACK(clocks_received),
                     (gpointer) ctk_object);
    
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GPU_3D_CLOCK_FREQS),
                     G_CALLBACK(clocks_received),
                     (gpointer) ctk_object);
    
    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS),
                     G_CALLBACK(clocks_received),
                     (gpointer) ctk_object);

    g_signal_connect(G_OBJECT(ctk_event),
                     CTK_EVENT_NAME(NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE),
                     G_CALLBACK(auto_detection_state_received),
                     (gpointer) ctk_object);

    /* Show the widget */

    gtk_widget_show_all(GTK_WIDGET(ctk_object));

    return GTK_WIDGET(ctk_object);

} /* ctk_clocks_new() */