Beispiel #1
0
/* ctk_event_emit_string() - Emits signal(s) on a registered ctk_event object.
 * This function is primarily used to simulate NV-CONTROL events such
 * that various parts of nvidia-settings can communicate (internally)
 */
void ctk_event_emit_string(CtkEvent *ctk_event,
                    unsigned int mask, int attrib)
{
    CtkEventStruct event;
    CtkEventSource *source;
    Display *dpy = NvCtrlGetDisplayPtr(ctk_event->handle);


    if (attrib > NV_CTRL_STRING_LAST_ATTRIBUTE) return;


    /* Find the event source */
    source = event_sources;
    while (source) {
        if (source->dpy == dpy) {
            break;
        }
        source = source->next;
    }
    if (!source) return;


    /* Broadcast event to all relevant ctk_event objects */

    event.attribute = attrib;
    event.value = 0;
    event.display_mask = mask;

    CTK_EVENT_BROADCAST(source,
                        string_signals[attrib],
                        &event,
                        NvCtrlGetTargetType(ctk_event->handle),
                        NvCtrlGetTargetId(ctk_event->handle));

} /* ctk_event_emit_string() */
Beispiel #2
0
/* ctk_event_emit() - Emits signal(s) on a registered ctk_event object.
 * This function is primarily used to simulate NV-CONTROL events such
 * that various parts of nvidia-settings can communicate (internally)
 */
void ctk_event_emit(CtkEvent *ctk_event,
                    unsigned int mask,
                    int attrib,
                    int value)
{
    CtrlEvent event;
    CtkEventSource *source;
    CtrlTarget *ctrl_target = ctk_event->ctrl_target;
    NvCtrlEventHandle *event_handle = NvCtrlGetEventHandle(ctrl_target);


    if (attrib > NV_CTRL_LAST_ATTRIBUTE) return;


    /* Find the event source */
    source = event_sources;
    while (source) {
        if (source->event_handle == event_handle) {
            break;
        }
        source = source->next;
    }
    if (!source) return;


    /* Broadcast event to all relevant ctk_event objects */
    memset(&event, 0, sizeof(CtrlEvent));

    event.type        = CTRL_EVENT_TYPE_INTEGER_ATTRIBUTE;
    event.target_type = NvCtrlGetTargetType(ctrl_target);
    event.target_id   = NvCtrlGetTargetId(ctrl_target);

    event.int_attr.attribute = attrib;
    event.int_attr.value     = value;

    CTK_EVENT_BROADCAST(source, signals[attrib], &event);

} /* ctk_event_emit() */
Beispiel #3
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);
}
Beispiel #4
0
/* - ctk_event_register_source()
 *
 * Keep track of event sources globally to support
 * dispatching events on a dpy to multiple CtkEvent
 * objects.  Since the driver only sends out one event
 * notification per dpy (client), there should only be one
 * event source attached per unique dpy.  When an event
 * is received, the dispatching function should then
 * emit a signal to every CtkEvent object that
 * requests event notification from the dpy for the
 * given target type/id (X screen, GPU etc).
 */
static void ctk_event_register_source(CtkEvent *ctk_event)
{
    Display *dpy = NvCtrlGetDisplayPtr(ctk_event->handle);
    CtkEventSource *event_source;
    CtkEventNode *event_node;

    if (!dpy) {
        return;
    }

    /* Do we already have an event source for this dpy? */
    event_source = event_sources;
    while (event_source) {
        if (event_source->dpy == dpy) {
            break;
        }
        event_source = event_source->next;
    }

    /* create a new input source */
    if (!event_source) {
        GSource *source;

        static GSourceFuncs ctk_source_funcs = {
            ctk_event_prepare,
            ctk_event_check,
            ctk_event_dispatch,
            NULL, /* finalize */
            NULL, /* closure_callback */
            NULL, /* closure_marshal */
        };

        source = g_source_new(&ctk_source_funcs, sizeof(CtkEventSource));
        event_source = (CtkEventSource *) source;
        if (!event_source) {
            return;
        }
        
        event_source->dpy = dpy;
        event_source->event_poll_fd.fd = ConnectionNumber(dpy);
        event_source->event_poll_fd.events = G_IO_IN;
        event_source->event_base = NvCtrlGetEventBase(ctk_event->handle);
        event_source->randr_event_base =
            NvCtrlGetXrandrEventBase(ctk_event->handle);
        
        /* add the input source to the glib main loop */
        
        g_source_add_poll(source, &event_source->event_poll_fd);
        g_source_attach(source, NULL);

        /* add the source to the global list of sources */

        event_source->next = event_sources;
        event_sources = event_source;
    }


    /* Add the ctk_event object to the source's list of event objects */

    event_node = (CtkEventNode *)g_malloc(sizeof(CtkEventNode));
    if (!event_node) {
        return;
    }
    event_node->ctk_event = ctk_event;
    event_node->target_type = NvCtrlGetTargetType(ctk_event->handle);
    event_node->target_id = NvCtrlGetTargetId(ctk_event->handle);
    event_node->next = event_source->ctk_events;
    event_source->ctk_events = event_node;
    /*
     * This next bit of code is to make sure that the randr_event_base
     * for this event source is valid in the case where a NON X Screen
     * target type handle is used to create the initial event source
     * (Resulting in randr_event_base being == -1), followed by an
     * X Screen target type handle registering itself to receive
     * XRandR events on the existing dpy/event source.
     */
    if (event_source->randr_event_base == -1 &&
        event_node->target_type == NV_CTRL_TARGET_TYPE_X_SCREEN) {
        event_source->randr_event_base =
            NvCtrlGetXrandrEventBase(ctk_event->handle);
    }

} /* ctk_event_register_source() */
Beispiel #5
0
/* - ctk_event_register_source()
 *
 * Keep track of event sources globally to support
 * dispatching events on an event handle to multiple CtkEvent
 * objects.  Since the driver only sends out one event
 * notification per event handle (client), there should only be one
 * event source attached per unique event handle.  When an event
 * is received, the dispatching function should then
 * emit a signal to every CtkEvent object that
 * requests event notification from the event handle for the
 * given target type/id (X screen, GPU etc).
 */
static void ctk_event_register_source(CtkEvent *ctk_event)
{
    CtrlTarget *ctrl_target = ctk_event->ctrl_target;
    NvCtrlEventHandle *event_handle = NvCtrlGetEventHandle(ctrl_target);
    CtkEventSource *event_source;
    CtkEventNode *event_node;

    if (!event_handle) {
        return;
    }

    /* Do we already have an event source for this event handle? */
    event_source = find_event_source(event_handle);

    /* create a new input source */
    if (!event_source) {
        GSource *source;
        int event_fd;

        static GSourceFuncs ctk_source_funcs = {
            ctk_event_prepare,
            ctk_event_check,
            ctk_event_dispatch,
            NULL, /* finalize */
            NULL, /* closure_callback */
            NULL, /* closure_marshal */
        };

        source = g_source_new(&ctk_source_funcs, sizeof(CtkEventSource));
        event_source = (CtkEventSource *) source;
        if (!event_source) {
            return;
        }
        
        NvCtrlEventHandleGetFD(event_handle, &event_fd);
        event_source->event_handle = event_handle;
        event_source->event_poll_fd.fd = event_fd;
        event_source->event_poll_fd.events = G_IO_IN;
        
        /* add the input source to the glib main loop */
        
        g_source_add_poll(source, &event_source->event_poll_fd);
        g_source_attach(source, NULL);

        /* add the source to the global list of sources */

        event_source->next = event_sources;
        event_sources = event_source;
    }


    /* Add the ctk_event object to the source's list of event objects */

    event_node = (CtkEventNode *)g_malloc(sizeof(CtkEventNode));
    if (!event_node) {
        return;
    }
    event_node->ctk_event = ctk_event;
    event_node->target_type = NvCtrlGetTargetType(ctrl_target);
    event_node->target_id = NvCtrlGetTargetId(ctrl_target);
    event_node->next = event_source->ctk_events;
    event_source->ctk_events = event_node;

} /* ctk_event_register_source() */
Beispiel #6
0
int nv_write_config_file(const char *filename, const CtrlSystem *system,
                         const ParsedAttribute *p, const ConfigProperties *conf)
{
    int ret, entry, val, randr_gamma_available;
    FILE *stream;
    time_t now;
    ReturnStatus status;
    CtrlAttributePerms perms;
    CtrlTargetNode *node;
    CtrlTarget *t;
    char *prefix, scratch[4];
    char *locale = "C";

    if (!filename) {
        nv_error_msg("Unable to open configuration file for writing.");
        return NV_FALSE;
    }

    stream = fopen(filename, "w");
    if (!stream) {
        nv_error_msg("Unable to open file '%s' for writing.", filename);
        return NV_FALSE;
    }
    
    /* write header */
    
    now = time(NULL);
    
    fprintf(stream, "#\n");
    fprintf(stream, "# %s\n", filename);
    fprintf(stream, "#\n");
    fprintf(stream, "# Configuration file for nvidia-settings - the NVIDIA "
            "X Server Settings utility\n");

    /* NOTE: ctime(3) generates a new line */
    
    fprintf(stream, "# Generated on %s", ctime(&now));
    fprintf(stream, "#\n");
    
    /*
     * set the locale to "C" before writing the configuration file to
     * reduce the risk of locale related parsing problems.  Restore
     * the original locale before exiting this function.
     */

    if (setlocale(LC_NUMERIC, "C") == NULL) {
        nv_warning_msg("Error writing configuration file '%s': could "
                       "not set the locale 'C'.", filename);
        locale = conf->locale;
    }

    /* write the values in ConfigProperties */

    write_config_properties(stream, conf, locale);

    /* for each screen, query each attribute in the table */

    fprintf(stream, "\n");
    fprintf(stream, "# Attributes:\n");
    fprintf(stream, "\n");

    /*
     * Note: we only save writable attributes addressable by X screen here
     * followed by attributes for display target types.
     */

    for (node = system->targets[X_SCREEN_TARGET]; node; node = node->next) {

        t = node->t;

        /* skip it if we don't have a handle for this screen */

        if (!t->h) continue;

        /*
         * construct the prefix that will be printed in the config
         * file in front of each attribute on this screen; this will
         * either be "[screen]" or "[displayname]".
         */

        if (conf->booleans &
            CONFIG_PROPERTIES_INCLUDE_DISPLAY_NAME_IN_CONFIG_FILE) {
            prefix = t->name;
        } else {
            snprintf(scratch, 4, "%d", NvCtrlGetTargetId(t));
            prefix = scratch;
        }

        /* loop over all the entries in the table */

        for (entry = 0; entry < attributeTableLen; entry++) {
            const AttributeTableEntry *a = &attributeTable[entry];

            /*
             * skip all attributes that are not supposed to be written
             * to the config file
             */

            if (a->flags.no_config_write) {
                continue;
            }

            /*
             * special case the color attributes because we want to
             * print floats
             */

            if (a->type == CTRL_ATTRIBUTE_TYPE_COLOR) {
                float c[3], b[3], g[3];

                /*
                 * if we are using RandR gamma, skip saving the color info
                 */

                status = NvCtrlGetAttribute(t,
                                            NV_CTRL_ATTR_RANDR_GAMMA_AVAILABLE,
                                            &val);
                if (status == NvCtrlSuccess && val) continue;

                status = NvCtrlGetColorAttributes(t, c, b, g);
                if (status != NvCtrlSuccess) continue;
                fprintf(stream, "%s%c%s=%f\n",
                        prefix, DISPLAY_NAME_SEPARATOR, a->name,
                        get_color_value(a->attr, c, b, g));
                continue;
            }

            /* Only write out integer attributes, string and SDI CSC attributes
             * aren't written here.
             */
            if (a->type != CTRL_ATTRIBUTE_TYPE_INTEGER) {
                continue;
            }

            /*
             * Ignore display attributes (they are written later on) and only
             * write attributes that can be written for an X screen target
             */

            status = NvCtrlGetAttributePerms(t, a->type, a->attr, &perms);
            if (status != NvCtrlSuccess || !(perms.write) ||
                !(perms.valid_targets & CTRL_TARGET_PERM_BIT(X_SCREEN_TARGET)) ||
                (perms.valid_targets & CTRL_TARGET_PERM_BIT(DISPLAY_TARGET))) {
                continue;
            }

            status = NvCtrlGetAttribute(t, a->attr, &val);
            if (status != NvCtrlSuccess) {
                continue;
            }

            if (a->f.int_flags.is_display_id) {
                const char *name = NvCtrlGetDisplayConfigName(system, val);
                if (name) {
                    fprintf(stream, "%s%c%s=%s\n", prefix,
                            DISPLAY_NAME_SEPARATOR, a->name, name);
                }
                continue;
            }

            fprintf(stream, "%s%c%s=%d\n", prefix,
                    DISPLAY_NAME_SEPARATOR, a->name, val);

        } /* entry */

    } /* screen */

    /*
     * Write attributes addressable to display targets
     */

    for (node = system->targets[DISPLAY_TARGET]; node; node = node->next) {

        t = node->t;

        /* skip it if we don't have a handle for this display */

        if (!t->h) continue;

        /* 
         * check to see if we have RANDR gamma available. We may
         * skip writing attributes if it is missing. 
         */

        status = NvCtrlGetAttribute(t, 
                                    NV_CTRL_ATTR_RANDR_GAMMA_AVAILABLE,
                                    &randr_gamma_available);
        if (status != NvCtrlSuccess) {
            randr_gamma_available = 0;
        }

        /* Get the prefix we want to use for the display device target */

        prefix = create_display_device_target_string(t, conf);

        /* loop over all the entries in the table */

        for (entry = 0; entry < attributeTableLen; entry++) {
            const AttributeTableEntry *a = &attributeTable[entry];

            /*
             * skip all attributes that are not supposed to be written
             * to the config file
             */

            if (a->flags.no_config_write) {
                continue;
            }

            /*
             * for the display target we only write color attributes for now
             */

            if (a->type == CTRL_ATTRIBUTE_TYPE_COLOR) {
                float c[3], b[3], g[3];

                if (!randr_gamma_available) continue;

                status = NvCtrlGetColorAttributes(t, c, b, g);
                if (status != NvCtrlSuccess) continue;

                fprintf(stream, "%s%c%s=%f\n",
                        prefix, DISPLAY_NAME_SEPARATOR, a->name,
                        get_color_value(a->attr, c, b, g));
                continue;
            }

            /* Only write out integer attributes, string and SDI CSC attributes
             * aren't written here.
             */
            if (a->type != CTRL_ATTRIBUTE_TYPE_INTEGER) {
                continue;
            }

            /* Make sure this is a display and writable attribute */

            status = NvCtrlGetAttributePerms(t, a->type, a->attr, &perms);
            if (status != NvCtrlSuccess || !(perms.write) ||
                !(perms.valid_targets & CTRL_TARGET_PERM_BIT(DISPLAY_TARGET))) {
                continue;
            }

            status = NvCtrlGetAttribute(t, a->attr, &val);
            if (status == NvCtrlSuccess) {
                fprintf(stream, "%s%c%s=%d\n", prefix,
                        DISPLAY_NAME_SEPARATOR, a->name, val);
            }
        }

        free(prefix);
    }
    
    /*
     * loop the ParsedAttribute list, writing the attributes to file.
     * note that we ignore conf->include_display_name_in_config_file
     * when writing these parsed attributes; this is because parsed
     * attributes (like the framelock properties) require a display
     * name be specified (since there are multiple X servers
     * involved).
     */

    while (p) {
        char target_str[64];
        const AttributeTableEntry *a = p->attr_entry;

        if (!p->next) {
            p = p->next;
            continue;
        }

        /*
         * if the parsed attribute has a target specification, and a
         * target type other than an X screen, include a target
         * specification in what we write to the .rc file.
         */

        target_str[0] = '\0';

        if (p->parser_flags.has_target &&
            (p->target_type != X_SCREEN_TARGET)) {

            const CtrlTargetTypeInfo *targetTypeInfo;

            /* Find the target name of the target type */
            targetTypeInfo = NvCtrlGetTargetTypeInfo(p->target_type);
            if (targetTypeInfo) {
                snprintf(target_str, 64, "[%s:%d]",
                         targetTypeInfo->parsed_name, p->target_id);
            }
        }

        if (a->flags.hijack_display_device) {
            fprintf(stream, "%s%s%c%s[0x%08x]=%d\n", p->display, target_str,
                    DISPLAY_NAME_SEPARATOR, a->name,
                    p->display_device_mask,
                    p->val.i);
        } else {
            fprintf(stream, "%s%s%c%s=%d\n", p->display, target_str,
                    DISPLAY_NAME_SEPARATOR, a->name, p->val.i);
        }


        p = p->next;
    }

    setlocale(LC_NUMERIC, conf->locale);

    /* close the configuration file */

    ret = fclose(stream);
    if (ret != 0) {
        nv_error_msg("Failure while closing file '%s'.", filename);
        return NV_FALSE;
    }
    
    return NV_TRUE;
    
} /* nv_write_config_file() */
Beispiel #7
0
/*
 * Rebuilds the list of display devices available for syncing.
 */
static void xv_sync_to_display_rebuild_buttons(CtkXVideo *ctk_xvideo,
                                               gboolean update_status)
{
    ReturnStatus ret;
    int enabled_display_id;
    int *pData;
    int len;
    int i;

    GtkWidget *last_button;
    GtkWidget *button;
    CtrlTarget *ctrl_target = ctk_xvideo->ctrl_target;


    /* Remove all buttons */

    ctk_empty_container(ctk_xvideo->xv_sync_to_display_button_box);


    /* Rebuild the list based on the curren configuration */

    ret = NvCtrlGetAttribute(ctrl_target,
                             NV_CTRL_XV_SYNC_TO_DISPLAY_ID,
                             &enabled_display_id);
    if (ret != NvCtrlSuccess) {
        nv_warning_msg("Failed to query XV Sync display ID on X screen %d.",
                       NvCtrlGetTargetId(ctrl_target));
        return;
    }

    ret = NvCtrlGetBinaryAttribute(ctrl_target, 0,
                                   NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN,
                                   (unsigned char **)(&pData), &len);
    if (ret != NvCtrlSuccess) {
        nv_warning_msg("Failed to query list of displays assigned to X screen "
                       " %d.",
                       NvCtrlGetTargetId(ctrl_target));
        return;
    }


    /* Add a button for No Display Specified */
    last_button = NULL;
    button = xv_sync_to_display_radio_button_add(ctk_xvideo, NULL,
                                                 NV_CTRL_XV_SYNC_TO_DISPLAY_ID_AUTO);

    if (button) {
        /* Track the first button */
        if (!last_button) {
            ctk_xvideo->xv_sync_to_display_buttons = button;
        }

        last_button = button;
    }
    /* Add a button for each display device */
    for (i = 0; i < pData[0]; i++) {
        int display_id = pData[1+i];

        button = xv_sync_to_display_radio_button_add(ctk_xvideo,
                                                     last_button,
                                                     display_id);
        if (!button) {
            continue;
        }

        /* Make sure the enabled display is marked as so */
        if (display_id == enabled_display_id) {
            xv_sync_to_display_set_enabled(ctk_xvideo, button,
                                           update_status);
        }

        /* Track the first button */
        if (!last_button) {
            ctk_xvideo->xv_sync_to_display_buttons = button;
        }

        last_button = button;
    }

    gtk_widget_show_all(ctk_xvideo->xv_sync_to_display_button_box);
}
Beispiel #8
0
/*
 * CTK VCS (Visual Computing System) widget creation
 *
 */
GtkWidget* ctk_vcs_new(NvCtrlAttributeHandle *handle,
                        CtkConfig *ctk_config)
{
    GObject *object;
    CtkVcs *ctk_object;
    GtkWidget *label;
    GtkWidget *vbox;
    GtkWidget *hbox;
    GtkWidget *event;
    GtkWidget *banner;
    GtkWidget *hseparator;
    GtkWidget *table;
    GtkWidget *scrollWin;
    GtkWidget *checkbutton;

    gchar *product_name;
    gchar *serial_number;
    gchar *build_date;
    gchar *product_id;
    gchar *firmware_version;
    gchar *hardware_version;

    gint current_row;
    gboolean high_perf_mode;

    ReturnStatus ret;
    gchar *s;
    char *psu_str = NULL;
    PSUEntry psuEntry;

    GtkWidget *vbox_scroll, *hbox_scroll;

    /*
     * get the static string data that we will display below
     */
    
    /* Product Name */
    ret = NvCtrlGetStringAttribute(handle,
                                   NV_CTRL_STRING_VCSC_PRODUCT_NAME,
                                   &product_name);
    if (ret != NvCtrlSuccess) {
        product_name = g_strdup("Unable to determine");
    }

    /* Serial Number */
    ret = NvCtrlGetStringAttribute(handle,
                                   NV_CTRL_STRING_VCSC_SERIAL_NUMBER,
                                   &serial_number);
    if (ret != NvCtrlSuccess) {
        serial_number = g_strdup("Unable to determine");
    }

    /* Build Date */
    ret = NvCtrlGetStringAttribute(handle,
                                   NV_CTRL_STRING_VCSC_BUILD_DATE,
                                   &build_date);
    if (ret != NvCtrlSuccess) {
        build_date = g_strdup("Unable to determine");
    }

    /* Product ID */
    ret = NvCtrlGetStringAttribute(handle,
                                   NV_CTRL_STRING_VCSC_PRODUCT_ID,
                                   &product_id);
    if (ret != NvCtrlSuccess) {
        product_id = g_strdup("Unable to determine");
    }

    /* Firmware Version */
    ret = NvCtrlGetStringAttribute(handle,
                                   NV_CTRL_STRING_VCSC_FIRMWARE_VERSION,
                                   &firmware_version);
    if (ret != NvCtrlSuccess) {
        firmware_version = g_strdup("Unable to determine");
    }

    /* Hardware Version */
    ret = NvCtrlGetStringAttribute(handle,
                                   NV_CTRL_STRING_VCSC_HARDWARE_VERSION,
                                   &hardware_version);
    if (ret != NvCtrlSuccess) {
        hardware_version = g_strdup("Unable to determine");
    }


    /* now, create the object */
    
    object = g_object_new(CTK_TYPE_VCS, NULL);
    ctk_object = CTK_VCS(object);

    /* cache the attribute handle */

    ctk_object->handle = handle;
    ctk_object->ctk_config = ctk_config;

    /* set container properties of the object */

    gtk_box_set_spacing(GTK_BOX(ctk_object), 10);

    /* banner */

    banner = ctk_banner_image_new(BANNER_ARTWORK_VCS);
    gtk_box_pack_start(GTK_BOX(ctk_object), banner, FALSE, FALSE, 0);

    /*
     * This displays basic System information, including
     * display name, Operating system type and the NVIDIA driver version.
     */

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

    /* General purpose error dialog */
    ctk_object->error_dialog = create_error_dialog(ctk_object);

    if (NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_VCSC_HIGH_PERF_MODE,
                            &high_perf_mode) == NvCtrlSuccess) {

        hbox = gtk_hbox_new(FALSE, 0);
        checkbutton = gtk_check_button_new_with_label("Enable High Performance Mode");
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), high_perf_mode);
        g_signal_connect(G_OBJECT(checkbutton), "toggled", 
                         G_CALLBACK(vcs_perf_checkbox_toggled),
                         (gpointer) ctk_object);
        gtk_box_pack_start(GTK_BOX(hbox), checkbutton, TRUE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); 
    }

    /* Create the Scrolling Window */
    scrollWin = gtk_scrolled_window_new(NULL, NULL);
    hbox_scroll = gtk_hbox_new(FALSE, 0);
    vbox_scroll = gtk_vbox_new(FALSE, 5);
    event = gtk_event_box_new();
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollWin),
                                   GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
    gtk_widget_modify_fg(event, GTK_STATE_NORMAL, &(event->style->text[GTK_STATE_NORMAL]));
    gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &(event->style->base[GTK_STATE_NORMAL]));
    gtk_container_add(GTK_CONTAINER(event), hbox_scroll);
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollWin),
                                          event);
    gtk_box_pack_start(GTK_BOX(hbox_scroll), vbox_scroll, TRUE, TRUE, 5);
    gtk_widget_set_size_request(scrollWin, -1, 50);
    gtk_box_pack_start(GTK_BOX(vbox), scrollWin, TRUE, TRUE, 0);

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

    label = gtk_label_new("VCS 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);

    table = gtk_table_new(5, 2, FALSE);
    gtk_box_pack_start(GTK_BOX(vbox_scroll), 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);

    add_table_row(table, 0,
                  0, 0.5, "Product Name:", 0, 0.5, product_name);
    add_table_row(table, 1,
                  0, 0.5, "Serial Number:", 0, 0.5, serial_number);
    add_table_row(table, 2,
                  0, 0.5, "Build Date:", 0, 0.5, build_date);
    add_table_row(table, 3,
                  0, 0.5, "Product ID:", 0, 0.5, product_id);
    add_table_row(table, 4,
                  0, 0.5, "Firmware version:", 0, 0.5, firmware_version);
    add_table_row(table, 5,
                  0, 0.5, "Hardware version:", 0, 0.5, hardware_version);

    g_free(product_name);
    g_free(serial_number);
    g_free(build_date);
    g_free(product_id);
    g_free(firmware_version);
    g_free(hardware_version);


    /* Query Canoas 2.0 specific details */
    if ((NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_VCSC_HIGH_PERF_MODE, 
                            &high_perf_mode) == NvCtrlSuccess) && 
        (NvCtrlGetStringAttribute(ctk_object->handle,
                                  NV_CTRL_STRING_VCSC_PSU_INFO,
                                  &psu_str)  == NvCtrlSuccess)) {
        GtkWidget *vbox_padding;

        /* Show the additonal queried information */


        /* Populate scrolling window with data */
        vbox_padding = gtk_vbox_new(FALSE, 0);
        hbox = gtk_hbox_new(FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox_scroll), vbox_padding, FALSE, FALSE, 1);
        gtk_box_pack_start(GTK_BOX(vbox_scroll), hbox, FALSE, FALSE, 0);
        label = gtk_label_new("VCS Thermal 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);

        table = gtk_table_new(3, 2, FALSE);
        gtk_box_pack_start(GTK_BOX(vbox_scroll), 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);

        label = gtk_label_new("Intake Temperature:");
        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

        label = gtk_label_new(NULL);
        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
        ctk_object->intake_temp = label;

        label = gtk_label_new("Exhaust Temperature:");
        /* This is the current largest label.  Get its size */
        gtk_widget_size_request(label, &ctk_object->req);

        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

        label = gtk_label_new(NULL);
        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_table_attach(GTK_TABLE(table), label, 1, 2, 1, 2,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
        ctk_object->exhaust_temp = label;

        label = gtk_label_new("Board Temperature:");
        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

        label = gtk_label_new(NULL);
        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_table_attach(GTK_TABLE(table), label, 1, 2, 2, 3,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
        ctk_object->board_temp = label;

        /* Populate table for PSU information */

        psuEntry.psu_current    = -1;
        psuEntry.psu_power      = -1;
        psuEntry.psu_voltage    = -1;
        psuEntry.psu_state      = -1;

        if (psu_str) {
            parse_token_value_pairs(psu_str, apply_psu_entry_token, &psuEntry);
        }

        vbox_padding = gtk_vbox_new(FALSE, 0);
        hbox = gtk_hbox_new(FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox_scroll), vbox_padding, FALSE, FALSE, 1);
        gtk_box_pack_start(GTK_BOX(vbox_scroll), hbox, FALSE, FALSE, 0);
        label = gtk_label_new("VCS Power Supply Unit 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);

        table = gtk_table_new(4, 2, FALSE);
        gtk_box_pack_start(GTK_BOX(vbox_scroll), 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);

        label = gtk_label_new("PSU State:");
        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_widget_set_size_request(label, ctk_object->req.width, -1);
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);


        label = gtk_label_new(NULL);
        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
        ctk_object->psu_state = label;

        label = gtk_label_new("PSU Current:");
        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_widget_set_size_request(label, ctk_object->req.width, -1);
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);


        label = gtk_label_new(NULL);
        gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
        gtk_table_attach(GTK_TABLE(table), label, 1, 2, 1, 2,
                         GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
        ctk_object->psu_current = label;

        current_row = 2;

        if (psuEntry.psu_power != -1) {
            label = gtk_label_new("PSU Power:");
            gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
            gtk_widget_set_size_request(label, ctk_object->req.width, -1);
            gtk_table_attach(GTK_TABLE(table), label, 0, 1, 
                             current_row, current_row + 1,
                             GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

            label = gtk_label_new(NULL);
            gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
            gtk_table_attach(GTK_TABLE(table), label, 1, 2, 
                             current_row, current_row + 1,
                             GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
            ctk_object->psu_power = label;
            current_row++;
        }

        if (psuEntry.psu_voltage != -1) {
            label = gtk_label_new("PSU Voltage:");
            gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
            gtk_widget_set_size_request(label, ctk_object->req.width, -1);
            gtk_table_attach(GTK_TABLE(table), label, 0, 1, 
                             current_row, current_row + 1,
                             GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);

            label = gtk_label_new(NULL);
            gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
            gtk_table_attach(GTK_TABLE(table), label, 1, 2, 
                             current_row, current_row + 1,
                             GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
            ctk_object->psu_voltage = label;
        }

        /* Create container for fan status table */

        vbox_padding = gtk_vbox_new(FALSE, 0);
        hbox = gtk_hbox_new(FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox_scroll), vbox_padding, FALSE, FALSE, 1);
        gtk_box_pack_start(GTK_BOX(vbox_scroll), hbox, FALSE, FALSE, 0);
        label = gtk_label_new("VCS Fan 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);

        hbox = gtk_hbox_new(FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox_scroll), hbox, FALSE, FALSE, 0);
        ctk_object->fan_status_container = hbox;

        /* Register a timer callback to update the dynamic information */
        s = g_strdup_printf("VCS Monitor (VCS %d)",
                            NvCtrlGetTargetId(ctk_object->handle));

        ctk_config_add_timer(ctk_object->ctk_config,
                             DEFAULT_UPDATE_VCS_INFO_TIME_INTERVAL,
                             s,
                             (GSourceFunc) update_vcs_info,
                             (gpointer) ctk_object);
        g_free(s);

        update_vcs_info(ctk_object);
    }

    gtk_widget_show_all(GTK_WIDGET(object));
    
    return GTK_WIDGET(object);
}