Add loop and pause buttons.
[rugen] / src / page_status.c
1 /*
2 * page_status.c -- Status Page Handling
3 * Copyright (C) 2002-2003 Charles Yates <charles.yates@pandora.be>
4 * Copyright (C) 2010 Dan Dennedy <dan@dennedy.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * 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 Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <gtk/gtk.h>
29
30 #include "interface.h"
31 #include "support.h"
32 #include "dv1394app.h"
33 #include "page.h"
34
35 typedef struct
36 {
37 struct page_t parent;
38 dv1394app app;
39 GtkWidget *widget;
40 mvcp status;
41 int terminated;
42 pthread_t status_thread;
43 guint context;
44 int unit;
45 int count;
46 }
47 *page_status, page_status_t;
48
49 static GtkWidget *this_page_get_widget( page );
50
51 /** Show the status associated to a unit.
52 */
53
54 static int show_status( page_status this, mvcp_status status )
55 {
56 GtkWidget *widget = this_page_get_widget( ( page )this );
57 char temp[ 1024 ] = "";
58 char temp2[ 1024 ];
59 char label_name[ 256 ];
60
61 sprintf( temp, "%05d %05d %05d %s [", status->in, status->position, status->out, status->clip );
62
63 switch( status->status )
64 {
65 case unit_offline:
66 strcat( temp, "offline" );
67 break;
68 case unit_undefined:
69 strcat( temp, "undefined" );
70 break;
71 case unit_not_loaded:
72 strcat( temp, "unloaded" );
73 break;
74 case unit_stopped:
75 strcat( temp, "stopped" );
76 break;
77 case unit_playing:
78 strcat( temp, "playing" );
79 break;
80 case unit_paused:
81 strcat( temp, "paused" );
82 break;
83 case unit_disconnected:
84 strcat( temp, "disconnect" );
85 break;
86 default:
87 strcat( temp, "unknown" );
88 break;
89 }
90
91 strcat( temp, "]" );
92
93 sprintf( label_name, "label_unit_%d", status->unit );
94
95 gdk_threads_enter();
96 widget = lookup_widget( widget, label_name );
97 gtk_label_set_text( GTK_LABEL( widget ), temp );
98 if ( status->unit == dv1394app_get_selected_unit( this->app ) )
99 {
100 sprintf( temp2, "U%d - %s", status->unit, temp );
101 widget = lookup_widget( dv1394app_get_widget( this->app ), "statusbar" );
102 gtk_statusbar_pop( GTK_STATUSBAR( widget ), this->context );
103 gtk_statusbar_push( GTK_STATUSBAR( widget ), this->context, temp2 );
104 dv1394app_show_status( this->app, status );
105 }
106 gdk_flush();
107 gdk_threads_leave();
108
109 return status->unit >= this->count;
110 }
111
112 static void show_units( page_status this, gboolean active )
113 {
114 int index = 0;
115 int index2 = 0;
116
117 GtkWidget *widget;
118 char temp[ 1024 ] = "";
119 char button_name[ 256 ];
120
121 mvcp_units units = NULL;
122 mvcp_unit_entry_t unit;
123 int unit_count = 0;
124
125 mvcp_nodes nodes = NULL;
126 mvcp_node_entry_t node;
127 int node_count = 0;
128
129 if ( active )
130 {
131 units = mvcp_units_init( this->status );
132 unit_count = mvcp_units_count( units );
133 nodes = mvcp_nodes_init( this->status );
134 node_count = mvcp_nodes_count( nodes );
135 this->count = unit_count;
136 }
137
138 gdk_threads_enter();
139
140 for ( index = 0; index < MAX_UNITS; index ++ )
141 {
142 if ( index < unit_count )
143 {
144 mvcp_units_get( units, index, &unit );
145
146 for ( index2 = 0; index2 < node_count; index2 ++ )
147 {
148 mvcp_nodes_get( nodes, index2, &node );
149 if ( !strcmp( node.guid, unit.guid ) )
150 break;
151 }
152
153 if ( index2 < node_count )
154 sprintf( temp, "U%d - %s (%s)", unit.unit, node.name, unit.guid );
155 else
156 sprintf( temp, "U%d - %s", unit.unit, unit.guid );
157
158 sprintf( button_name, "radiobutton_%d", index );
159 widget = lookup_widget( this_page_get_widget( ( page )this ), button_name );
160 gtk_widget_show( widget );
161 gtk_button_set_label( GTK_BUTTON( widget ), temp );
162 sprintf( button_name, "label_unit_%d", index );
163 widget = lookup_widget( this_page_get_widget( ( page )this ), button_name );
164 gtk_widget_show( widget );
165 }
166 else
167 {
168 sprintf( button_name, "radiobutton_%d", index );
169 widget = lookup_widget( this_page_get_widget( ( page )this ), button_name );
170 gtk_widget_hide( widget );
171 sprintf( button_name, "label_unit_%d", index );
172 widget = lookup_widget( this_page_get_widget( ( page )this ), button_name );
173 gtk_widget_hide( widget );
174 }
175 }
176 gdk_flush();
177 gdk_threads_leave();
178
179 mvcp_notifier notifier = mvcp_get_notifier( this->status );
180 mvcp_status_t status;
181
182 for ( index = 0; index < MAX_UNITS; index ++ )
183 {
184 status.unit = index;
185 if ( !active )
186 status.status = unit_disconnected;
187 else
188 mvcp_notifier_get( notifier, &status, index );
189 show_status( this, &status );
190 }
191
192 if ( active )
193 {
194 mvcp_nodes_close( nodes );
195 mvcp_units_close( units );
196 }
197 }
198
199 /** Status monitoring thread.
200 */
201
202 static void *status_thread( void *arg )
203 {
204 page_status this = arg;
205 mvcp_notifier notifier = mvcp_get_notifier( this->status );
206 mvcp_status_t status;
207
208 show_units( this, TRUE );
209
210 while ( !this->terminated )
211 {
212 if ( mvcp_notifier_wait( notifier, &status ) != -1 )
213 {
214 char buf[32];
215
216 if ( status.status == unit_disconnected )
217 break;
218 if ( show_status( this, &status ) )
219 show_units( this, TRUE );
220 if ( mvcp_unit_get( this->app->command, this->app->selected_unit, "eof", buf, sizeof(buf) ) != -1)
221 this->app->eof = buf[0];
222 else
223 this->app->eof = 0;
224 }
225 }
226
227 show_units( this, FALSE );
228
229 if ( !this->terminated )
230 {
231 GtkWidget *widget = lookup_widget( dv1394app_get_widget( this->app ), "button_disconnect" );
232 gdk_threads_enter();
233 gtk_signal_emit_by_name( GTK_OBJECT( widget ), "clicked" );
234 gdk_threads_leave();
235 }
236
237 return NULL;
238 }
239
240 void on_radiobutton_toggled( GtkToggleButton *togglebutton, gpointer user_data )
241 {
242 page_status this = user_data;
243 dv1394app app = this->app;
244 int index = 0;
245 GtkWidget *widget = this_page_get_widget( ( page )this );
246 for ( index = 0; index < MAX_UNITS; index ++ )
247 {
248 char button_name[ 256 ];
249 sprintf( button_name, "radiobutton_%d", index );
250 if ( lookup_widget( widget, button_name ) == GTK_WIDGET( togglebutton ) )
251 break;
252 }
253 if ( index < MAX_UNITS )
254 {
255 mvcp_status_t status;
256 mvcp_notifier notifier = mvcp_get_notifier( this->status );
257 dv1394app_on_unit_change( app, index );
258 mvcp_notifier_get( notifier, &status, index );
259 gdk_threads_leave( );
260 show_status( this, &status );
261 gdk_threads_enter( );
262 }
263 }
264
265 static GtkWidget *this_page_get_widget( page super )
266 {
267 page_status this = ( page_status )super;
268 if ( this->widget == NULL )
269 this->widget = create_page_status( );
270 return this->widget;
271 }
272
273 static void this_page_get_toolbar_info( page super, GtkIconSize size, GtkWidget **icon, char **label )
274 {
275 *icon = gtk_image_new_from_stock( "gtk-home", size );
276 *label = _("_Units");
277 }
278
279 static void this_page_on_connect( page super )
280 {
281 page_status this = ( page_status )super;
282 if ( this->terminated )
283 {
284 this->terminated = 0;
285 this->status = mvcp_init( dv1394app_get_parser( this->app ) );
286 pthread_create( &this->status_thread, NULL, status_thread, this );
287 }
288 }
289
290 static void this_page_on_disconnect( page super )
291 {
292 page_status this = ( page_status )super;
293 if ( !this->terminated )
294 {
295 GtkWidget *widget;
296 this->terminated = 1;
297 gdk_threads_leave();
298 pthread_join( this->status_thread, NULL );
299 gdk_threads_enter();
300 mvcp_close( this->status );
301 widget = lookup_widget( dv1394app_get_widget( this->app ), "statusbar" );
302 gtk_statusbar_push( GTK_STATUSBAR( widget ), this->context, "Disconnected." );
303 }
304 }
305
306 static void this_page_close( page super )
307 {
308 page_status this = ( page_status )super;
309 if ( this != NULL )
310 free( this );
311 }
312
313 page page_status_init( dv1394app app )
314 {
315 page_status this = calloc( 1, sizeof( page_status_t ) );
316 int index = 0;
317 GtkWidget *widget;
318
319 this->parent.get_widget = this_page_get_widget;
320 this->parent.get_toolbar_info = this_page_get_toolbar_info;
321 this->parent.on_connect = this_page_on_connect;
322 this->parent.on_disconnect = this_page_on_disconnect;
323 this->parent.close = this_page_close;
324 this->app = app;
325 this->terminated = 1;
326
327 for ( index = 0; index < MAX_UNITS; index ++ )
328 {
329 char button_name[ 256 ];
330 sprintf( button_name, "radiobutton_%d", index );
331 widget = lookup_widget( this_page_get_widget( ( page )this ), button_name );
332 gtk_signal_connect( GTK_OBJECT( widget ), "toggled", GTK_SIGNAL_FUNC( on_radiobutton_toggled ), this );
333 }
334
335 widget = lookup_widget( dv1394app_get_widget( this->app ), "statusbar" );
336 this->context = gtk_statusbar_get_context_id( GTK_STATUSBAR( widget ), "info" );
337 gtk_statusbar_push( GTK_STATUSBAR( widget ), this->context, "Disconnected." );
338
339 return ( page )this;
340 }