~ubuntu-branches/ubuntu/precise/nvidia-settings/precise-proposed

« back to all changes in this revision

Viewing changes to src/gtk+-2.x/ctkframelock.c

  • Committer: Bazaar Package Importer
  • Author(s): Randall Donald
  • Date: 2004-07-03 19:09:17 UTC
  • Revision ID: james.westby@ubuntu.com-20040703190917-rqkze2s58ux5pamy
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
 
3
 * and Linux systems.
 
4
 *
 
5
 * Copyright (C) 2004 NVIDIA Corporation.
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of Version 2 of the GNU General Public
 
9
 * License as published by the Free Software Foundation.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
 
14
 * of the GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the:
 
18
 *
 
19
 *           Free Software Foundation, Inc.
 
20
 *           59 Temple Place - Suite 330
 
21
 *           Boston, MA 02111-1307, USA
 
22
 *
 
23
 */
 
24
 
 
25
#include <gtk/gtk.h>
 
26
#include <NvCtrlAttributes.h>
 
27
#include <stdlib.h>
 
28
#include <stdio.h>
 
29
#include <string.h>
 
30
 
 
31
#include "ctkframelock.h"
 
32
#include "ctkhelp.h"
 
33
 
 
34
#include "frame_lock_banner.h"
 
35
#include "led_green.h"
 
36
#include "led_red.h"
 
37
#include "led_grey.h"
 
38
 
 
39
#include "rj45_input.h"
 
40
#include "rj45_output.h"
 
41
 
 
42
#include "parse.h"
 
43
#include "msg.h"
 
44
 
 
45
 
 
46
#define DEFAULT_UPDATE_STATUS_TIME_INTERVAL 1000
 
47
#define DEFAULT_TEST_LINK_TIME_INTERVAL 2000
 
48
#define DEFAULT_CHECK_FOR_ETHERNET_TIME_INTERVAL 10000
 
49
 
 
50
#define POLARITY_RISING 0x1
 
51
#define POLARITY_FALLING 0x2
 
52
#define POLARITY_BOTH 0x3
 
53
 
 
54
/*
 
55
 * functions for the FrameLock Widget
 
56
 */
 
57
 
 
58
static void ctk_framelock_class_init(CtkFramelockClass *ctk_framelock_class);
 
59
 
 
60
static gpointer add_x_screen(CtkFramelock *, const gchar *, gboolean);
 
61
static GtkWidget *create_add_x_screen_dialog(CtkFramelock *ctk_framelock);
 
62
static GtkWidget *create_remove_x_screen_dialog(CtkFramelock *ctk_framelock);
 
63
static GtkWidget *create_error_msg_dialog(CtkFramelock *ctk_framelock);
 
64
static GtkWidget *create_sync_state_button(CtkFramelock *ctk_framelock);
 
65
 
 
66
static gboolean update_status(gpointer user_data);
 
67
static gboolean check_for_ethernet(gpointer user_data);
 
68
 
 
69
static void test_link(GtkWidget *button, CtkFramelock *ctk_framelock);
 
70
static gint test_link_done(gpointer data);
 
71
 
 
72
static void toggle_sync_state_button(GtkWidget *button,
 
73
                                     CtkFramelock *ctk_framelock);
 
74
 
 
75
static void show_remove_x_screen_dialog(GtkWidget *, CtkFramelock *);
 
76
static void error_msg(CtkFramelock *ctk_framelock, const gchar *fmt, ...);
 
77
 
 
78
 
 
79
 
 
80
static void create_list_store(CtkFramelock *ctk_framelock);
 
81
static void add_member_to_list_store(CtkFramelock *ctk_framelock,
 
82
                                     const gpointer handle);
 
83
 
 
84
static void apply_parsed_attribute_list(CtkFramelock *ctk_framelock,
 
85
                                        ParsedAttribute *p);
 
86
 
 
87
static GtkWidget *add_house_sync_controls(CtkFramelock *ctk_framelock);
 
88
static void update_house_sync_controls(CtkFramelock *ctk_framelock);
 
89
 
 
90
static void add_columns_to_treeview(CtkFramelock *ctk_framelock);
 
91
 
 
92
static void sync_interval_entry_activate(GtkEntry *, gpointer);
 
93
static void house_sync_format_entry_activate(GtkEditable *, gpointer);
 
94
 
 
95
static gboolean find_master(CtkFramelock *, GtkTreeIter *,
 
96
                            NvCtrlAttributeHandle **);
 
97
 
 
98
enum
 
99
{
 
100
    COLUMN_HANDLE,
 
101
    COLUMN_DISPLAY_MASK,
 
102
    COLUMN_DISPLAY_NAME,
 
103
    COLUMN_MASTER,
 
104
    COLUMN_STEREO_SYNC,
 
105
    COLUMN_TIMING,
 
106
    COLUMN_SYNC_READY,
 
107
    COLUMN_SYNC_RATE,
 
108
    COLUMN_HOUSE,
 
109
    COLUMN_RJ45_PORT0,
 
110
    COLUMN_RJ45_PORT1,
 
111
    COLUMN_POLARITY,
 
112
    COLUMN_SYNC_SKEW,
 
113
    COLUMN_SYNC_INTERVAL,
 
114
    COLUMN_HOUSE_FORMAT,
 
115
    NUM_COLUMNS
 
116
};
 
117
 
 
118
 
 
119
 
 
120
 
 
121
/*
 
122
 * helper functions for displaying the correct thing in the columns of
 
123
 * the tree view
 
124
 */
 
125
 
 
126
static void led_renderer_func       (GtkTreeViewColumn *tree_column,
 
127
                                     GtkCellRenderer   *cell,
 
128
                                     GtkTreeModel      *model,
 
129
                                     GtkTreeIter       *iter,
 
130
                                     gpointer           data);
 
131
 
 
132
static void rj45_renderer_func      (GtkTreeViewColumn *tree_column,
 
133
                                     GtkCellRenderer   *cell,
 
134
                                     GtkTreeModel      *model,
 
135
                                     GtkTreeIter       *iter,
 
136
                                     gpointer           data);
 
137
 
 
138
static void rate_renderer_func      (GtkTreeViewColumn *tree_column,
 
139
                                     GtkCellRenderer   *cell,
 
140
                                     GtkTreeModel      *model,
 
141
                                     GtkTreeIter       *iter,
 
142
                                     gpointer           data);
 
143
 
 
144
static void polarity_renderer_func  (GtkTreeViewColumn *tree_column,
 
145
                                     GtkCellRenderer   *cell,
 
146
                                     GtkTreeModel      *model,
 
147
                                     GtkTreeIter       *iter,
 
148
                                     gpointer           data);
 
149
 
 
150
static void sync_skew_renderer_func (GtkTreeViewColumn *tree_column,
 
151
                                     GtkCellRenderer   *cell,
 
152
                                     GtkTreeModel      *model,
 
153
                                     GtkTreeIter       *iter,
 
154
                                     gpointer           data);
 
155
 
 
156
/* callback functions */
 
157
 
 
158
static void master_toggled(GtkCellRendererToggle *cell, 
 
159
                           gchar                 *path_str,
 
160
                           gpointer               data);
 
161
 
 
162
static void rising_edge_toggled(GtkCellRendererToggle *cell,
 
163
                                gchar                 *path_string,
 
164
                                gpointer               user_data);
 
165
 
 
166
static void falling_edge_toggled(GtkCellRendererToggle *cell,
 
167
                                 gchar                 *path_string,
 
168
                                 gpointer               user_data);
 
169
 
 
170
static void sync_skew_edited(GtkCellRendererText *cell,
 
171
                             const gchar         *path_string,
 
172
                             const gchar         *new_text,
 
173
                             gpointer             data);
 
174
 
 
175
static GObjectClass *parent_class;
 
176
 
 
177
 
 
178
 
 
179
/*
 
180
 * ctk_framelock_get_type() - register the FrameLock class and
 
181
 * return the unique type id.
 
182
 */
 
183
 
 
184
GType ctk_framelock_get_type(
 
185
    void
 
186
)
 
187
{
 
188
    static GType ctk_framelock_type = 0;
 
189
 
 
190
    if (!ctk_framelock_type) {
 
191
        static const GTypeInfo ctk_framelock_info = {
 
192
            sizeof (CtkFramelockClass),
 
193
            NULL, /* base_init */
 
194
            NULL, /* base_finalize */
 
195
            (GClassInitFunc) ctk_framelock_class_init,
 
196
            NULL, /* class_finalize */
 
197
            NULL, /* class_data */
 
198
            sizeof (CtkFramelock),
 
199
            0, /* n_preallocs */
 
200
            NULL, /* instance_init */
 
201
        };
 
202
        
 
203
        ctk_framelock_type = g_type_register_static
 
204
            (GTK_TYPE_VBOX, "CtkFramelock", &ctk_framelock_info, 0);
 
205
    }
 
206
 
 
207
    return ctk_framelock_type;
 
208
 
 
209
} /* ctk_framelock_get_type() */
 
210
 
 
211
 
 
212
 
 
213
 
 
214
/*
 
215
 * ctk_framelock_class_init() - initialize the object structure
 
216
 */
 
217
 
 
218
static void ctk_framelock_class_init(
 
219
    CtkFramelockClass *ctk_framelock_class
 
220
)
 
221
{
 
222
    GObjectClass *gobject_class;
 
223
 
 
224
    gobject_class = (GObjectClass *) ctk_framelock_class;
 
225
    parent_class = g_type_class_peek_parent(ctk_framelock_class);
 
226
 
 
227
} /* ctk_framelock_class_init() */
 
228
 
 
229
 
 
230
 
 
231
/*
 
232
 * ctk_framelock_new() - return a new instance of the FrameLock
 
233
 * class.
 
234
 */
 
235
 
 
236
GtkWidget* ctk_framelock_new(NvCtrlAttributeHandle *handle,
 
237
                             GtkWidget *parent_window, CtkConfig *ctk_config,
 
238
                             ParsedAttribute *p)
 
239
{
 
240
    GObject *object;
 
241
    CtkFramelock *ctk_framelock;
 
242
    GtkWidget *hbox;
 
243
    GtkWidget *hbox2;
 
244
    GtkWidget *label;
 
245
    GtkWidget *frame;
 
246
    GtkWidget *image;
 
247
    GtkWidget *sw;
 
248
    GtkWidget *hseparator;
 
249
    gint value;
 
250
 
 
251
    guint8 *image_buffer = NULL;
 
252
    const nv_image_t *img;
 
253
 
 
254
    /* make sure we have a handle */
 
255
 
 
256
    g_return_val_if_fail(handle != NULL, NULL);
 
257
 
 
258
    /*
 
259
     * Only expose FrameLock if the current NV-CONTROL handle supports
 
260
     * FrameLock.  This isn't absolutely necessary, because the
 
261
     * FrameLock control page does not have to include the current
 
262
     * NV-CONTROL handle in the FrameLock Group.  However, we don't
 
263
     * want to expose the FrameLock page unconditionally (it would
 
264
     * only confuse most users), so this is as good a condition as
 
265
     * anything else.
 
266
     */
 
267
    
 
268
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK, &value);
 
269
    if (value != NV_CTRL_FRAMELOCK_SUPPORTED) return NULL;
 
270
    
 
271
    /* create a new instance of the object */
 
272
    
 
273
    object = g_object_new(CTK_TYPE_FRAMELOCK, NULL);
 
274
    
 
275
    ctk_framelock = CTK_FRAMELOCK(object);
 
276
    ctk_framelock->attribute_handle = handle;
 
277
    ctk_framelock->parent_window = GTK_WINDOW(parent_window);
 
278
 
 
279
    gtk_box_set_spacing(GTK_BOX(ctk_framelock), 10);
 
280
 
 
281
    /* banner */
 
282
 
 
283
    hbox = gtk_hbox_new(FALSE, 0);
 
284
    gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
 
285
 
 
286
    frame = gtk_frame_new(NULL);
 
287
    gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
 
288
    
 
289
    gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
 
290
 
 
291
    img = &frame_lock_banner_image;
 
292
 
 
293
    image_buffer = decompress_image_data(img);
 
294
 
 
295
    image = gtk_image_new_from_pixbuf
 
296
        (gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
 
297
                                  FALSE, 8, img->width, img->height,
 
298
                                  img->width * img->bytes_per_pixel,
 
299
                                  free_decompressed_image, NULL));
 
300
 
 
301
    gtk_container_add(GTK_CONTAINER(frame), image);
 
302
 
 
303
    /* scrollable list */
 
304
 
 
305
    sw = gtk_scrolled_window_new(NULL, NULL);
 
306
    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
 
307
                                        GTK_SHADOW_IN);
 
308
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
 
309
                                   GTK_POLICY_AUTOMATIC,
 
310
                                   GTK_POLICY_ALWAYS);
 
311
    gtk_box_pack_start(GTK_BOX(object), sw, TRUE, TRUE, 0);
 
312
    
 
313
    /* create the list store and treeview */
 
314
 
 
315
    create_list_store(ctk_framelock);
 
316
 
 
317
    /* plug the treeview into the scrollable window */
 
318
    
 
319
    gtk_container_add(GTK_CONTAINER(sw), GTK_WIDGET(ctk_framelock->treeview));
 
320
      
 
321
    hseparator = gtk_hseparator_new();
 
322
    gtk_box_pack_start(GTK_BOX(object), hseparator, FALSE, TRUE, 0);
 
323
 
 
324
    /* Sync Interval and House Sync Format controls */
 
325
    
 
326
    hbox = add_house_sync_controls(ctk_framelock);
 
327
    gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, TRUE, 0);
 
328
    
 
329
    hseparator = gtk_hseparator_new();
 
330
    gtk_box_pack_start(GTK_BOX(object), hseparator, FALSE, TRUE, 0);
 
331
 
 
332
    /* create any needed dialog windows */
 
333
 
 
334
    ctk_framelock->add_x_screen_dialog =
 
335
        create_add_x_screen_dialog(ctk_framelock);
 
336
 
 
337
    ctk_framelock->remove_x_screen_dialog =
 
338
        create_remove_x_screen_dialog(ctk_framelock);
 
339
 
 
340
    ctk_framelock->error_msg_dialog =
 
341
        create_error_msg_dialog(ctk_framelock);
 
342
 
 
343
    /* create buttons */
 
344
        
 
345
    hbox = gtk_hbox_new(FALSE, 5);
 
346
    gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, TRUE, 0);
 
347
    
 
348
    /* "Add X Screen..." button */
 
349
 
 
350
    label = gtk_label_new("Add X Screen...");
 
351
    hbox2 = gtk_hbox_new(FALSE, 0);
 
352
    ctk_framelock->add_x_screen_button = gtk_button_new();
 
353
    
 
354
    gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 15);
 
355
    gtk_container_add(GTK_CONTAINER(ctk_framelock->add_x_screen_button),
 
356
                      hbox2);
 
357
    
 
358
    gtk_box_pack_start(GTK_BOX(hbox), ctk_framelock->add_x_screen_button,
 
359
                       FALSE, TRUE, 0);
 
360
    
 
361
    g_signal_connect_swapped(G_OBJECT(ctk_framelock->add_x_screen_button),
 
362
                             "clicked", G_CALLBACK(gtk_widget_show_all),
 
363
                             (gpointer) ctk_framelock->add_x_screen_dialog);
 
364
 
 
365
    /* "Remove X Screen..." button */
 
366
 
 
367
    label = gtk_label_new("Remove X Screen...");
 
368
    hbox2 = gtk_hbox_new(FALSE, 0);
 
369
    ctk_framelock->remove_x_screen_button = gtk_button_new();
 
370
 
 
371
    gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 15);
 
372
    gtk_container_add(GTK_CONTAINER(ctk_framelock->remove_x_screen_button),
 
373
                      hbox2);
 
374
 
 
375
    gtk_box_pack_start(GTK_BOX(hbox), ctk_framelock->remove_x_screen_button,
 
376
                       FALSE, TRUE, 0);
 
377
    gtk_widget_set_sensitive(ctk_framelock->remove_x_screen_button, FALSE);
 
378
    
 
379
    g_signal_connect(G_OBJECT(ctk_framelock->remove_x_screen_button),
 
380
                     "clicked", G_CALLBACK(show_remove_x_screen_dialog),
 
381
                     GTK_OBJECT(ctk_framelock));
 
382
    
 
383
    /* "Test Link" button */
 
384
 
 
385
    label = gtk_label_new("Test Link");
 
386
    hbox2 = gtk_hbox_new(FALSE, 0);
 
387
    ctk_framelock->test_link_button = gtk_toggle_button_new();
 
388
    
 
389
    gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 15);
 
390
    gtk_container_add(GTK_CONTAINER(ctk_framelock->test_link_button), hbox2);
 
391
 
 
392
    gtk_box_pack_start(GTK_BOX(hbox), ctk_framelock->test_link_button,
 
393
                       FALSE, TRUE, 0);
 
394
        
 
395
    gtk_widget_set_sensitive(ctk_framelock->test_link_button, FALSE);
 
396
 
 
397
    g_signal_connect(G_OBJECT(ctk_framelock->test_link_button), "toggled",
 
398
                     G_CALLBACK(test_link), GTK_OBJECT(ctk_framelock));
 
399
    
 
400
    /* Sync State button */
 
401
 
 
402
    ctk_framelock->sync_state_button = create_sync_state_button(ctk_framelock);
 
403
 
 
404
    gtk_box_pack_start(GTK_BOX(hbox), ctk_framelock->sync_state_button,
 
405
                       FALSE, TRUE, 0);
 
406
 
 
407
    gtk_widget_set_sensitive(ctk_framelock->sync_state_button, FALSE);
 
408
    
 
409
    g_signal_connect(G_OBJECT(ctk_framelock->sync_state_button), "toggled",
 
410
                     G_CALLBACK(toggle_sync_state_button),
 
411
                     GTK_OBJECT(ctk_framelock));
 
412
    
 
413
    /* show the page */
 
414
    
 
415
    gtk_widget_show_all(GTK_WIDGET(object));
 
416
    
 
417
    /* register a timer callback to update the status of the page */
 
418
 
 
419
    ctk_config_add_timer(ctk_config, DEFAULT_UPDATE_STATUS_TIME_INTERVAL,
 
420
                         "FrameLock Connection Status",
 
421
                         (GSourceFunc) update_status,
 
422
                         (gpointer) ctk_framelock);
 
423
    
 
424
    /* register a timer callback to check the rj45 ports */
 
425
 
 
426
    ctk_config_add_timer(ctk_config, DEFAULT_CHECK_FOR_ETHERNET_TIME_INTERVAL,
 
427
                         "FrameLock RJ45 Check",
 
428
                         (GSourceFunc) check_for_ethernet,
 
429
                         (gpointer) ctk_framelock);
 
430
 
 
431
    ctk_framelock->ctk_config = ctk_config;
 
432
 
 
433
    /* create the watch cursor */
 
434
 
 
435
    ctk_framelock->wait_cursor = gdk_cursor_new(GDK_WATCH);
 
436
    
 
437
    /* apply the parsed attribute list */
 
438
 
 
439
    apply_parsed_attribute_list(ctk_framelock, p);
 
440
    
 
441
    return GTK_WIDGET(object);
 
442
    
 
443
} /* ctk_framelock_new() */
 
444
 
 
445
 
 
446
 
 
447
/**************************************************************************/
 
448
 
 
449
static gchar *houseFormatStrings[] = {
 
450
    "Composite, Auto",      /* VIDEO_MODE_COMPOSITE_AUTO */
 
451
    "TTL",                  /* VIDEO_MODE_TTL */
 
452
    "Composite, Bi-Level",  /* VIDEO_MODE_COMPOSITE_BI_LEVEL */
 
453
    "Composite, Tri-Level", /* VIDEO_MODE_COMPOSITE_TRI_LEVEL */
 
454
    };
 
455
 
 
456
static void detect_house_sync_format_toggled(GtkToggleButton *togglebutton,
 
457
                                             gpointer user_data);
 
458
 
 
459
/*
 
460
 * House Sync autodetection scheme: a modal push button is used to
 
461
 * request auto detection.  When the button is pressed, we program the
 
462
 * first format type and then start a timer.
 
463
 *
 
464
 * From the timer, we check if we are getting a house sync; if we are,
 
465
 * then update the settings and unpress the button.  If we are not,
 
466
 * program the next format in the sequence and try again.
 
467
 */
 
468
 
 
469
 
 
470
/*
 
471
 * detect_house_sync_format_timer() - 
 
472
 */
 
473
 
 
474
static gboolean detect_house_sync_format_timer(gpointer user_data)
 
475
{
 
476
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(user_data);
 
477
    NvCtrlAttributeHandle *handle = NULL;
 
478
    gint house;
 
479
    GtkTreeIter iter;
 
480
 
 
481
    if (!find_master(ctk_framelock, &iter, &handle)) {
 
482
        goto done;
 
483
    }
 
484
 
 
485
    /* check if we now have house sync */
 
486
    
 
487
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_HOUSE_STATUS, &house);
 
488
 
 
489
    if (house) {
 
490
        GtkTreeModel *model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
491
        /*
 
492
         * We found house sync; use the current_detect_format
 
493
         */
 
494
 
 
495
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
496
                           COLUMN_HOUSE, house, -1);
 
497
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
498
                           COLUMN_HOUSE_FORMAT,
 
499
                           ctk_framelock->current_detect_format, -1);
 
500
        
 
501
        update_house_sync_controls(ctk_framelock);
 
502
 
 
503
        ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
504
                                     "House Sync format detected as %s.",
 
505
                                     houseFormatStrings
 
506
                                     [ctk_framelock->current_detect_format]);
 
507
        
 
508
        goto done;
 
509
    }
 
510
 
 
511
    /*
 
512
     * we did not find house sync, yet, so move to the next format
 
513
     */
 
514
    
 
515
    switch (ctk_framelock->current_detect_format) {
 
516
 
 
517
    case NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_AUTO:
 
518
        ctk_framelock->current_detect_format =
 
519
            NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_BI_LEVEL;
 
520
        break;
 
521
        
 
522
    case NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_BI_LEVEL:
 
523
        ctk_framelock->current_detect_format =
 
524
            NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_TRI_LEVEL;
 
525
        break;
 
526
        
 
527
    case NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_TRI_LEVEL:
 
528
        ctk_framelock->current_detect_format =
 
529
            NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL;
 
530
        break;
 
531
 
 
532
    case NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL:
 
533
        ctk_framelock->current_detect_format =
 
534
            NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_AUTO;
 
535
        ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
536
                                     "Unable to detect house sync format.");
 
537
        goto done;
 
538
        break;
 
539
    }
 
540
    
 
541
    /*
 
542
     * Set the new video format
 
543
     */
 
544
 
 
545
    NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_VIDEO_MODE,
 
546
                       ctk_framelock->current_detect_format);
 
547
 
 
548
    return TRUE;
 
549
 
 
550
 done:
 
551
 
 
552
    /* untoggle the detect button */
 
553
    
 
554
    g_signal_handlers_block_by_func
 
555
        (G_OBJECT(ctk_framelock->house_format_detect),
 
556
         G_CALLBACK(detect_house_sync_format_toggled),
 
557
         (gpointer) ctk_framelock);
 
558
 
 
559
    gtk_toggle_button_set_active
 
560
        (GTK_TOGGLE_BUTTON(ctk_framelock->house_format_detect), FALSE);
 
561
    
 
562
    g_signal_handlers_unblock_by_func
 
563
        (G_OBJECT(ctk_framelock->house_format_detect),
 
564
         G_CALLBACK(detect_house_sync_format_toggled),
 
565
         (gpointer) ctk_framelock);
 
566
 
 
567
    /* do not call this timer any more */
 
568
    
 
569
    return FALSE;
 
570
    
 
571
} /* detect_house_sync_format_timer() */
 
572
 
 
573
 
 
574
 
 
575
/*
 
576
 * detect_house_sync_format_toggled() - called when the house sync
 
577
 * "detect" button is toggled.  If the toggle button is active, then
 
578
 * start the detect sequence by programming
 
579
 * NV_CTRL_FRAMELOCK_VIDEO_MODE to COMPOSITE_AUTO
 
580
 *
 
581
 * XXX what happens if the master gets changed while we are doing
 
582
 * this?
 
583
 */
 
584
 
 
585
static void detect_house_sync_format_toggled(GtkToggleButton *togglebutton,
 
586
                                             gpointer user_data)
 
587
{
 
588
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(user_data);
 
589
    NvCtrlAttributeHandle *handle = NULL;
 
590
    
 
591
    if (gtk_toggle_button_get_active(togglebutton)) {
 
592
        
 
593
        /*
 
594
         * the toggle button is active: we now start scanning through
 
595
         * the possible input video modes and enable the house sync
 
596
         * format timer.
 
597
         */
 
598
        
 
599
        if (!find_master(ctk_framelock, NULL, &handle)) {
 
600
 
 
601
            g_signal_handlers_block_by_func
 
602
                (G_OBJECT(ctk_framelock->house_format_detect),
 
603
                 G_CALLBACK(detect_house_sync_format_toggled),
 
604
                 (gpointer) ctk_framelock);
 
605
            
 
606
            gtk_toggle_button_set_active
 
607
                (GTK_TOGGLE_BUTTON(ctk_framelock->house_format_detect), FALSE);
 
608
 
 
609
            g_signal_handlers_unblock_by_func
 
610
                (G_OBJECT(ctk_framelock->house_format_detect),
 
611
                 G_CALLBACK(detect_house_sync_format_toggled),
 
612
                 (gpointer) ctk_framelock);
 
613
            
 
614
            return;
 
615
        }
 
616
        
 
617
        ctk_framelock->current_detect_format =
 
618
            NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_AUTO;
 
619
 
 
620
        NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_VIDEO_MODE,
 
621
                           ctk_framelock->current_detect_format);
 
622
        
 
623
        ctk_framelock->house_format_detect_timer =
 
624
            g_timeout_add(500, detect_house_sync_format_timer, user_data);
 
625
        
 
626
        ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
627
                                     "Attempting to detect house sync...");
 
628
    } else {
 
629
        
 
630
        /*
 
631
         * the toggle button is no longer active: disable the timer
 
632
         */
 
633
        
 
634
        g_source_remove(ctk_framelock->house_format_detect_timer);
 
635
        ctk_framelock->house_format_detect_timer = 0;
 
636
 
 
637
        ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
638
                                     "Aborted house sync detection.");
 
639
    }
 
640
    
 
641
} /* detect_house_sync_format_toggled() */
 
642
 
 
643
 
 
644
 
 
645
/*
 
646
 * add_house_sync_controls() -
 
647
 */
 
648
 
 
649
static GtkWidget *add_house_sync_controls(CtkFramelock *ctk_framelock)
 
650
{
 
651
    GtkWidget *hbox;
 
652
    GtkWidget *hbox2;
 
653
    GtkWidget *label;
 
654
    GList *glist;
 
655
    
 
656
    hbox = gtk_hbox_new(FALSE, 5);
 
657
    
 
658
    /* sync interval */
 
659
 
 
660
    ctk_framelock->sync_interval_frame = gtk_frame_new(NULL);
 
661
    gtk_box_pack_start(GTK_BOX(hbox), ctk_framelock->sync_interval_frame,
 
662
                       FALSE, TRUE, 0);
 
663
    
 
664
    hbox2 = gtk_hbox_new(FALSE, 5);
 
665
    gtk_container_add(GTK_CONTAINER(ctk_framelock->sync_interval_frame),hbox2);
 
666
        
 
667
    label = gtk_label_new("Sync Interval:");
 
668
    gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, TRUE, 5);
 
669
    
 
670
    ctk_framelock->sync_interval_entry = gtk_entry_new();
 
671
    gtk_entry_set_text(GTK_ENTRY(ctk_framelock->sync_interval_entry), "0");
 
672
    gtk_entry_set_width_chars
 
673
        (GTK_ENTRY(ctk_framelock->sync_interval_entry), 4);
 
674
    gtk_box_pack_start
 
675
        (GTK_BOX(hbox2), ctk_framelock->sync_interval_entry, FALSE, TRUE, 5);
 
676
 
 
677
    g_signal_connect(G_OBJECT(ctk_framelock->sync_interval_entry),
 
678
                     "activate", G_CALLBACK(sync_interval_entry_activate),
 
679
                     (gpointer) ctk_framelock);
 
680
    
 
681
    /* house format */
 
682
 
 
683
    ctk_framelock->house_format_frame = gtk_frame_new(NULL);
 
684
    gtk_box_pack_start(GTK_BOX(hbox),
 
685
                       ctk_framelock->house_format_frame, FALSE, TRUE, 0);
 
686
    
 
687
    hbox2 = gtk_hbox_new(FALSE, 5);
 
688
    gtk_container_add(GTK_CONTAINER(ctk_framelock->house_format_frame), hbox2);
 
689
    
 
690
    label = gtk_label_new("House Sync Format:");
 
691
    gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, TRUE, 5);
 
692
    
 
693
    ctk_framelock->house_format_combo = gtk_combo_new();
 
694
    glist = NULL;
 
695
    
 
696
    glist = g_list_append
 
697
        (glist,
 
698
         houseFormatStrings[NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_AUTO]);
 
699
    
 
700
    glist = g_list_append
 
701
        (glist,
 
702
         houseFormatStrings[NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_BI_LEVEL]);
 
703
    
 
704
    glist = g_list_append
 
705
        (glist,
 
706
         houseFormatStrings[NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_TRI_LEVEL]);
 
707
    
 
708
    glist = g_list_append
 
709
        (glist, houseFormatStrings[NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL]);
 
710
    
 
711
    gtk_combo_set_popdown_strings
 
712
        (GTK_COMBO(ctk_framelock->house_format_combo), glist);
 
713
    gtk_editable_set_editable
 
714
        (GTK_EDITABLE(GTK_COMBO(ctk_framelock->house_format_combo)->entry),
 
715
         FALSE);
 
716
    
 
717
    g_signal_connect
 
718
        (G_OBJECT(GTK_EDITABLE
 
719
                  (GTK_COMBO(ctk_framelock->house_format_combo)->entry)),
 
720
         "changed", G_CALLBACK(house_sync_format_entry_activate),
 
721
         (gpointer) ctk_framelock);
 
722
    
 
723
    gtk_box_pack_start(GTK_BOX(hbox2),
 
724
                       ctk_framelock->house_format_combo, FALSE, TRUE, 5);
 
725
 
 
726
    /* detect button */
 
727
 
 
728
    ctk_framelock->house_format_detect =
 
729
        gtk_toggle_button_new_with_label("Detect");
 
730
    gtk_box_pack_start(GTK_BOX(hbox2),
 
731
                       ctk_framelock->house_format_detect, FALSE, TRUE, 5);
 
732
 
 
733
    g_signal_connect(G_OBJECT(ctk_framelock->house_format_detect), "toggled",
 
734
                     G_CALLBACK(detect_house_sync_format_toggled),
 
735
                     ctk_framelock);
 
736
 
 
737
    return hbox;
 
738
    
 
739
} /* add_house_sync_controls() */
 
740
 
 
741
 
 
742
 
 
743
/*
 
744
 * update_house_sync_controls() - update the gui with the current
 
745
 * sw-state of the house sync control values.
 
746
 */
 
747
 
 
748
static void update_house_sync_controls(CtkFramelock *ctk_framelock)
 
749
{
 
750
    GtkTreeModel *model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
751
    gboolean house = FALSE, sensitive;
 
752
    gint sync_interval, house_format;
 
753
    gchar str[32];
 
754
    GtkTreeIter iter;
 
755
    
 
756
    if (find_master(ctk_framelock, &iter, NULL)) {
 
757
        gtk_tree_model_get(model,                &iter,
 
758
                           COLUMN_HOUSE,         &house,
 
759
                           COLUMN_SYNC_INTERVAL, &sync_interval,
 
760
                           COLUMN_HOUSE_FORMAT,  &house_format,
 
761
                           -1);
 
762
        
 
763
        snprintf(str, 32, "%d", sync_interval);
 
764
        gtk_entry_set_text(GTK_ENTRY(ctk_framelock->sync_interval_entry),str); 
 
765
        
 
766
        if (house_format < NV_CTRL_FRAMELOCK_VIDEO_MODE_NONE)
 
767
            house_format = NV_CTRL_FRAMELOCK_VIDEO_MODE_NONE;
 
768
        if (house_format > NV_CTRL_FRAMELOCK_VIDEO_MODE_HDTV)
 
769
            house_format = NV_CTRL_FRAMELOCK_VIDEO_MODE_HDTV;
 
770
        
 
771
        gtk_entry_set_text
 
772
            (GTK_ENTRY(GTK_COMBO(ctk_framelock->house_format_combo)->entry),
 
773
             houseFormatStrings[house_format]);
 
774
    }
 
775
    
 
776
    if (ctk_framelock->framelock_enabled) {
 
777
        sensitive = FALSE;
 
778
    } else {
 
779
        sensitive = TRUE;
 
780
    }
 
781
    
 
782
    gtk_widget_set_sensitive(ctk_framelock->sync_interval_frame, sensitive);
 
783
    gtk_widget_set_sensitive(ctk_framelock->house_format_frame, sensitive);  
 
784
    
 
785
} /* update_house_sync_controls() */
 
786
 
 
787
 
 
788
 
 
789
static void sync_interval_entry_activate(GtkEntry *entry, gpointer user_data)
 
790
{
 
791
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(user_data);
 
792
    NvCtrlAttributeHandle *handle = NULL;
 
793
    const gchar *str = gtk_entry_get_text(entry);
 
794
    gint interval;
 
795
    
 
796
    interval = strtol(str, NULL, 10);
 
797
    
 
798
    if (find_master(ctk_framelock, NULL, &handle)) {
 
799
        NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_SYNC_INTERVAL, interval);
 
800
    }
 
801
}
 
802
 
 
803
static void house_sync_format_entry_activate(GtkEditable *editable,
 
804
                                             gpointer user_data)
 
805
{
 
806
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(user_data);
 
807
    const gchar *str = gtk_entry_get_text
 
808
        (GTK_ENTRY(GTK_COMBO(ctk_framelock->house_format_combo)->entry));
 
809
    NvCtrlAttributeHandle *handle = NULL;
 
810
    gint mode;
 
811
 
 
812
    for (mode = NV_CTRL_FRAMELOCK_VIDEO_MODE_NONE;
 
813
         mode <= NV_CTRL_FRAMELOCK_VIDEO_MODE_HDTV; mode++) {
 
814
        
 
815
        if (strcmp(houseFormatStrings[mode], str) == 0) {
 
816
 
 
817
            if (find_master(ctk_framelock, NULL, &handle)) {
 
818
                NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_VIDEO_MODE, mode);
 
819
            }
 
820
            return;
 
821
        }
 
822
    }
 
823
} /* house_sync_format_entry_activate() */
 
824
 
 
825
 
 
826
 
 
827
/*
 
828
 * add_columns_to_treeview() - add the columns to the treeview,
 
829
 * assigning renderer functions as necessary
 
830
 */
 
831
 
 
832
static void add_columns_to_treeview(CtkFramelock *ctk_framelock)
 
833
{
 
834
    GtkCellRenderer *renderer;
 
835
    GtkTreeViewColumn *column;
 
836
    
 
837
    /* column for display name */
 
838
    
 
839
    renderer = gtk_cell_renderer_text_new();
 
840
    column = gtk_tree_view_column_new_with_attributes("Display",
 
841
                                                      renderer,
 
842
                                                      "text",
 
843
                                                      COLUMN_DISPLAY_NAME,
 
844
                                                      NULL);
 
845
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
846
    gtk_tree_view_column_set_resizable(column, TRUE);
 
847
    
 
848
    /* column for master toggles */
 
849
    
 
850
    renderer = gtk_cell_renderer_toggle_new();
 
851
    gtk_cell_renderer_toggle_set_radio((GtkCellRendererToggle*)renderer, TRUE);
 
852
    g_signal_connect(renderer, "toggled",
 
853
                     G_CALLBACK(master_toggled), ctk_framelock);
 
854
    
 
855
    column = gtk_tree_view_column_new_with_attributes("Master",
 
856
                                                      renderer,
 
857
                                                      "active",
 
858
                                                      COLUMN_MASTER,
 
859
                                                      NULL);
 
860
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
861
    gtk_tree_view_column_set_resizable(column, TRUE);
 
862
    
 
863
 
 
864
    /* column for stereo */
 
865
    
 
866
    renderer = gtk_cell_renderer_pixbuf_new();
 
867
    column = gtk_tree_view_column_new_with_attributes("Stereo Sync",
 
868
                                                      renderer,
 
869
                                                      NULL);
 
870
    
 
871
    gtk_tree_view_column_set_cell_data_func(column,
 
872
                                            renderer,
 
873
                                            led_renderer_func,
 
874
                                            GINT_TO_POINTER
 
875
                                            (COLUMN_STEREO_SYNC),
 
876
                                            NULL);
 
877
    
 
878
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
879
    gtk_tree_view_column_set_resizable(column, TRUE);
 
880
 
 
881
    /* column for timing */
 
882
 
 
883
    renderer = gtk_cell_renderer_pixbuf_new();
 
884
    column = gtk_tree_view_column_new_with_attributes("Timing",
 
885
                                                      renderer,
 
886
                                                      NULL);
 
887
 
 
888
    /*
 
889
     * led_renderer_func() needs the ctk_framelock, but only when
 
890
     * dealing with the Timing column; so hook a pointer to
 
891
     * ctk_framelock off of this ViewColumn widget.
 
892
     */
 
893
    
 
894
    g_object_set_data(G_OBJECT(column), "ctk_framelock", ctk_framelock);
 
895
    
 
896
    gtk_tree_view_column_set_cell_data_func(column,
 
897
                                            renderer,
 
898
                                            led_renderer_func,
 
899
                                            GINT_TO_POINTER(COLUMN_TIMING),
 
900
                                            NULL);
 
901
    
 
902
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
903
    gtk_tree_view_column_set_resizable(column, TRUE);
 
904
 
 
905
    /* column for sync_ready */
 
906
    
 
907
    renderer = gtk_cell_renderer_pixbuf_new();
 
908
    column = gtk_tree_view_column_new_with_attributes("Sync Ready",
 
909
                                                      renderer,
 
910
                                                      NULL);
 
911
    
 
912
    gtk_tree_view_column_set_cell_data_func(column,
 
913
                                            renderer,
 
914
                                            led_renderer_func,
 
915
                                            GINT_TO_POINTER(COLUMN_SYNC_READY),
 
916
                                            NULL);
 
917
    
 
918
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
919
    gtk_tree_view_column_set_resizable(column, TRUE);
 
920
 
 
921
    
 
922
    /* column for sync_rate */
 
923
    
 
924
    renderer = gtk_cell_renderer_text_new();
 
925
    column = gtk_tree_view_column_new_with_attributes("Sync Rate",
 
926
                                                      renderer,
 
927
                                                      NULL);
 
928
    gtk_tree_view_column_set_cell_data_func(column,
 
929
                                            renderer,
 
930
                                            rate_renderer_func,
 
931
                                            GINT_TO_POINTER(COLUMN_SYNC_RATE),
 
932
                                            NULL);
 
933
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
934
    gtk_tree_view_column_set_resizable(column, TRUE);
 
935
 
 
936
 
 
937
    /* column for house */
 
938
    
 
939
    renderer = gtk_cell_renderer_pixbuf_new();
 
940
    column = gtk_tree_view_column_new_with_attributes("House",
 
941
                                                      renderer,
 
942
                                                      NULL);
 
943
    
 
944
    gtk_tree_view_column_set_cell_data_func(column,
 
945
                                            renderer,
 
946
                                            led_renderer_func,
 
947
                                            GINT_TO_POINTER(COLUMN_HOUSE),
 
948
                                            NULL);
 
949
    
 
950
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
951
    gtk_tree_view_column_set_resizable(column, TRUE);
 
952
 
 
953
    /* column for rj45 port0 */
 
954
    
 
955
    renderer = gtk_cell_renderer_pixbuf_new();
 
956
    column = gtk_tree_view_column_new_with_attributes("Port0",
 
957
                                                      renderer,
 
958
                                                      NULL);
 
959
    gtk_tree_view_column_set_cell_data_func(column,
 
960
                                            renderer,
 
961
                                            rj45_renderer_func,
 
962
                                            GINT_TO_POINTER(COLUMN_RJ45_PORT0),
 
963
                                            NULL);
 
964
 
 
965
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
966
    gtk_tree_view_column_set_resizable(column, TRUE);
 
967
 
 
968
    /* column for rj45 port1 */
 
969
    
 
970
    renderer = gtk_cell_renderer_pixbuf_new();
 
971
    column = gtk_tree_view_column_new_with_attributes("Port1",
 
972
                                                      renderer,
 
973
                                                      NULL);
 
974
    
 
975
    gtk_tree_view_column_set_cell_data_func(column,
 
976
                                            renderer,
 
977
                                            rj45_renderer_func,
 
978
                                            GINT_TO_POINTER(COLUMN_RJ45_PORT1),
 
979
                                            NULL);
 
980
 
 
981
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
982
    gtk_tree_view_column_set_resizable(column, TRUE);
 
983
    
 
984
    
 
985
    /* column for rising edge */
 
986
    
 
987
    renderer = gtk_cell_renderer_toggle_new();
 
988
 
 
989
    g_signal_connect(renderer, "toggled",
 
990
                     G_CALLBACK(rising_edge_toggled), ctk_framelock);
 
991
 
 
992
    column = gtk_tree_view_column_new_with_attributes("Rising", renderer,
 
993
                                                      NULL);
 
994
    gtk_tree_view_column_set_cell_data_func(column, renderer,
 
995
                                            polarity_renderer_func,
 
996
                                            GUINT_TO_POINTER(POLARITY_RISING),
 
997
                                            NULL);
 
998
    
 
999
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
1000
    gtk_tree_view_column_set_resizable(column, TRUE);
 
1001
    
 
1002
    
 
1003
    /* column for falling edge */
 
1004
    
 
1005
    renderer = gtk_cell_renderer_toggle_new();
 
1006
 
 
1007
    g_signal_connect(renderer, "toggled",
 
1008
                     G_CALLBACK(falling_edge_toggled), ctk_framelock);
 
1009
 
 
1010
    column = gtk_tree_view_column_new_with_attributes("Falling",
 
1011
                                                      renderer,
 
1012
                                                      NULL);
 
1013
    gtk_tree_view_column_set_cell_data_func(column, renderer,
 
1014
                                            polarity_renderer_func,
 
1015
                                            GUINT_TO_POINTER(POLARITY_FALLING),
 
1016
                                            NULL);
 
1017
    
 
1018
    
 
1019
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
1020
    gtk_tree_view_column_set_resizable(column, TRUE);
 
1021
 
 
1022
    
 
1023
    /* column for sync skew */
 
1024
    
 
1025
    renderer = gtk_cell_renderer_text_new();
 
1026
 
 
1027
    g_signal_connect(renderer, "edited",
 
1028
                     G_CALLBACK(sync_skew_edited), ctk_framelock);
 
1029
    
 
1030
    column = gtk_tree_view_column_new_with_attributes("Sync Skew",
 
1031
                                                      renderer,
 
1032
                                                      "text",
 
1033
                                                      COLUMN_SYNC_SKEW,
 
1034
                                                      "editable",
 
1035
                                                      TRUE,
 
1036
                                                      NULL);
 
1037
    
 
1038
    gtk_tree_view_column_set_cell_data_func(column,
 
1039
                                            renderer,
 
1040
                                            sync_skew_renderer_func,
 
1041
                                            GINT_TO_POINTER(COLUMN_SYNC_SKEW),
 
1042
                                            NULL);
 
1043
    
 
1044
    gtk_tree_view_append_column(ctk_framelock->treeview, column);
 
1045
    gtk_tree_view_column_set_resizable(column, TRUE);
 
1046
 
 
1047
} /* add_columns_to_treeview() */
 
1048
 
 
1049
 
 
1050
 
 
1051
/*
 
1052
 * led_renderer_func() - set the cell's pixbuf to either a green or a
 
1053
 * red LED, based on the value in the model for this iter.
 
1054
 */
 
1055
 
 
1056
static void led_renderer_func(GtkTreeViewColumn *tree_column,
 
1057
                              GtkCellRenderer   *cell,
 
1058
                              GtkTreeModel      *model,
 
1059
                              GtkTreeIter       *iter,
 
1060
                              gpointer           data)
 
1061
{
 
1062
    static GdkPixbuf *led_green_pixbuf = NULL;
 
1063
    static GdkPixbuf *led_red_pixbuf = NULL;
 
1064
    static GdkPixbuf *led_grey_pixbuf = NULL;
 
1065
    gboolean value, master, framelock_enabled;
 
1066
    gpointer obj;
 
1067
    gint column, house = 0;
 
1068
 
 
1069
    /*
 
1070
     * we hooked a pointer to the ctk_framelock off the ViewColumn
 
1071
     * widget
 
1072
     */
 
1073
 
 
1074
    obj = g_object_get_data(G_OBJECT(tree_column), "ctk_framelock");
 
1075
    
 
1076
    column = GPOINTER_TO_INT(data);
 
1077
    
 
1078
    gtk_tree_model_get(model, iter, column, &value,
 
1079
                       COLUMN_MASTER, &master, -1);
 
1080
 
 
1081
    framelock_enabled = FALSE;  
 
1082
    if (obj) {
 
1083
        CtkFramelock *ctk_framelock = CTK_FRAMELOCK(obj);
 
1084
        if (ctk_framelock->framelock_enabled) framelock_enabled = TRUE;
 
1085
    }
 
1086
 
 
1087
    gtk_tree_model_get(model, iter, COLUMN_HOUSE, &house, -1);
 
1088
    
 
1089
    /* 
 
1090
     * make the master's Timing LED grey if framelock is enabled
 
1091
     * (otherwise, it will be red when framelock is enabled, which is
 
1092
     * confusing).
 
1093
     *
 
1094
     * If we are receiving house sync, then light the LED green.
 
1095
     */
 
1096
    
 
1097
    if ((column == COLUMN_TIMING) && master && framelock_enabled && !house) {
 
1098
        if (!led_grey_pixbuf)
 
1099
            led_grey_pixbuf = gdk_pixbuf_new_from_xpm_data(led_grey_xpm);
 
1100
        g_object_set(GTK_CELL_RENDERER(cell), "pixbuf", led_grey_pixbuf, NULL);
 
1101
    } else if (value || (house && framelock_enabled && master)) {
 
1102
        if (!led_green_pixbuf)
 
1103
            led_green_pixbuf = gdk_pixbuf_new_from_xpm_data(led_green_xpm);
 
1104
        g_object_set(GTK_CELL_RENDERER(cell),
 
1105
                     "pixbuf", led_green_pixbuf, NULL);
 
1106
    } else {
 
1107
        if (!led_red_pixbuf)
 
1108
            led_red_pixbuf = gdk_pixbuf_new_from_xpm_data(led_red_xpm);
 
1109
        g_object_set(GTK_CELL_RENDERER(cell), "pixbuf", led_red_pixbuf, NULL);
 
1110
    }
 
1111
} /* led_renderer_func() */
 
1112
 
 
1113
 
 
1114
 
 
1115
/*
 
1116
 * rj45_renderer_func() - set the cell's pixbuf either to the "input"
 
1117
 * rj45 pixbuf or the "output" rj45 pixbuf, based on the value in the
 
1118
 * model for this iter.
 
1119
 *
 
1120
 * XXX should there be an "unknown" state?
 
1121
 */
 
1122
 
 
1123
static void rj45_renderer_func(GtkTreeViewColumn *tree_column,
 
1124
                               GtkCellRenderer   *cell,
 
1125
                               GtkTreeModel      *model,
 
1126
                               GtkTreeIter       *iter,
 
1127
                               gpointer           data)
 
1128
{
 
1129
    static GdkPixbuf *rj45_input_pixbuf = NULL;
 
1130
    static GdkPixbuf *rj45_output_pixbuf = NULL;
 
1131
    gboolean value;
 
1132
    gint column;
 
1133
 
 
1134
    column = GPOINTER_TO_INT(data);
 
1135
 
 
1136
    gtk_tree_model_get (model, iter, column, &value, -1);
 
1137
 
 
1138
    if (value == NV_CTRL_FRAMELOCK_PORT0_STATUS_INPUT) {
 
1139
        if (!rj45_input_pixbuf)
 
1140
            rj45_input_pixbuf = gdk_pixbuf_new_from_xpm_data(rj45_input_xpm);
 
1141
        g_object_set(GTK_CELL_RENDERER(cell), "pixbuf",
 
1142
                      rj45_input_pixbuf, NULL);
 
1143
    } else {
 
1144
        if (!rj45_output_pixbuf)
 
1145
            rj45_output_pixbuf = gdk_pixbuf_new_from_xpm_data(rj45_output_xpm);
 
1146
        g_object_set(GTK_CELL_RENDERER(cell), "pixbuf",
 
1147
                     rj45_output_pixbuf, NULL);
 
1148
    }
 
1149
} /* rj45_renderer_func() */
 
1150
 
 
1151
 
 
1152
 
 
1153
/*
 
1154
 * rate_renderer_func() - set the cell's "text" attribute to a string
 
1155
 * representation of the rate in the model at this iter.
 
1156
 */
 
1157
 
 
1158
static void rate_renderer_func(GtkTreeViewColumn *tree_column,
 
1159
                               GtkCellRenderer   *cell,
 
1160
                               GtkTreeModel      *model,
 
1161
                               GtkTreeIter       *iter,
 
1162
                               gpointer           data)
 
1163
{
 
1164
    gint column = GPOINTER_TO_INT(data);
 
1165
    guint value;
 
1166
    gfloat fvalue;
 
1167
    gchar str[32];
 
1168
 
 
1169
    gtk_tree_model_get (model, iter, column, &value, -1);
 
1170
 
 
1171
    fvalue = (float) value / 1000.0;
 
1172
 
 
1173
    snprintf(str, 32, "%6.2f Hz", fvalue);
 
1174
    
 
1175
    g_object_set(GTK_CELL_RENDERER(cell), "text", str, NULL);
 
1176
 
 
1177
} /* rate_renderer_func() */
 
1178
 
 
1179
 
 
1180
 
 
1181
/*
 
1182
 * polarity_renderer_func() - set the attribute "active" to either
 
1183
 * true or false, based on if the bit specified in mask is present in
 
1184
 * the model for this iter.
 
1185
 */
 
1186
 
 
1187
static void polarity_renderer_func(GtkTreeViewColumn *tree_column,
 
1188
                                   GtkCellRenderer   *cell,
 
1189
                                   GtkTreeModel      *model,
 
1190
                                   GtkTreeIter       *iter,
 
1191
                                   gpointer           data)
 
1192
{
 
1193
    guint value, mask = GPOINTER_TO_UINT(data);
 
1194
    
 
1195
    gtk_tree_model_get(model, iter, COLUMN_POLARITY, &value, -1);
 
1196
    
 
1197
    if (value & mask) {
 
1198
        g_object_set(GTK_CELL_RENDERER(cell), "active", TRUE, NULL);
 
1199
    } else {
 
1200
        g_object_set(GTK_CELL_RENDERER(cell), "active", FALSE, NULL);
 
1201
    }
 
1202
} /* polarity_renderer_func() */
 
1203
 
 
1204
 
 
1205
 
 
1206
/*
 
1207
 * sync_skew_renderer_func() - set the cell's "text" attribute to a
 
1208
 * string representation of the sync delay in the model at this iter.
 
1209
 */
 
1210
 
 
1211
static void sync_skew_renderer_func(GtkTreeViewColumn *tree_column,
 
1212
                                    GtkCellRenderer   *cell,
 
1213
                                    GtkTreeModel      *model,
 
1214
                                    GtkTreeIter       *iter,
 
1215
                                    gpointer           data)
 
1216
{
 
1217
    gint column = GPOINTER_TO_INT(data);
 
1218
    guint value;
 
1219
    gchar str[32];
 
1220
    gfloat delay;
 
1221
    
 
1222
    gtk_tree_model_get (model, iter, column, &value, -1);
 
1223
 
 
1224
    delay = ((gfloat) value) * NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR;
 
1225
 
 
1226
    snprintf(str, 32, "%10.2f uS", delay);
 
1227
    
 
1228
    g_object_set (GTK_CELL_RENDERER(cell), "text", str, NULL);
 
1229
    
 
1230
} /* sync_skew_renderer_func() */
 
1231
 
 
1232
 
 
1233
 
 
1234
/*
 
1235
 * master_toggled() - called whenever a master is assigned.
 
1236
 */
 
1237
 
 
1238
static void master_toggled(GtkCellRendererToggle *cell, 
 
1239
                           gchar                 *path_str,
 
1240
                           gpointer               data)
 
1241
{
 
1242
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(data);
 
1243
    GtkTreeModel *model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
1244
    GtkTreeIter   iter, walking_iter;
 
1245
    GtkTreePath  *path = gtk_tree_path_new_from_string(path_str);
 
1246
    gboolean master, valid;
 
1247
    gchar *display_name;
 
1248
    
 
1249
    NvCtrlAttributeHandle *handle;
 
1250
 
 
1251
    /* do not change the master while framelock is enabled */
 
1252
 
 
1253
    if (ctk_framelock->framelock_enabled) {
 
1254
        ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
1255
                                     "Cannot change master while "
 
1256
                                     "FrameLock is enabled.");
 
1257
        return;
 
1258
    }
 
1259
 
 
1260
    /* get toggled iter */
 
1261
    
 
1262
    gtk_tree_model_get_iter(model, &iter, path);
 
1263
    gtk_tree_path_free(path);
 
1264
    
 
1265
    /* if we're already the master, do nothing */
 
1266
 
 
1267
    gtk_tree_model_get(model, &iter, COLUMN_MASTER, &master,
 
1268
                       COLUMN_DISPLAY_NAME, &display_name, -1);
 
1269
    
 
1270
    if (master) return;
 
1271
    
 
1272
    /* walk through the model, and turn off any other masters */
 
1273
 
 
1274
    valid = gtk_tree_model_get_iter_first(model, &walking_iter);
 
1275
    while (valid) {
 
1276
        gboolean walking_master;
 
1277
        gtk_tree_model_get(model, &walking_iter,
 
1278
                           COLUMN_MASTER, &walking_master, -1);
 
1279
        
 
1280
        if (walking_master) {
 
1281
            gtk_tree_model_get(model, &walking_iter,
 
1282
                               COLUMN_HANDLE, &handle, -1);
 
1283
            if (handle) {
 
1284
                gtk_list_store_set(GTK_LIST_STORE(model), &walking_iter,
 
1285
                                   COLUMN_MASTER, FALSE, -1);
 
1286
                NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_MASTER,
 
1287
                                   NV_CTRL_FRAMELOCK_MASTER_FALSE);
 
1288
            }
 
1289
        }
 
1290
        
 
1291
        valid = gtk_tree_model_iter_next(model, &walking_iter);
 
1292
    }
 
1293
    
 
1294
    /* set new value */
 
1295
    gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_MASTER,
 
1296
                       TRUE, -1);
 
1297
    
 
1298
    gtk_tree_model_get(model, &iter, COLUMN_HANDLE, &handle, -1);
 
1299
    NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_MASTER,
 
1300
                       NV_CTRL_FRAMELOCK_MASTER_TRUE);
 
1301
    
 
1302
    ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
1303
                                 "X Screen '%s' assigned master.",
 
1304
                                 display_name);
 
1305
 
 
1306
    update_house_sync_controls(ctk_framelock);
 
1307
    
 
1308
} /* master_toggled() */
 
1309
 
 
1310
static void polarity_toggled(GtkCellRendererToggle *cell,
 
1311
                             CtkFramelock          *ctk_framelock,
 
1312
                             gchar                 *path_string,
 
1313
                             guint                  mask)
 
1314
{
 
1315
    GtkTreeModel *model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
1316
    GtkTreePath *path;
 
1317
    GtkTreeIter iter;
 
1318
    gint polarity;
 
1319
    gboolean enabled;
 
1320
    NvCtrlAttributeHandle *handle;
 
1321
    gchar *polarity_str;
 
1322
 
 
1323
    path = gtk_tree_path_new_from_string(path_string);
 
1324
    gtk_tree_model_get_iter(model, &iter, path);
 
1325
    gtk_tree_path_free(path);
 
1326
 
 
1327
    gtk_tree_model_get(model, &iter, COLUMN_POLARITY, &polarity, -1);
 
1328
 
 
1329
    g_object_get(GTK_CELL_RENDERER(cell), "active", &enabled, NULL);
 
1330
 
 
1331
    enabled ^= 1;
 
1332
 
 
1333
    /* don't allow the user to turn off the rising edge */
 
1334
    
 
1335
    if (mask == NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE) enabled = TRUE;
 
1336
    
 
1337
    if (enabled) polarity |= mask;
 
1338
    else         polarity &= ~mask;
 
1339
    
 
1340
    gtk_list_store_set(ctk_framelock->list_store, &iter,
 
1341
                       COLUMN_POLARITY, polarity, -1);
 
1342
    
 
1343
    gtk_tree_model_get(model, &iter, COLUMN_HANDLE, &handle, -1);
 
1344
    
 
1345
    NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_POLARITY, polarity);
 
1346
 
 
1347
    switch (polarity) {
 
1348
    case NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE:
 
1349
        polarity_str = "rising";
 
1350
        break;
 
1351
    case NV_CTRL_FRAMELOCK_POLARITY_BOTH_EDGES:
 
1352
        polarity_str = "rising and falling";
 
1353
        break;
 
1354
    default:
 
1355
        return;
 
1356
    }
 
1357
 
 
1358
    ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
1359
                                 "Set edge polarity to %s.", polarity_str);
 
1360
}
 
1361
 
 
1362
static void rising_edge_toggled(GtkCellRendererToggle *cell,
 
1363
                                gchar                 *path_string,
 
1364
                                gpointer               user_data)
 
1365
{
 
1366
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(user_data);
 
1367
    
 
1368
    polarity_toggled(cell, ctk_framelock, path_string, POLARITY_RISING);
 
1369
}
 
1370
 
 
1371
static void falling_edge_toggled(GtkCellRendererToggle *cell,
 
1372
                                 gchar                 *path_string,
 
1373
                                 gpointer               user_data)
 
1374
{
 
1375
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(user_data);
 
1376
    
 
1377
    polarity_toggled(cell, ctk_framelock, path_string, POLARITY_FALLING);
 
1378
}
 
1379
 
 
1380
 
 
1381
static void sync_skew_edited(GtkCellRendererText *cell,
 
1382
                             const gchar         *path_string,
 
1383
                             const gchar         *new_text,
 
1384
                             gpointer             data)
 
1385
{
 
1386
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(data);
 
1387
    NvCtrlAttributeHandle *handle;
 
1388
    GtkTreeModel *model;
 
1389
    GtkTreePath *path;
 
1390
    GtkTreeIter iter;
 
1391
    gfloat delay;
 
1392
    gint value;
 
1393
 
 
1394
    delay = strtod(new_text, (char **)NULL);
 
1395
 
 
1396
    value = (gint) (delay / NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR);
 
1397
 
 
1398
    if (value < 0) value = 0;
 
1399
    if (value > NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX)
 
1400
        value = NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX;
 
1401
    
 
1402
    delay = ((gfloat) value) * NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR;
 
1403
    
 
1404
    model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
1405
    path = gtk_tree_path_new_from_string(path_string);
 
1406
    gtk_tree_model_get_iter(model, &iter, path);
 
1407
    gtk_tree_path_free(path);
 
1408
 
 
1409
    gtk_list_store_set(ctk_framelock->list_store, &iter,
 
1410
                       COLUMN_SYNC_SKEW, value, -1);
 
1411
    
 
1412
    gtk_tree_model_get(model, &iter, COLUMN_HANDLE, &handle, -1);
 
1413
 
 
1414
    NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_SYNC_DELAY, value);
 
1415
 
 
1416
    ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
1417
                                 "Sync delay set to %.2f uS", delay);
 
1418
}
 
1419
 
 
1420
 
 
1421
 
 
1422
/************************************************************************/
 
1423
/*
 
1424
 * functions relating to add_x_screen_dialog
 
1425
 */
 
1426
 
 
1427
 
 
1428
/*
 
1429
 * add_x_screen_response() - this function gets called in response to
 
1430
 * the "response" event from the "Add X Screen..." dialog box.
 
1431
 */
 
1432
 
 
1433
static void add_x_screen_response(GtkWidget *button, gint response,
 
1434
                                  gpointer user_data)
 
1435
{
 
1436
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(user_data);
 
1437
    const gchar *display_name;
 
1438
    
 
1439
    /* hide the dialog box */
 
1440
 
 
1441
    gtk_widget_hide_all(ctk_framelock->add_x_screen_dialog);
 
1442
    
 
1443
    /* set the focus back to the text entry */
 
1444
    
 
1445
    gtk_widget_grab_focus(ctk_framelock->add_x_screen_entry);
 
1446
    
 
1447
    /* if the response is not "OK" then we're done */
 
1448
    
 
1449
    if (response != GTK_RESPONSE_OK) return;
 
1450
    
 
1451
    /* get the display name specified by the user */
 
1452
 
 
1453
    display_name =
 
1454
        gtk_entry_get_text(GTK_ENTRY(ctk_framelock->add_x_screen_entry));
 
1455
    
 
1456
    add_x_screen(ctk_framelock, display_name, TRUE);
 
1457
    
 
1458
}
 
1459
 
 
1460
 
 
1461
static gpointer add_x_screen(CtkFramelock *ctk_framelock,
 
1462
                             const gchar *display_name, gboolean error_dialog)
 
1463
{
 
1464
    GtkTreeModel *model;
 
1465
    GtkTreeIter iter;
 
1466
    gpointer h;
 
1467
    Display *display;
 
1468
    gint screen, value;
 
1469
    gboolean valid;
 
1470
    const gchar *tmp;
 
1471
 
 
1472
    /* if no display name specified, print an error and return */
 
1473
 
 
1474
    if (!display_name || (display_name[0] == '\0')) {
 
1475
 
 
1476
        if (error_dialog) {
 
1477
            error_msg(ctk_framelock, "<span weight=\"bold\" size=\"larger\">"
 
1478
                      "Unable to add X screen to FrameLock group.</span>\n\n"
 
1479
                      "No X Screen specified.");
 
1480
        } else {
 
1481
            nv_error_msg("Unable to add X screen to FrameLock group; "
 
1482
                         "no X Screen specified.");
 
1483
        }
 
1484
        return NULL;
 
1485
    }
 
1486
 
 
1487
    /*
 
1488
     * try to prevent users from adding the same X screen more than
 
1489
     * once XXX this is not an absolute check: this does not catch
 
1490
     * "localhost:0.0" versus ":0.0", for example.
 
1491
     */
 
1492
    
 
1493
    model = GTK_TREE_MODEL(ctk_framelock->list_store);    
 
1494
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
1495
    while (valid) {
 
1496
        gtk_tree_model_get(model, &iter, COLUMN_DISPLAY_NAME, &tmp, -1);
 
1497
        if (nv_strcasecmp(display_name, tmp)) {
 
1498
            if (error_dialog) {
 
1499
                error_msg(ctk_framelock, "<span weight=\"bold\" "
 
1500
                          "size=\"larger\">Unable to add X screen "
 
1501
                          "to FrameLock Group</span>\n\n"
 
1502
                          "The X screen %s already belongs to the FrameLock "
 
1503
                          "Group.", display_name);
 
1504
            } else {
 
1505
                nv_error_msg("Unable to add X screen to FrameLock Group; "
 
1506
                             "the X screen %s already belongs to the "
 
1507
                             "FrameLock Group.", display_name);
 
1508
            }
 
1509
            return NULL;
 
1510
        }
 
1511
        valid = gtk_tree_model_iter_next(model, &iter);
 
1512
    }
 
1513
 
 
1514
    /* open an X Display connection to that X screen */
 
1515
    
 
1516
    display = XOpenDisplay(display_name);
 
1517
    if (!display) {
 
1518
        if (error_dialog) {
 
1519
            error_msg(ctk_framelock, "<span weight=\"bold\" "
 
1520
                      "size=\"larger\">Unable "
 
1521
                      "to add X screen to FrameLock group</span>\n\nUnable to "
 
1522
                      "connect to X Display '%s'.", display_name);
 
1523
        } else {
 
1524
            nv_error_msg("Unable to add X screen to FrameLock group; unable "
 
1525
                         "to connect to X Display '%s'.", display_name);
 
1526
        }
 
1527
        return NULL;
 
1528
    }
 
1529
    
 
1530
    /* create a new NV-CONTROL handle */
 
1531
    
 
1532
    screen = DefaultScreen(display);
 
1533
    
 
1534
    h = NvCtrlAttributeInit(display, screen,
 
1535
                            NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM);
 
1536
    
 
1537
    if (!h) {
 
1538
        if (error_dialog) {
 
1539
            error_msg(ctk_framelock, "<span weight=\"bold\" "
 
1540
                      "size=\"larger\">Unable "
 
1541
                      "to add X screen to FrameLock group</span>\n\nXXX need "
 
1542
                      "descriptive message.");
 
1543
        } else {
 
1544
            nv_error_msg("Unable to add X screen to FrameLock group.");
 
1545
        }
 
1546
        return NULL;
 
1547
    }
 
1548
 
 
1549
    /* does this NV-CONTROL handle support FrameLock? */
 
1550
    
 
1551
    NvCtrlGetAttribute(h, NV_CTRL_FRAMELOCK, &value);
 
1552
    if (value != NV_CTRL_FRAMELOCK_SUPPORTED) {
 
1553
        if (error_dialog) {
 
1554
            error_msg(ctk_framelock, "<span weight=\"bold\" "
 
1555
                      "size=\"larger\">Unable "
 
1556
                      "to add X screen to FrameLock group</span>\n\n"
 
1557
                      "This X Screen does not support FrameLock.");
 
1558
        } else {
 
1559
            nv_error_msg("Unable to add X screen to FrameLock group; "
 
1560
                         "this X Screen does not support FrameLock.");
 
1561
        }
 
1562
        NvCtrlAttributeClose(h);
 
1563
        return NULL;
 
1564
    }
 
1565
 
 
1566
    /* XXX need to check that the current modeline matches */
 
1567
 
 
1568
    /* add the screen to the list store */
 
1569
    
 
1570
    add_member_to_list_store(ctk_framelock, h);
 
1571
 
 
1572
    /* update the house sync controls */
 
1573
 
 
1574
    update_house_sync_controls(ctk_framelock);
 
1575
 
 
1576
    /* enable the "Test Link" and "Enable Framelock" buttons */
 
1577
 
 
1578
    gtk_widget_set_sensitive(ctk_framelock->sync_state_button, TRUE);
 
1579
 
 
1580
    ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
1581
                                 "Added X Screen '%s'", display_name);
 
1582
    return h;
 
1583
}
 
1584
 
 
1585
static GtkWidget *create_add_x_screen_dialog(CtkFramelock *ctk_framelock)
 
1586
{
 
1587
    GtkWidget *dialog;
 
1588
    GtkWidget *vbox;
 
1589
    GtkWidget *hbox;
 
1590
    GtkWidget *label, *descr;
 
1591
    GtkWidget *image;
 
1592
    GdkPixbuf *pixbuf;
 
1593
    GtkWidget *alignment;
 
1594
 
 
1595
    dialog = gtk_dialog_new_with_buttons("Add X Screen",
 
1596
                                         ctk_framelock->parent_window,
 
1597
                                         GTK_DIALOG_MODAL |
 
1598
                                         GTK_DIALOG_DESTROY_WITH_PARENT |
 
1599
                                         GTK_DIALOG_NO_SEPARATOR,
 
1600
                                         GTK_STOCK_CANCEL,
 
1601
                                         GTK_RESPONSE_CANCEL,
 
1602
                                         GTK_STOCK_OK,
 
1603
                                         GTK_RESPONSE_OK,
 
1604
                                         NULL);
 
1605
 
 
1606
    g_signal_connect (GTK_OBJECT(dialog), "response",
 
1607
                      G_CALLBACK(add_x_screen_response),
 
1608
                      GTK_OBJECT(ctk_framelock));
 
1609
 
 
1610
    gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
 
1611
    gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
 
1612
    
 
1613
    hbox = gtk_hbox_new(FALSE, 12);
 
1614
    gtk_container_set_border_width(GTK_CONTAINER(hbox), 6);
 
1615
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
 
1616
 
 
1617
    pixbuf = gtk_widget_render_icon(dialog, GTK_STOCK_DIALOG_QUESTION,
 
1618
                                    GTK_ICON_SIZE_DIALOG, NULL);
 
1619
    image = gtk_image_new_from_pixbuf(pixbuf);
 
1620
    g_object_unref(pixbuf);
 
1621
 
 
1622
    label = gtk_label_new("X Screen:");
 
1623
    descr = gtk_label_new("Please specify the X screen to be added to the "
 
1624
                          "FrameLock group.");
 
1625
    
 
1626
    ctk_framelock->add_x_screen_entry = gtk_entry_new();
 
1627
    
 
1628
    gtk_entry_set_text(GTK_ENTRY(ctk_framelock->add_x_screen_entry),
 
1629
                       NvCtrlGetDisplayName
 
1630
                       (ctk_framelock->attribute_handle));
 
1631
    
 
1632
    gtk_entry_set_width_chars
 
1633
        (GTK_ENTRY(ctk_framelock->add_x_screen_entry), 16);
 
1634
 
 
1635
    alignment = gtk_alignment_new(0.0, 0.0, 0, 0);
 
1636
    gtk_container_add(GTK_CONTAINER(alignment), image);
 
1637
    gtk_box_pack_start(GTK_BOX(hbox), alignment, FALSE, FALSE, 2);
 
1638
 
 
1639
    vbox = gtk_vbox_new(FALSE, 12);
 
1640
    gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
 
1641
 
 
1642
    alignment = gtk_alignment_new(0.0, 0.0, 0, 0);
 
1643
    gtk_container_add(GTK_CONTAINER(alignment), descr);
 
1644
    gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
 
1645
 
 
1646
    hbox = gtk_hbox_new(FALSE, 12);
 
1647
    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
 
1648
 
 
1649
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
 
1650
    gtk_box_pack_start(GTK_BOX(hbox), ctk_framelock->add_x_screen_entry,
 
1651
                       TRUE, TRUE, 0);
 
1652
    
 
1653
    return dialog;
 
1654
 
 
1655
} /* create_add_x_screen_dialog() */
 
1656
 
 
1657
 
 
1658
/************************************************************************/
 
1659
/*
 
1660
 * functions relating to remove_x_screen_dialog
 
1661
 */
 
1662
 
 
1663
 
 
1664
static void tree_selection_changed(GtkTreeSelection *selection,
 
1665
                                   gpointer user_data)
 
1666
{
 
1667
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(user_data);
 
1668
 
 
1669
    if (gtk_tree_selection_get_selected(selection, NULL, NULL)) {
 
1670
        gtk_widget_set_sensitive(ctk_framelock->remove_x_screen_button, TRUE);
 
1671
    } else {
 
1672
        gtk_widget_set_sensitive(ctk_framelock->remove_x_screen_button,FALSE);
 
1673
    }
 
1674
}
 
1675
 
 
1676
 
 
1677
 
 
1678
static void remove_x_screen(GtkWidget *button, gint response,
 
1679
                            gpointer user_data)
 
1680
{
 
1681
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(user_data);
 
1682
    gboolean valid;
 
1683
    GtkTreeModel *model;
 
1684
    GtkTreeIter iter;
 
1685
    gchar *display_name;
 
1686
    
 
1687
    gtk_widget_hide_all(ctk_framelock->remove_x_screen_dialog);
 
1688
 
 
1689
    if (response != GTK_RESPONSE_OK) return;
 
1690
 
 
1691
    gtk_tree_model_get(GTK_TREE_MODEL(ctk_framelock->list_store),
 
1692
                       &ctk_framelock->remove_x_screen_iter,
 
1693
                       COLUMN_DISPLAY_NAME, &display_name, -1);
 
1694
 
 
1695
    ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
1696
                                 "Removed X Screen '%s'", display_name);
 
1697
    
 
1698
    /* XXX disable anything that we need to in the X server */
 
1699
    
 
1700
    gtk_list_store_remove(GTK_LIST_STORE(ctk_framelock->list_store),
 
1701
                          &ctk_framelock->remove_x_screen_iter);
 
1702
    
 
1703
    /*
 
1704
     * if there are no entries left, then disable the "Test Link" and
 
1705
     * "Enable FrameLock" buttons.
 
1706
     */
 
1707
 
 
1708
    model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
1709
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
1710
    if (!valid) {
 
1711
        gtk_widget_set_sensitive(ctk_framelock->sync_state_button, FALSE);
 
1712
    }
 
1713
}
 
1714
 
 
1715
static void show_remove_x_screen_dialog(GtkWidget *button,
 
1716
                                        CtkFramelock *ctk_framelock)
 
1717
{
 
1718
    GtkTreeIter iter;
 
1719
    GtkTreeSelection *selection;
 
1720
    gchar *str, *display_name;
 
1721
 
 
1722
    selection = gtk_tree_view_get_selection(ctk_framelock->treeview);
 
1723
    
 
1724
    if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
 
1725
    
 
1726
    gtk_tree_model_get(GTK_TREE_MODEL(ctk_framelock->list_store), &iter,
 
1727
                       COLUMN_DISPLAY_NAME, &display_name, -1);
 
1728
    
 
1729
    str = g_strconcat("Remove X Screen '", display_name, "'?", NULL);
 
1730
    gtk_label_set_text(GTK_LABEL(ctk_framelock->remove_x_screen_label), str);
 
1731
    g_free(str);
 
1732
    
 
1733
    ctk_framelock->remove_x_screen_iter = iter;
 
1734
    
 
1735
    gtk_widget_show_all(ctk_framelock->remove_x_screen_dialog);
 
1736
}
 
1737
 
 
1738
 
 
1739
 
 
1740
static GtkWidget *create_remove_x_screen_dialog(
 
1741
    CtkFramelock *ctk_framelock
 
1742
)
 
1743
{
 
1744
    GtkWidget *dialog;
 
1745
    GtkWidget *hbox;
 
1746
    GtkWidget *image;
 
1747
    GdkPixbuf *pixbuf;
 
1748
    GtkWidget *alignment;
 
1749
    
 
1750
 
 
1751
    dialog = gtk_dialog_new_with_buttons("Remove X Screen",
 
1752
                                         ctk_framelock->parent_window,
 
1753
                                         GTK_DIALOG_MODAL |
 
1754
                                         GTK_DIALOG_DESTROY_WITH_PARENT |
 
1755
                                         GTK_DIALOG_NO_SEPARATOR,
 
1756
                                         GTK_STOCK_CANCEL,
 
1757
                                         GTK_RESPONSE_CANCEL,
 
1758
                                         GTK_STOCK_OK,
 
1759
                                         GTK_RESPONSE_OK,
 
1760
                                         NULL);
 
1761
 
 
1762
    g_signal_connect(GTK_OBJECT(dialog), "response",
 
1763
                     G_CALLBACK(remove_x_screen),
 
1764
                     GTK_OBJECT(ctk_framelock));
 
1765
 
 
1766
    gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
 
1767
    gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
 
1768
    
 
1769
    hbox = gtk_hbox_new(FALSE, 12);
 
1770
    gtk_container_set_border_width(GTK_CONTAINER(hbox), 6);
 
1771
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
 
1772
    
 
1773
    pixbuf = gtk_widget_render_icon(dialog, GTK_STOCK_DIALOG_QUESTION,
 
1774
                                    GTK_ICON_SIZE_DIALOG, NULL);
 
1775
    image = gtk_image_new_from_pixbuf(pixbuf);
 
1776
    g_object_unref(pixbuf);
 
1777
 
 
1778
    ctk_framelock->remove_x_screen_label = gtk_label_new(NULL);
 
1779
    
 
1780
    alignment = gtk_alignment_new(0.0, 0.0, 0, 0);
 
1781
    gtk_container_add(GTK_CONTAINER(alignment), image);
 
1782
    gtk_box_pack_start(GTK_BOX(hbox), alignment, FALSE, FALSE, 2);
 
1783
 
 
1784
    alignment = gtk_alignment_new(0.0, 0.0, 0, 0);
 
1785
    gtk_container_add(GTK_CONTAINER(alignment),
 
1786
                      ctk_framelock->remove_x_screen_label);
 
1787
    gtk_box_pack_start(GTK_BOX(hbox), alignment, FALSE, FALSE, 0);
 
1788
 
 
1789
    return dialog;
 
1790
 
 
1791
} /* create_remove_x_screen_dialog() */
 
1792
 
 
1793
 
 
1794
 
 
1795
/************************************************************************/
 
1796
/*
 
1797
 * function for updating the status
 
1798
 */
 
1799
 
 
1800
 
 
1801
/*
 
1802
 * update_status() - query the following from each member of the sync
 
1803
 * group:
 
1804
 *
 
1805
 *  NV_CTRL_FRAMELOCK_STEREO_SYNC
 
1806
 *  NV_CTRL_FRAMELOCK_TIMING
 
1807
 *  NV_CTRL_FRAMELOCK_SYNC_READY
 
1808
 *  NV_CTRL_FRAMELOCK_SYNC_RATE
 
1809
 *  NV_CTRL_FRAMELOCK_HOUSE_STATUS
 
1810
 *  NV_CTRL_FRAMELOCK_PORT0_STATUS
 
1811
 *  NV_CTRL_FRAMELOCK_PORT1_STATUS
 
1812
 *
 
1813
 * XXX maybe rather than have a button to do this, the app could be
 
1814
 * set to poll (and auto update the gui) periodically?
 
1815
 */
 
1816
 
 
1817
static gboolean update_status(gpointer user_data)
 
1818
{
 
1819
    gboolean valid;
 
1820
    GtkTreeIter iter;
 
1821
    gint stereo_sync, timing, sync_ready, sync_rate, house, port0, port1;
 
1822
    GtkTreeModel *model;
 
1823
    NvCtrlAttributeHandle *handle;
 
1824
    CtkFramelock *ctk_framelock;
 
1825
 
 
1826
    ctk_framelock = CTK_FRAMELOCK(user_data);
 
1827
 
 
1828
    model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
1829
    
 
1830
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
1831
    while (valid) {
 
1832
        gtk_tree_model_get(model, &iter, COLUMN_HANDLE, &handle, -1);
 
1833
        if (!handle) break;
 
1834
        
 
1835
        NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_STEREO_SYNC,  &stereo_sync);
 
1836
        NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_TIMING,       &timing);
 
1837
        NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_SYNC_READY,   &sync_ready);
 
1838
        NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_SYNC_RATE,    &sync_rate);
 
1839
        NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_HOUSE_STATUS, &house);
 
1840
        NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_PORT0_STATUS, &port0);
 
1841
        NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_PORT1_STATUS, &port1);
 
1842
        
 
1843
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
1844
                           COLUMN_STEREO_SYNC, stereo_sync, -1);
 
1845
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
1846
                           COLUMN_TIMING, timing, -1);
 
1847
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
1848
                           COLUMN_SYNC_READY, sync_ready, -1);
 
1849
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
1850
                           COLUMN_SYNC_RATE, sync_rate, -1);
 
1851
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
1852
                           COLUMN_HOUSE, house, -1);
 
1853
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
1854
                           COLUMN_RJ45_PORT0, port0, -1);
 
1855
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
1856
                           COLUMN_RJ45_PORT1, port1, -1);
 
1857
 
 
1858
        valid = gtk_tree_model_iter_next(model, &iter);
 
1859
    }
 
1860
 
 
1861
    return TRUE;
 
1862
    
 
1863
} /* update_status() */
 
1864
 
 
1865
 
 
1866
 
 
1867
 
 
1868
 
 
1869
/*
 
1870
 * test_link() - tell the master to enable the test signal, update
 
1871
 * everyone's status, and then disable the test signal.
 
1872
 */
 
1873
 
 
1874
static void test_link(GtkWidget *button, CtkFramelock *ctk_framelock)
 
1875
{
 
1876
    gboolean valid, master, enabled;
 
1877
    GtkTreeIter iter;
 
1878
    NvCtrlAttributeHandle *handle;
 
1879
    GtkTreeModel *model;
 
1880
    
 
1881
    enabled = gtk_toggle_button_get_active
 
1882
        (GTK_TOGGLE_BUTTON(ctk_framelock->test_link_button));
 
1883
    
 
1884
    if (!enabled) return;
 
1885
    
 
1886
    model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
1887
 
 
1888
    /* find the master handle */
 
1889
 
 
1890
    handle = NULL;
 
1891
 
 
1892
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
1893
    while (valid) {
 
1894
        gtk_tree_model_get(model, &iter, COLUMN_MASTER, &master, -1);
 
1895
        if (master) {
 
1896
            gtk_tree_model_get(model, &iter, COLUMN_HANDLE,
 
1897
                               &handle, -1);
 
1898
            break;
 
1899
        }
 
1900
        valid = gtk_tree_model_iter_next(model, &iter);
 
1901
    }
 
1902
 
 
1903
    if (!handle) return;
 
1904
 
 
1905
    /* enable the test signal */
 
1906
    
 
1907
    gdk_window_set_cursor
 
1908
        ((GTK_WIDGET(ctk_framelock->parent_window))->window,
 
1909
         ctk_framelock->wait_cursor);
 
1910
        
 
1911
    gtk_grab_add(button);
 
1912
    
 
1913
    NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_TEST_SIGNAL,
 
1914
                       NV_CTRL_FRAMELOCK_TEST_SIGNAL_ENABLE);
 
1915
    
 
1916
    ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
1917
                                 "Test Link started.");
 
1918
 
 
1919
    /* register the "done" function */
 
1920
 
 
1921
    g_timeout_add(DEFAULT_TEST_LINK_TIME_INTERVAL,
 
1922
                  test_link_done, (gpointer) ctk_framelock);
 
1923
    
 
1924
} /* test_link() */
 
1925
 
 
1926
 
 
1927
static gint test_link_done(gpointer data)
 
1928
{
 
1929
    CtkFramelock *ctk_framelock = (CtkFramelock *) data;
 
1930
    gboolean valid, master;
 
1931
    GtkTreeIter iter;
 
1932
    NvCtrlAttributeHandle *handle;
 
1933
    GtkTreeModel *model;
 
1934
 
 
1935
    model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
1936
 
 
1937
    /* find the master handle */
 
1938
 
 
1939
    handle = NULL;
 
1940
 
 
1941
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
1942
    while (valid) {
 
1943
        gtk_tree_model_get(model, &iter, COLUMN_MASTER, &master, -1);
 
1944
        if (master) {
 
1945
            gtk_tree_model_get(model, &iter, COLUMN_HANDLE,
 
1946
                               &handle, -1);
 
1947
            break;
 
1948
        }
 
1949
        valid = gtk_tree_model_iter_next(model, &iter);
 
1950
    }
 
1951
 
 
1952
    if (!handle) return FALSE;
 
1953
 
 
1954
    /* disable the test signal */
 
1955
        
 
1956
    NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_TEST_SIGNAL,
 
1957
                       NV_CTRL_FRAMELOCK_TEST_SIGNAL_DISABLE);
 
1958
    
 
1959
    gtk_grab_remove(ctk_framelock->test_link_button);
 
1960
        
 
1961
    gdk_window_set_cursor((GTK_WIDGET(ctk_framelock->parent_window))->window,
 
1962
                          NULL);
 
1963
 
 
1964
    ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
1965
                                 "Test Link complete.");
 
1966
 
 
1967
    /* un-press the testlink button */
 
1968
    
 
1969
    g_signal_handlers_block_by_func
 
1970
        (G_OBJECT(ctk_framelock->test_link_button),
 
1971
         G_CALLBACK(test_link),
 
1972
         (gpointer) ctk_framelock);
 
1973
    
 
1974
    gtk_toggle_button_set_active
 
1975
        (GTK_TOGGLE_BUTTON(ctk_framelock->test_link_button), FALSE);
 
1976
 
 
1977
    g_signal_handlers_unblock_by_func
 
1978
        (G_OBJECT(ctk_framelock->test_link_button),
 
1979
         G_CALLBACK(test_link),
 
1980
         (gpointer) ctk_framelock);
 
1981
    
 
1982
    return FALSE;
 
1983
}
 
1984
 
 
1985
 
 
1986
static GtkWidget *create_sync_state_button(CtkFramelock *ctk_framelock)
 
1987
{
 
1988
    GtkWidget *label;
 
1989
    GtkWidget *hbox, *hbox2;
 
1990
    GdkPixbuf *pixbuf;
 
1991
    GtkWidget *image = NULL;
 
1992
    GtkWidget *button;
 
1993
 
 
1994
    button = gtk_toggle_button_new();
 
1995
 
 
1996
    /* create the enable syncing icon */
 
1997
 
 
1998
    pixbuf = gtk_widget_render_icon(button,
 
1999
                                    GTK_STOCK_EXECUTE,
 
2000
                                    GTK_ICON_SIZE_BUTTON,
 
2001
                                    "enable framelock");
 
2002
    if (pixbuf) image = gtk_image_new_from_pixbuf(pixbuf);
 
2003
    label = gtk_label_new("Enable FrameLock");
 
2004
 
 
2005
    hbox = gtk_hbox_new(FALSE, 2);
 
2006
 
 
2007
    if (image) gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 2);
 
2008
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
 
2009
 
 
2010
    hbox2 = gtk_hbox_new(FALSE, 0);
 
2011
    gtk_box_pack_start(GTK_BOX(hbox2), hbox, FALSE, FALSE, 15);
 
2012
 
 
2013
    gtk_widget_show_all(hbox2);
 
2014
 
 
2015
    /*
 
2016
     * XXX increment the reference count, so that when we do
 
2017
     * gtk_container_remove() later, it doesn't get destroyed
 
2018
     */
 
2019
 
 
2020
    gtk_object_ref(GTK_OBJECT(hbox2));
 
2021
 
 
2022
    ctk_framelock->enable_syncing_label = hbox2;
 
2023
    
 
2024
 
 
2025
    /* create the disable syncing icon */
 
2026
    
 
2027
    pixbuf = gtk_widget_render_icon(button,
 
2028
                                    GTK_STOCK_STOP,
 
2029
                                    GTK_ICON_SIZE_BUTTON,
 
2030
                                    "disable framelock");
 
2031
    if (pixbuf) image = gtk_image_new_from_pixbuf(pixbuf);
 
2032
    label = gtk_label_new("Disable FrameLock");
 
2033
    
 
2034
    hbox = gtk_hbox_new(FALSE, 2);
 
2035
    
 
2036
    if (image) gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 2);
 
2037
    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
 
2038
    
 
2039
    hbox2 = gtk_hbox_new(FALSE, 0);
 
2040
    gtk_box_pack_start(GTK_BOX(hbox2), hbox, FALSE, FALSE, 15);
 
2041
 
 
2042
    gtk_widget_show_all(hbox2);
 
2043
    
 
2044
    /*
 
2045
     * XXX increment the reference count, so that when we do
 
2046
     * gtk_container_remove() later, it doesn't get destroyed
 
2047
     */
 
2048
 
 
2049
    gtk_object_ref(GTK_OBJECT(hbox2));
 
2050
    
 
2051
    ctk_framelock->disable_syncing_label = hbox2;
 
2052
    
 
2053
    /* start with syncing disabled */
 
2054
    
 
2055
    gtk_container_add(GTK_CONTAINER(button),
 
2056
                      ctk_framelock->enable_syncing_label);
 
2057
    
 
2058
    return (button);
 
2059
}
 
2060
 
 
2061
 
 
2062
static void toggle_sync_state_button(GtkWidget *button,
 
2063
                                     CtkFramelock *ctk_framelock)
 
2064
{
 
2065
    gboolean valid;
 
2066
    GtkTreeIter iter;
 
2067
    NvCtrlAttributeHandle *handle;
 
2068
    guint display_mask, val;
 
2069
    gboolean enabled;
 
2070
    GtkTreeSelection *selection;
 
2071
    
 
2072
    GtkTreeModel *model;
 
2073
    
 
2074
    enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
 
2075
 
 
2076
    if (enabled) val = NV_CTRL_FRAMELOCK_SYNC_ENABLE;
 
2077
    else         val = NV_CTRL_FRAMELOCK_SYNC_DISABLE;
 
2078
    
 
2079
    /*
 
2080
     * set the NV_CTRL_FRAMELOCK_SYNC status on each member of the
 
2081
     * FrameLock group
 
2082
     */
 
2083
    
 
2084
    handle = NULL;
 
2085
    model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
2086
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
2087
    while (valid) {
 
2088
        gtk_tree_model_get(model, &iter, COLUMN_HANDLE, &handle,
 
2089
                           COLUMN_DISPLAY_MASK, &display_mask, -1);
 
2090
        if (!handle) return; /* XXX */
 
2091
        
 
2092
        NvCtrlSetDisplayAttribute(handle, display_mask,
 
2093
                                  NV_CTRL_FRAMELOCK_SYNC, val);
 
2094
        valid = gtk_tree_model_iter_next(model, &iter);
 
2095
    }
 
2096
    
 
2097
    /* 
 
2098
     * toggle the TEST_SIGNAL, to guarantee accuracy of the universal
 
2099
     * frame count (as returned by the glXQueryFrameCountNV() function
 
2100
     * in the GLX_NV_swap_group extension)
 
2101
     */
 
2102
 
 
2103
    if (enabled && find_master(ctk_framelock, NULL, &handle)) {
 
2104
        NvCtrlSetAttribute(handle,
 
2105
                           NV_CTRL_FRAMELOCK_TEST_SIGNAL,
 
2106
                           NV_CTRL_FRAMELOCK_TEST_SIGNAL_ENABLE);
 
2107
        NvCtrlSetAttribute(handle,
 
2108
                           NV_CTRL_FRAMELOCK_TEST_SIGNAL,
 
2109
                           NV_CTRL_FRAMELOCK_TEST_SIGNAL_DISABLE);
 
2110
    }
 
2111
 
 
2112
    /* alter the button */
 
2113
 
 
2114
    if (enabled) {
 
2115
        if (!ctk_framelock->framelock_enabled) {
 
2116
            
 
2117
            gtk_container_remove
 
2118
                (GTK_CONTAINER(ctk_framelock->sync_state_button),
 
2119
                 ctk_framelock->enable_syncing_label);
 
2120
            gtk_container_add(GTK_CONTAINER(ctk_framelock->sync_state_button),
 
2121
                              ctk_framelock->disable_syncing_label);
 
2122
        }
 
2123
        
 
2124
        /*
 
2125
         * disable the "Add Screen" and "Remove Screen" buttons;
 
2126
         * enable the "Test Link" button
 
2127
         */
 
2128
 
 
2129
        gtk_widget_set_sensitive(ctk_framelock->add_x_screen_button, FALSE);
 
2130
        gtk_widget_set_sensitive(ctk_framelock->remove_x_screen_button, FALSE);
 
2131
        gtk_widget_set_sensitive(ctk_framelock->test_link_button, TRUE);
 
2132
        
 
2133
        /* disable the house sync controls */
 
2134
 
 
2135
        gtk_widget_set_sensitive(ctk_framelock->sync_interval_frame, FALSE);
 
2136
        gtk_widget_set_sensitive(ctk_framelock->house_format_frame, FALSE);
 
2137
 
 
2138
    } else {
 
2139
        if (ctk_framelock->framelock_enabled) {
 
2140
            gtk_container_remove
 
2141
                (GTK_CONTAINER(ctk_framelock->sync_state_button),
 
2142
                 ctk_framelock->disable_syncing_label);
 
2143
            gtk_container_add(GTK_CONTAINER(ctk_framelock->sync_state_button),
 
2144
                              ctk_framelock->enable_syncing_label);
 
2145
        }
 
2146
 
 
2147
        /* enable the "Add Screen" button; disable the "Test Link" button */
 
2148
 
 
2149
        gtk_widget_set_sensitive(ctk_framelock->add_x_screen_button, TRUE);
 
2150
        gtk_widget_set_sensitive(ctk_framelock->test_link_button, FALSE);
 
2151
 
 
2152
        /* check if the "Remove Screen" button should be enabled */
 
2153
 
 
2154
        selection = gtk_tree_view_get_selection(ctk_framelock->treeview);
 
2155
        tree_selection_changed(selection, GTK_OBJECT(ctk_framelock));
 
2156
 
 
2157
        /* enable the house sync controls */
 
2158
 
 
2159
        gtk_widget_set_sensitive(ctk_framelock->sync_interval_frame, TRUE);
 
2160
        gtk_widget_set_sensitive(ctk_framelock->house_format_frame, TRUE);
 
2161
    }
 
2162
 
 
2163
    ctk_framelock->framelock_enabled = enabled;
 
2164
 
 
2165
    ctk_config_statusbar_message(ctk_framelock->ctk_config,
 
2166
                                 "FrameLock %s.",
 
2167
                                 enabled ? "enabled" : "disabled");
 
2168
 
 
2169
} /* toggle_sync_state_button() */
 
2170
 
 
2171
 
 
2172
/************************************************************************/
 
2173
/*
 
2174
 * functions relating to the error_msg_dialog
 
2175
 */
 
2176
 
 
2177
static GtkWidget *create_error_msg_dialog(CtkFramelock *ctk_framelock)
 
2178
{
 
2179
    GtkWidget *dialog;
 
2180
    GtkWidget *hbox;
 
2181
    GtkWidget *image;
 
2182
    GtkWidget *alignment;
 
2183
    GdkPixbuf *pixbuf;
 
2184
    
 
2185
    
 
2186
    dialog = gtk_dialog_new_with_buttons("Error",
 
2187
                                         ctk_framelock->parent_window,
 
2188
                                         GTK_DIALOG_MODAL |
 
2189
                                         GTK_DIALOG_DESTROY_WITH_PARENT |
 
2190
                                         GTK_DIALOG_NO_SEPARATOR,
 
2191
                                         GTK_STOCK_OK,
 
2192
                                         GTK_RESPONSE_OK,
 
2193
                                         NULL);
 
2194
 
 
2195
    g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
 
2196
                             G_CALLBACK(gtk_widget_hide_all),
 
2197
                             GTK_OBJECT(dialog));
 
2198
 
 
2199
    gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
 
2200
    gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
 
2201
 
 
2202
    hbox = gtk_hbox_new(FALSE, 12);
 
2203
    gtk_container_set_border_width(GTK_CONTAINER(hbox), 6);
 
2204
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
 
2205
    
 
2206
    pixbuf = gtk_widget_render_icon(dialog, GTK_STOCK_DIALOG_ERROR,
 
2207
                                    GTK_ICON_SIZE_DIALOG, NULL);
 
2208
    image = gtk_image_new_from_pixbuf(pixbuf);
 
2209
    g_object_unref(pixbuf);
 
2210
    
 
2211
    ctk_framelock->error_msg_label = gtk_label_new(NULL);
 
2212
 
 
2213
    alignment = gtk_alignment_new(0.0, 0.0, 0, 0);
 
2214
    gtk_container_add(GTK_CONTAINER(alignment), image);
 
2215
    gtk_box_pack_start(GTK_BOX(hbox), alignment, FALSE, FALSE, 2);
 
2216
 
 
2217
    alignment = gtk_alignment_new(0.0, 0.0, 0, 0);
 
2218
    gtk_container_add(GTK_CONTAINER(alignment),
 
2219
                      ctk_framelock->error_msg_label);
 
2220
    gtk_box_pack_start(GTK_BOX(hbox), alignment, FALSE, FALSE, 0);
 
2221
 
 
2222
    return dialog;
 
2223
}
 
2224
 
 
2225
static void error_msg(CtkFramelock *ctk_framelock, const gchar *fmt, ...)
 
2226
{
 
2227
    va_list ap;
 
2228
    gchar *msg;
 
2229
 
 
2230
    va_start(ap, fmt);
 
2231
    msg = nv_build_vararg_string(fmt, ap);
 
2232
    va_end(ap);
 
2233
    
 
2234
    gtk_label_set_line_wrap(GTK_LABEL(ctk_framelock->error_msg_label), TRUE);
 
2235
    gtk_label_set_use_markup(GTK_LABEL(ctk_framelock->error_msg_label), TRUE);
 
2236
    gtk_label_set_markup(GTK_LABEL(ctk_framelock->error_msg_label), msg);
 
2237
    gtk_widget_show_all(ctk_framelock->error_msg_dialog);
 
2238
    
 
2239
    free(msg);
 
2240
}
 
2241
 
 
2242
 
 
2243
 
 
2244
/************************************************************************/
 
2245
/*
 
2246
 * Functions for manipulating the List Store
 
2247
 */
 
2248
 
 
2249
 
 
2250
static void create_list_store(CtkFramelock *ctk_framelock)
 
2251
{
 
2252
    GtkTreeSelection *selection;
 
2253
 
 
2254
    ctk_framelock->list_store =
 
2255
        gtk_list_store_new(NUM_COLUMNS,
 
2256
                           G_TYPE_POINTER,  /* HANDLE */
 
2257
                           G_TYPE_UINT,     /* DISPLAY_MASK */
 
2258
                           G_TYPE_STRING,   /* DISPLAY_NAME */
 
2259
                           G_TYPE_BOOLEAN,  /* MASTER  */
 
2260
                           G_TYPE_BOOLEAN,  /* STEREO_SYNC */
 
2261
                           G_TYPE_BOOLEAN,  /* TIMING */
 
2262
                           G_TYPE_BOOLEAN,  /* SYNC_READY */
 
2263
                           G_TYPE_UINT,     /* SYNC_RATE */
 
2264
                           G_TYPE_BOOLEAN,  /* HOUSE */
 
2265
                           G_TYPE_BOOLEAN,  /* RJ45_PORT0 */
 
2266
                           G_TYPE_BOOLEAN,  /* RJ45_PORT1 */
 
2267
                           G_TYPE_UINT,     /* POLARITY */
 
2268
                           G_TYPE_UINT,     /* SYNC_SKEW */
 
2269
                           G_TYPE_UINT,     /* SYNC_INTERVAL */
 
2270
                           G_TYPE_UINT);    /* HOUSE_FORMAT */
 
2271
 
 
2272
    /* create the treeview */
 
2273
 
 
2274
    ctk_framelock->treeview =
 
2275
        GTK_TREE_VIEW(gtk_tree_view_new_with_model
 
2276
                      (GTK_TREE_MODEL(ctk_framelock->list_store)));
 
2277
    
 
2278
    gtk_tree_view_set_rules_hint(ctk_framelock->treeview, TRUE);
 
2279
    
 
2280
    g_object_unref(ctk_framelock->list_store);
 
2281
 
 
2282
    /* watch for selection changes to the treeview */
 
2283
    
 
2284
    selection = gtk_tree_view_get_selection(ctk_framelock->treeview);
 
2285
    
 
2286
    g_signal_connect(selection, "changed",
 
2287
                     G_CALLBACK(tree_selection_changed),
 
2288
                     GTK_OBJECT(ctk_framelock));
 
2289
 
 
2290
    /* add columns to the tree view */
 
2291
    
 
2292
    add_columns_to_treeview(ctk_framelock);
 
2293
 
 
2294
} /* create_list_store() */
 
2295
 
 
2296
 
 
2297
 
 
2298
/*
 
2299
 * add_member_to_list_store()
 
2300
 */
 
2301
 
 
2302
static void add_member_to_list_store(CtkFramelock *ctk_framelock,
 
2303
                                     const gpointer handle)
 
2304
{
 
2305
    GtkTreeIter iter;
 
2306
    GtkTreeModel *model;
 
2307
    gint master, stereo_sync, timing, sync_ready, sync_rate;
 
2308
    gint house, port0, port1, polarity, sync_skew, display_mask;
 
2309
    gint sync_interval, house_format;
 
2310
    gboolean valid, have_master;
 
2311
    gchar *display_name;
 
2312
 
 
2313
    /*
 
2314
     * If we don't have a master already, make this the master; if we
 
2315
     * do have a master already, make sure this isn't the master.
 
2316
     */
 
2317
 
 
2318
    have_master = FALSE;
 
2319
    model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
2320
 
 
2321
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
2322
    while (valid) {
 
2323
        gtk_tree_model_get(model, &iter, COLUMN_MASTER, &have_master, -1);
 
2324
        if (have_master) break;
 
2325
        valid = gtk_tree_model_iter_next(model, &iter);
 
2326
    }
 
2327
 
 
2328
    master = !have_master;
 
2329
 
 
2330
    NvCtrlSetAttribute(handle, NV_CTRL_FRAMELOCK_MASTER, master);
 
2331
    
 
2332
    /* query all the other fields */
 
2333
    
 
2334
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_STEREO_SYNC,  &stereo_sync);
 
2335
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_TIMING,       &timing);
 
2336
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_SYNC_READY,   &sync_ready);
 
2337
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_SYNC_RATE,    &sync_rate);
 
2338
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_HOUSE_STATUS, &house);
 
2339
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_PORT0_STATUS, &port0);
 
2340
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_PORT1_STATUS, &port1);
 
2341
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_POLARITY,     &polarity);
 
2342
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_SYNC_DELAY,   &sync_skew);
 
2343
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_SYNC_INTERVAL,&sync_interval);
 
2344
    NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_VIDEO_MODE,   &house_format);
 
2345
    
 
2346
    NvCtrlGetAttribute(handle, NV_CTRL_ENABLED_DISPLAYS, &display_mask);
 
2347
 
 
2348
    gtk_list_store_append(ctk_framelock->list_store, &iter);
 
2349
    
 
2350
    display_name = NvCtrlGetDisplayName(handle);
 
2351
 
 
2352
    gtk_list_store_set(ctk_framelock->list_store, &iter,
 
2353
                       COLUMN_HANDLE,            handle,
 
2354
                       COLUMN_DISPLAY_MASK,      display_mask,
 
2355
                       COLUMN_DISPLAY_NAME,      display_name,
 
2356
                       COLUMN_MASTER,            master,
 
2357
                       COLUMN_STEREO_SYNC,       stereo_sync,
 
2358
                       COLUMN_TIMING,            timing,
 
2359
                       COLUMN_SYNC_READY,        sync_ready,
 
2360
                       COLUMN_SYNC_RATE,         sync_rate,
 
2361
                       COLUMN_HOUSE,             house,
 
2362
                       COLUMN_RJ45_PORT0,        port0,
 
2363
                       COLUMN_RJ45_PORT1,        port1,
 
2364
                       COLUMN_POLARITY,          polarity,
 
2365
                       COLUMN_SYNC_SKEW,         sync_skew,
 
2366
                       COLUMN_SYNC_INTERVAL,     sync_interval,
 
2367
                       COLUMN_HOUSE_FORMAT,      house_format,
 
2368
                       -1);
 
2369
    
 
2370
} /* add_member_to_list_store() */
 
2371
 
 
2372
 
 
2373
static gboolean check_for_ethernet(gpointer user_data)
 
2374
{
 
2375
    CtkFramelock *ctk_framelock;
 
2376
    GtkTreeIter iter;
 
2377
    GtkTreeModel *model;
 
2378
    
 
2379
    NvCtrlAttributeHandle *handle;
 
2380
    gchar *display_name;
 
2381
    gboolean valid;
 
2382
    gint val;
 
2383
    
 
2384
    ctk_framelock = CTK_FRAMELOCK(user_data);
 
2385
    model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
2386
 
 
2387
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
2388
    while (valid) {
 
2389
        gtk_tree_model_get(model, &iter, COLUMN_HANDLE, &handle,
 
2390
                           COLUMN_DISPLAY_NAME, &display_name, -1);
 
2391
        if (!handle) break;
 
2392
 
 
2393
        NvCtrlGetAttribute(handle, NV_CTRL_FRAMELOCK_ETHERNET_DETECTED, &val);
 
2394
    
 
2395
        if (val != NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_NONE) {
 
2396
            error_msg(ctk_framelock, "<span weight=\"bold\" size=\"larger\">"
 
2397
                      "FrameLock RJ45 Error</span>\n\n"
 
2398
                      "Either an Ethernet LAN cable is connected to the "
 
2399
                      "framelock board on X Screen '%s' or the linked PC is "
 
2400
                      "not turned on. "
 
2401
                      "Either disconnect the LAN cable or turn on the linked "
 
2402
                      "PC for proper operation.",
 
2403
                      display_name);
 
2404
            
 
2405
            ctk_config_remove_timer(ctk_framelock->ctk_config,
 
2406
                                    (GSourceFunc) check_for_ethernet);
 
2407
            return FALSE;
 
2408
        }
 
2409
 
 
2410
        valid = gtk_tree_model_iter_next(model, &iter);
 
2411
    }
 
2412
 
 
2413
    return TRUE;
 
2414
}
 
2415
 
 
2416
 
 
2417
 
 
2418
static gboolean find_master(CtkFramelock *ctk_framelock,
 
2419
                            GtkTreeIter *return_iter,
 
2420
                            NvCtrlAttributeHandle **return_handle)
 
2421
{
 
2422
    GtkTreeModel *model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
2423
    NvCtrlAttributeHandle *handle = NULL;
 
2424
    gboolean master = FALSE, valid;
 
2425
    GtkTreeIter iter;
 
2426
 
 
2427
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
2428
    while (valid) {
 
2429
        gtk_tree_model_get(model, &iter,
 
2430
                           COLUMN_MASTER, &master,
 
2431
                           COLUMN_HANDLE, &handle,
 
2432
                           -1);
 
2433
        if (master) break;
 
2434
 
 
2435
        valid = gtk_tree_model_iter_next(model, &iter);
 
2436
    }
 
2437
 
 
2438
    if (return_iter) *return_iter = iter;
 
2439
    if (return_handle) *return_handle = handle;
 
2440
    
 
2441
    return master;
 
2442
}
 
2443
 
 
2444
 
 
2445
 
 
2446
/*
 
2447
 * ctk_framelock_config_file_attributes() - add to the ParsedAttribute
 
2448
 * list any attributes that we want saved in the config file.
 
2449
 */
 
2450
 
 
2451
void ctk_framelock_config_file_attributes(GtkWidget *w, ParsedAttribute *head)
 
2452
{
 
2453
    CtkFramelock *ctk_framelock = CTK_FRAMELOCK(w);
 
2454
    GtkTreeModel *model = GTK_TREE_MODEL(ctk_framelock->list_store);
 
2455
    GtkTreeIter   iter;
 
2456
    gboolean      master, valid;
 
2457
    gchar        *display_name;
 
2458
    guint         polarity, display_mask;
 
2459
    gint          delay, sync_interval, house_format;
 
2460
    ParsedAttribute a;
 
2461
    
 
2462
    valid = gtk_tree_model_get_iter_first(model, &iter);
 
2463
    while (valid) {
 
2464
 
 
2465
        /*
 
2466
         * XXX is it sufficient to use sw state, or should we query
 
2467
         * the hw?
 
2468
         */
 
2469
 
 
2470
        gtk_tree_model_get(model, &iter,
 
2471
                           COLUMN_DISPLAY_NAME, &display_name,
 
2472
                           COLUMN_MASTER,       &master,
 
2473
                           COLUMN_POLARITY,     &polarity,
 
2474
                           COLUMN_SYNC_SKEW,    &delay,
 
2475
                           COLUMN_DISPLAY_MASK, &display_mask,
 
2476
                           COLUMN_SYNC_INTERVAL,&sync_interval,
 
2477
                           COLUMN_HOUSE_FORMAT, &house_format,
 
2478
                           -1);
 
2479
 
 
2480
#define __ADD_ATTR(x,y,z)                     \
 
2481
        a.display             = display_name; \
 
2482
        a.attr                = (x);          \
 
2483
        a.val                 = (y);          \
 
2484
        a.display_device_mask = (z);          \
 
2485
        nv_parsed_attribute_add(head, &a);
 
2486
 
 
2487
        __ADD_ATTR(NV_CTRL_FRAMELOCK_MASTER, master, 0);
 
2488
        __ADD_ATTR(NV_CTRL_FRAMELOCK_POLARITY, polarity, 0);
 
2489
        __ADD_ATTR(NV_CTRL_FRAMELOCK_SYNC_DELAY, delay, 0);
 
2490
        __ADD_ATTR(NV_CTRL_FRAMELOCK_SYNC,
 
2491
                   ctk_framelock->framelock_enabled, display_mask);
 
2492
 
 
2493
        if (master) {
 
2494
            __ADD_ATTR(NV_CTRL_FRAMELOCK_SYNC_INTERVAL, sync_interval, 0); 
 
2495
            __ADD_ATTR(NV_CTRL_FRAMELOCK_VIDEO_MODE, house_format, 0);
 
2496
        }
 
2497
 
 
2498
#undef __ADD_ATTR
 
2499
 
 
2500
        valid = gtk_tree_model_iter_next(model, &iter);
 
2501
    }
 
2502
} /* ctk_framelock_config_file_attributes() */
 
2503
 
 
2504
 
 
2505
 
 
2506
/*
 
2507
 * apply_parsed_attribute_list() - given a list of parsed attributes
 
2508
 * from the config file, apply the FrameLock settings contained
 
2509
 * therein.
 
2510
 */
 
2511
 
 
2512
static void apply_parsed_attribute_list(CtkFramelock *ctk_framelock,
 
2513
                                        ParsedAttribute *p)
 
2514
{
 
2515
    GtkTreeModel *model;
 
2516
    GtkTreeIter iter;
 
2517
    gpointer h, h_tmp;
 
2518
    gboolean valid, enable = FALSE;
 
2519
    gchar *display_name, *display_name_tmp;
 
2520
    
 
2521
    while (p) {
 
2522
        
 
2523
        if (!p->next) goto next_attribute;
 
2524
    
 
2525
        if (!(p->flags & NV_PARSER_TYPE_FRAMELOCK)) goto next_attribute;
 
2526
        
 
2527
        /*
 
2528
         * canonicalize the display name, so that we have a better
 
2529
         * chance of finding matches when we compare them below
 
2530
         */
 
2531
        
 
2532
        display_name = nv_standardize_screen_name(p->display, -1);
 
2533
        
 
2534
        /*
 
2535
         * find the NvCtrlAttributeHandle associated with this display
 
2536
         * name; either there is already an entry in the model with
 
2537
         * the same display name, and we can use its handle; or we add
 
2538
         * this display to the model and get a new handle.  As a side
 
2539
         * effect, we should end up with an iter that points into the
 
2540
         * correct entry in the model.
 
2541
         */
 
2542
        
 
2543
        h = NULL;
 
2544
        
 
2545
        model = GTK_TREE_MODEL(ctk_framelock->list_store);    
 
2546
        valid = gtk_tree_model_get_iter_first(model, &iter);
 
2547
 
 
2548
        while (valid) {
 
2549
            gtk_tree_model_get(model, &iter, COLUMN_DISPLAY_NAME,
 
2550
                               &display_name_tmp, -1);
 
2551
            if (nv_strcasecmp(display_name_tmp, display_name)) {
 
2552
                gtk_tree_model_get(model, &iter, COLUMN_HANDLE, &h, -1);
 
2553
                break;
 
2554
            }
 
2555
            
 
2556
            valid = gtk_tree_model_iter_next(model, &iter);
 
2557
        }
 
2558
    
 
2559
        if (!h) {
 
2560
            h = add_x_screen(ctk_framelock, display_name, FALSE);
 
2561
            
 
2562
            if (!h) goto next_attribute;
 
2563
 
 
2564
            model = GTK_TREE_MODEL(ctk_framelock->list_store);    
 
2565
            valid = gtk_tree_model_get_iter_first(model, &iter);
 
2566
            
 
2567
            while (valid) {
 
2568
                gtk_tree_model_get(model, &iter, COLUMN_HANDLE, &h_tmp, -1);
 
2569
                
 
2570
                if (h == h_tmp) break;
 
2571
                valid = gtk_tree_model_iter_next(model, &iter);
 
2572
            }
 
2573
        }
 
2574
        
 
2575
        /*
 
2576
         * now that we have an NvCtrlAttributeHandle and iter, apply
 
2577
         * the setting; note that this only really updates the gui,
 
2578
         * but the attributes have already been sent to the X server
 
2579
         * by the config file parser.
 
2580
         */
 
2581
        
 
2582
        switch (p->attr) {
 
2583
        case NV_CTRL_FRAMELOCK_MASTER:
 
2584
            
 
2585
            /* XXX only allow one master */
 
2586
            
 
2587
            gtk_list_store_set(ctk_framelock->list_store, &iter,
 
2588
                               COLUMN_MASTER, p->val, -1);
 
2589
            break;
 
2590
            
 
2591
        case NV_CTRL_FRAMELOCK_POLARITY:
 
2592
            gtk_list_store_set(ctk_framelock->list_store, &iter,
 
2593
                               COLUMN_POLARITY, p->val, -1);
 
2594
            break;
 
2595
            
 
2596
        case NV_CTRL_FRAMELOCK_SYNC_DELAY:
 
2597
            gtk_list_store_set(ctk_framelock->list_store, &iter,
 
2598
                               COLUMN_SYNC_SKEW, p->val, -1);
 
2599
            break;
 
2600
            
 
2601
        case NV_CTRL_FRAMELOCK_SYNC:
 
2602
            if (p->val) enable = TRUE;
 
2603
            break;
 
2604
 
 
2605
        case NV_CTRL_FRAMELOCK_SYNC_INTERVAL:
 
2606
            gtk_list_store_set(ctk_framelock->list_store, &iter,
 
2607
                               COLUMN_SYNC_INTERVAL, p->val, -1);
 
2608
            break;
 
2609
 
 
2610
        case NV_CTRL_FRAMELOCK_VIDEO_MODE:
 
2611
            gtk_list_store_set(ctk_framelock->list_store, &iter,
 
2612
                               COLUMN_HOUSE_FORMAT, p->val, -1);
 
2613
            break;
 
2614
        }
 
2615
        
 
2616
    next_attribute:
 
2617
        
 
2618
        p = p->next;
 
2619
    }
 
2620
 
 
2621
    /*
 
2622
     * set the state of the toggle button appropriately; this will
 
2623
     * trigger toggle_sync_state_button()
 
2624
     */
 
2625
 
 
2626
    gtk_toggle_button_set_active
 
2627
        (GTK_TOGGLE_BUTTON(ctk_framelock->sync_state_button), enable);
 
2628
    
 
2629
} /* apply_parsed_attribute_list () */
 
2630
 
 
2631
 
 
2632
 
 
2633
GtkTextBuffer *ctk_framelock_create_help(GtkTextTagTable *table)
 
2634
{
 
2635
    GtkTextIter i;
 
2636
    GtkTextBuffer *b;
 
2637
 
 
2638
    b = gtk_text_buffer_new(table);
 
2639
    
 
2640
    gtk_text_buffer_get_iter_at_offset(b, &i, 0);
 
2641
 
 
2642
    ctk_help_title(b, &i, "FrameLock Help");
 
2643
 
 
2644
    ctk_help_para(b, &i, "The FrameLock control page provides a way to "
 
2645
                  "manage an entire cluster of workstations in a FrameLock "
 
2646
                  "group.");
 
2647
    
 
2648
    ctk_help_heading(b, &i, "Add X Screen...");
 
2649
    ctk_help_para(b, &i, "Use this button to add an X Screen to the "
 
2650
                  "FrameLock group.  If the X Screen is remote, be sure "
 
2651
                  "you have configured remote access (via `xhost`, "
 
2652
                  "for example) such that you are allowed to establish "
 
2653
                  "a connection.");
 
2654
    
 
2655
    ctk_help_heading(b, &i, "Remove X Screen...");
 
2656
    ctk_help_para(b, &i, "Use this button to remove the currently selected "
 
2657
                  "X Screen from the FrameLock group.  If no X Screen is "
 
2658
                  "currently selected, then this button is greyed out.");
 
2659
    
 
2660
    ctk_help_heading(b, &i, "Test Link");
 
2661
    ctk_help_para(b, &i, "Use this toggle button to enable testing of "
 
2662
                  "the cabling between all members of the FrameLock group.  "
 
2663
                  "This will cause all FrameLock boards to receive a sync "
 
2664
                  "pulse, but the GPUs will not lock to the FrameLock "
 
2665
                  "pulse.  When Test Link is enabled, no other settings may "
 
2666
                  "be changed until you disable Test Link.");
 
2667
 
 
2668
    ctk_help_heading(b, &i, "Enable FrameLock");
 
2669
    ctk_help_para(b, &i, "This will lock the refresh rates of all members "
 
2670
                  "in the FrameLock group.  When FrameLock is enabled, "
 
2671
                  "you cannot add or remove any X screens from the FrameLock "
 
2672
                  "group, nor can you enable the Test Link.");
 
2673
 
 
2674
    ctk_help_heading(b, &i, "Display");
 
2675
    ctk_help_para(b, &i, "The 'Display' column lists the name of each X "
 
2676
                  "Screen in the FrameLock group.");
 
2677
 
 
2678
    ctk_help_heading(b, &i, "Master");
 
2679
    ctk_help_para(b, &i, "This radio button indicates which X Screen in the "
 
2680
                  "FrameLock group will emit the master sync pulse to which "
 
2681
                  "all other group members will latch.");
 
2682
 
 
2683
    ctk_help_heading(b, &i, "Stereo Sync");
 
2684
    ctk_help_para(b, &i, "This indicates that the GPU stereo signal is in "
 
2685
                  "sync with the framelock stereo signal.");
 
2686
    
 
2687
    ctk_help_heading(b, &i, "Timing");
 
2688
    ctk_help_para(b, &i, "This indicates that the FrameLock board is "
 
2689
                  "receiving a timing input.");
 
2690
 
 
2691
    ctk_help_heading(b, &i, "Sync Ready");
 
2692
    ctk_help_para(b, &i, "This indicates whether the FrameLock board is "
 
2693
                  "receiving sync pulses.  Green means syncing; red "
 
2694
                  "means not syncing.");
 
2695
 
 
2696
    ctk_help_heading(b, &i, "Sync Rate");
 
2697
    ctk_help_para(b, &i, "This is the sync rate that the FrameLock board "
 
2698
                  "is receiving.");
 
2699
 
 
2700
    ctk_help_heading(b, &i, "House");
 
2701
    ctk_help_para(b, &i, "This indicates whether the FrameLock board is "
 
2702
                  "receiving synchronization from the house (BNC) connector.");
 
2703
 
 
2704
    ctk_help_heading(b, &i, "Port0, Port1");
 
2705
    ctk_help_para(b, &i, "These indicate the status of the RJ45 ports on "
 
2706
                  "the backplane of the FrameLock board.  Green LEDs "
 
2707
                  "indicate that the port is configured for input, while "
 
2708
                  "yellow LEDs indicate that the port is configured for "
 
2709
                  "output.");
 
2710
 
 
2711
    ctk_help_heading(b, &i, "Rising/Falling");
 
2712
    ctk_help_para(b, &i, "These control which edge(s) of the sync pulse "
 
2713
                  "are latched to.");
 
2714
 
 
2715
    ctk_help_heading(b, &i, "Sync Delay");
 
2716
    ctk_help_para(b, &i, "The delay (in microseconds) between the FrameLock "
 
2717
                  "pulse and the GPU pulse.");
 
2718
    
 
2719
    ctk_help_heading(b, &i, "Miscellaneous");
 
2720
    ctk_help_para(b, &i, "The FrameLock control page registers several timers "
 
2721
                  "that are executed periodically; these are listed "
 
2722
                  "in the 'Active Timers' section of the 'nvidia-settings "
 
2723
                  "Configuration' page.  Most notably is the "
 
2724
                  "'FrameLock Connection Status' "
 
2725
                  "timer: this will poll all members of the FrameLock group "
 
2726
                  "for status information.");
 
2727
 
 
2728
    ctk_help_finish(b);
 
2729
 
 
2730
    return b;
 
2731
}