comparison src/Input/amidi-plug/i_configure-alsa.c @ 0:13389e613d67 trunk

[svn] - initial import of audacious-plugins tree (lots to do)
author nenolod
date Mon, 18 Sep 2006 01:11:49 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:13389e613d67
1 /*
2 *
3 * Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21
22 #include "i_configure-alsa.h"
23 #include "backend-alsa/b-alsa-config.h"
24 #include "backend-alsa/backend-alsa-icon.xpm"
25
26
27 enum
28 {
29 LISTPORT_TOGGLE_COLUMN = 0,
30 LISTPORT_PORTNUM_COLUMN,
31 LISTPORT_CLIENTNAME_COLUMN,
32 LISTPORT_PORTNAME_COLUMN,
33 LISTPORT_POINTER_COLUMN,
34 LISTPORT_N_COLUMNS
35 };
36
37 enum
38 {
39 LISTCARD_NAME_COLUMN = 0,
40 LISTCARD_ID_COLUMN,
41 LISTCARD_MIXERPTR_COLUMN,
42 LISTCARD_N_COLUMNS
43 };
44
45 enum
46 {
47 LISTMIXER_NAME_COLUMN = 0,
48 LISTMIXER_ID_COLUMN,
49 LISTMIXER_N_COLUMNS
50 };
51
52
53
54 void i_configure_ev_portlv_changetoggle( GtkCellRendererToggle * rdtoggle ,
55 gchar * path_str , gpointer data )
56 {
57 GtkTreeModel *model = (GtkTreeModel*)data;
58 GtkTreeIter iter;
59 GtkTreePath *path = gtk_tree_path_new_from_string( path_str );
60 gboolean toggled;
61
62 gtk_tree_model_get_iter( model , &iter , path );
63 gtk_tree_model_get( model , &iter , LISTPORT_TOGGLE_COLUMN , &toggled , -1 );
64
65 toggled ^= 1;
66 gtk_list_store_set( GTK_LIST_STORE(model), &iter , LISTPORT_TOGGLE_COLUMN , toggled , -1 );
67
68 gtk_tree_path_free (path);
69 }
70
71
72 gboolean i_configure_ev_mixctlcmb_inspect( GtkTreeModel * store , GtkTreePath * path,
73 GtkTreeIter * iter , gpointer mixctl_cmb )
74 {
75 gint ctl_id;
76 gchar * ctl_name;
77 amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
78 gtk_tree_model_get( GTK_TREE_MODEL(store) , iter ,
79 LISTMIXER_ID_COLUMN , &ctl_id ,
80 LISTMIXER_NAME_COLUMN , &ctl_name , -1 );
81 if (( !strcmp( ctl_name , alsacfg->alsa_mixer_ctl_name ) ) &&
82 ( ctl_id == alsacfg->alsa_mixer_ctl_id ))
83 {
84 /* this is the selected control in the mixer control combobox */
85 gtk_combo_box_set_active_iter( GTK_COMBO_BOX(mixctl_cmb) , iter );
86 return TRUE;
87 }
88 g_free( ctl_name );
89 return FALSE;
90 }
91
92
93 void i_configure_ev_cardcmb_changed( GtkWidget * card_cmb , gpointer mixctl_cmb )
94 {
95 GtkTreeIter iter;
96 if( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(card_cmb) , &iter ) )
97 {
98 amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
99 gpointer mixctl_store;
100 gint card_id;
101 GtkTreeModel * store = gtk_combo_box_get_model( GTK_COMBO_BOX(card_cmb) );
102 gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter ,
103 LISTCARD_ID_COLUMN , &card_id ,
104 LISTCARD_MIXERPTR_COLUMN , &mixctl_store , -1 );
105 gtk_combo_box_set_model( GTK_COMBO_BOX(mixctl_cmb) , GTK_TREE_MODEL(mixctl_store) );
106
107 /* check if the selected card is the one contained in configuration */
108 if ( card_id == alsacfg->alsa_mixer_card_id )
109 {
110 /* search for the selected mixer control in combo box */
111 gtk_tree_model_foreach( GTK_TREE_MODEL(mixctl_store) ,
112 i_configure_ev_mixctlcmb_inspect , mixctl_cmb );
113 }
114 }
115 }
116
117
118 gboolean i_configure_ev_portlv_inspecttoggle( GtkTreeModel * model , GtkTreePath * path ,
119 GtkTreeIter * iter , gpointer wpp )
120 {
121 gboolean toggled = FALSE;
122 gchar * portstring;
123 GString * wps = wpp;
124 gtk_tree_model_get ( model , iter ,
125 LISTPORT_TOGGLE_COLUMN , &toggled ,
126 LISTPORT_PORTNUM_COLUMN , &portstring , -1 );
127 if ( toggled ) /* check if the row points to an enabled port */
128 {
129 /* if this is not the first port added to wp, use comma as separator */
130 if ( wps->str[0] != '\0' ) g_string_append_c( wps , ',' );
131 g_string_append( wps , portstring );
132 }
133 g_free( portstring );
134 return FALSE;
135 }
136
137
138 void i_configure_ev_portlv_commit( gpointer port_lv )
139 {
140 amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
141 GtkTreeModel * store;
142 GString *wp = g_string_new( "" );
143 /* get the model of the port listview */
144 store = gtk_tree_view_get_model( GTK_TREE_VIEW(port_lv) );
145 /* after going through this foreach, wp contains a comma-separated list of selected ports */
146 gtk_tree_model_foreach( store , i_configure_ev_portlv_inspecttoggle , wp );
147 g_free( alsacfg->alsa_seq_wports ); /* free previous */
148 alsacfg->alsa_seq_wports = g_strdup( wp->str ); /* set with new */
149 g_string_free( wp , TRUE ); /* not needed anymore */
150 return;
151 }
152
153 void i_configure_ev_cardcmb_commit( gpointer card_cmb )
154 {
155 GtkTreeModel * store;
156 GtkTreeIter iter;
157 store = gtk_combo_box_get_model( GTK_COMBO_BOX(card_cmb) );
158 /* get the selected item */
159 if ( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(card_cmb) , &iter ) )
160 {
161 amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
162 /* update amidiplug_cfg.alsa_mixer_card_id */
163 gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter ,
164 LISTCARD_ID_COLUMN ,
165 &alsacfg->alsa_mixer_card_id , -1 );
166 }
167 return;
168 }
169
170 void i_configure_ev_mixctlcmb_commit( gpointer mixctl_cmb )
171 {
172 GtkTreeModel * store;
173 GtkTreeIter iter;
174 store = gtk_combo_box_get_model( GTK_COMBO_BOX(mixctl_cmb) );
175 /* get the selected item */
176 if ( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(mixctl_cmb) , &iter ) )
177 {
178 amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
179 g_free( alsacfg->alsa_mixer_ctl_name ); /* free previous */
180 /* update amidiplug_cfg.alsa_mixer_card_id */
181 gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter ,
182 LISTMIXER_NAME_COLUMN ,
183 &alsacfg->alsa_mixer_ctl_name ,
184 LISTMIXER_ID_COLUMN ,
185 &alsacfg->alsa_mixer_ctl_id , -1 );
186 }
187 return;
188 }
189
190
191 void i_configure_gui_ctlcmb_datafunc( GtkCellLayout *cell_layout , GtkCellRenderer *cr ,
192 GtkTreeModel *store , GtkTreeIter *iter , gpointer p )
193 {
194 gchar *ctl_display, *ctl_name;
195 gint ctl_id;
196 gtk_tree_model_get( store , iter ,
197 LISTMIXER_NAME_COLUMN , &ctl_name ,
198 LISTMIXER_ID_COLUMN , &ctl_id , -1 );
199 if ( ctl_id == 0 )
200 ctl_display = g_strdup_printf( "%s" , ctl_name );
201 else
202 ctl_display = g_strdup_printf( "%s (%i)" , ctl_name , ctl_id );
203 g_object_set( G_OBJECT(cr) , "text" , ctl_display , NULL );
204 g_free( ctl_display );
205 g_free( ctl_name );
206 }
207
208
209 void i_configure_gui_tab_alsa( GtkWidget * alsa_page_alignment ,
210 gpointer backend_list_p ,
211 gpointer commit_button )
212 {
213 GtkWidget *alsa_page_vbox;
214 GtkWidget *title_widget;
215 GtkWidget *content_vbox; /* this vbox will contain two items of equal space (50%/50%) */
216 GSList * backend_list = backend_list_p;
217 gboolean alsa_module_ok = FALSE;
218 gchar * alsa_module_pathfilename;
219
220 alsa_page_vbox = gtk_vbox_new( FALSE , 0 );
221
222 title_widget = i_configure_gui_draw_title( _("ALSA BACKEND CONFIGURATION") );
223 gtk_box_pack_start( GTK_BOX(alsa_page_vbox) , title_widget , FALSE , FALSE , 2 );
224
225 content_vbox = gtk_vbox_new( TRUE , 2 );
226
227 /* check if the ALSA module is available */
228 while ( backend_list != NULL )
229 {
230 amidiplug_sequencer_backend_name_t * mn = backend_list->data;
231 if ( !strcmp( mn->name , "alsa" ) )
232 {
233 alsa_module_ok = TRUE;
234 alsa_module_pathfilename = mn->filename;
235 break;
236 }
237 backend_list = backend_list->next;
238 }
239
240 if ( alsa_module_ok )
241 {
242 GtkListStore *port_store, *mixer_card_store;
243 GtkWidget *port_lv, *port_lv_sw, *port_lv_frame;
244 GtkCellRenderer *port_lv_toggle_rndr, *port_lv_text_rndr;
245 GtkTreeViewColumn *port_lv_toggle_col, *port_lv_portnum_col;
246 GtkTreeViewColumn *port_lv_clientname_col, *port_lv_portname_col;
247 GtkTreeSelection *port_lv_sel;
248 GtkTreeIter iter;
249 GtkWidget *mixer_table, *mixer_frame;
250 GtkCellRenderer *mixer_card_cmb_text_rndr, *mixer_ctl_cmb_text_rndr;
251 GtkWidget *mixer_card_cmb_evbox, *mixer_card_cmb, *mixer_card_label;
252 GtkWidget *mixer_ctl_cmb_evbox, *mixer_ctl_cmb, *mixer_ctl_label;
253 GtkTooltips *tips;
254
255 amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
256
257 gchar **portstring_from_cfg = NULL;
258
259 GModule * alsa_module;
260 GSList *wports = NULL, *wports_h = NULL, *scards = NULL, *scards_h = NULL;
261 GSList * (*get_port_list)( void );
262 void (*free_port_list)( GSList * );
263 GSList * (*get_card_list)( void );
264 void (*free_card_list)( GSList * );
265
266 if ( strlen( alsacfg->alsa_seq_wports ) > 0 )
267 portstring_from_cfg = g_strsplit( alsacfg->alsa_seq_wports , "," , 0 );
268
269 tips = gtk_tooltips_new();
270 g_object_set_data_full( G_OBJECT(alsa_page_alignment) , "tt" , tips , g_object_unref );
271
272 /* it's legit to assume that this can't fail,
273 since the module is present in the backend_list */
274 alsa_module = g_module_open( alsa_module_pathfilename , 0 );
275 g_module_symbol( alsa_module , "sequencer_port_get_list" , (gpointer*)&get_port_list );
276 g_module_symbol( alsa_module , "sequencer_port_free_list" , (gpointer*)&free_port_list );
277 g_module_symbol( alsa_module , "alsa_card_get_list" , (gpointer*)&get_card_list );
278 g_module_symbol( alsa_module , "alsa_card_free_list" , (gpointer*)&free_card_list );
279 /* get an updated list of writable ALSA MIDI ports and ALSA-enabled sound cards*/
280 wports = get_port_list(); wports_h = wports;
281 scards = get_card_list(); scards_h = scards;
282
283 /* ALSA MIDI PORT LISTVIEW */
284 port_store = gtk_list_store_new( LISTPORT_N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING ,
285 G_TYPE_STRING , G_TYPE_STRING , G_TYPE_POINTER );
286 while ( wports != NULL )
287 {
288 gboolean toggled = FALSE;
289 data_bucket_t * portinfo = (data_bucket_t *)wports->data;
290 GString * portstring = g_string_new("");
291 G_STRING_PRINTF( portstring , "%i:%i" , portinfo->bint[0] , portinfo->bint[1] );
292 gtk_list_store_append( port_store , &iter );
293 /* in the existing configuration there may be previously selected ports */
294 if ( portstring_from_cfg != NULL )
295 {
296 gint i = 0;
297 /* check if current row contains a port selected by user */
298 for ( i = 0 ; portstring_from_cfg[i] != NULL ; i++ )
299 {
300 /* if it's one of the selected ports, toggle its checkbox */
301 if ( !strcmp( portstring->str, portstring_from_cfg[i] ) )
302 toggled = TRUE;
303 }
304 }
305 gtk_list_store_set( port_store , &iter ,
306 LISTPORT_TOGGLE_COLUMN , toggled ,
307 LISTPORT_PORTNUM_COLUMN , portstring->str ,
308 LISTPORT_CLIENTNAME_COLUMN , portinfo->bcharp[0] ,
309 LISTPORT_PORTNAME_COLUMN , portinfo->bcharp[1] ,
310 LISTPORT_POINTER_COLUMN , portinfo , -1 );
311 g_string_free( portstring , TRUE );
312 /* on with next */
313 wports = wports->next;
314 }
315 g_strfreev( portstring_from_cfg ); /* not needed anymore */
316 port_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(port_store) );
317 gtk_tree_view_set_rules_hint( GTK_TREE_VIEW(port_lv), TRUE );
318 g_object_unref( port_store );
319 port_lv_toggle_rndr = gtk_cell_renderer_toggle_new();
320 gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , FALSE );
321 gtk_cell_renderer_toggle_set_active( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , TRUE );
322 g_signal_connect( port_lv_toggle_rndr , "toggled" ,
323 G_CALLBACK(i_configure_ev_portlv_changetoggle) , port_store );
324 port_lv_text_rndr = gtk_cell_renderer_text_new();
325 port_lv_toggle_col = gtk_tree_view_column_new_with_attributes( "", port_lv_toggle_rndr,
326 "active", LISTPORT_TOGGLE_COLUMN, NULL );
327 port_lv_portnum_col = gtk_tree_view_column_new_with_attributes( _("Port"), port_lv_text_rndr,
328 "text", LISTPORT_PORTNUM_COLUMN, NULL );
329 port_lv_clientname_col = gtk_tree_view_column_new_with_attributes( _("Client name"), port_lv_text_rndr,
330 "text", LISTPORT_CLIENTNAME_COLUMN, NULL );
331 port_lv_portname_col = gtk_tree_view_column_new_with_attributes( _("Port name"), port_lv_text_rndr,
332 "text", LISTPORT_PORTNAME_COLUMN, NULL );
333 gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_toggle_col );
334 gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portnum_col );
335 gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_clientname_col );
336 gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portname_col );
337 port_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(port_lv) );
338 gtk_tree_selection_set_mode( GTK_TREE_SELECTION(port_lv_sel) , GTK_SELECTION_NONE );
339 port_lv_sw = gtk_scrolled_window_new( NULL , NULL );
340 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(port_lv_sw),
341 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS );
342 port_lv_frame = gtk_frame_new( _("ALSA output ports") );
343 gtk_container_add( GTK_CONTAINER(port_lv_sw) , port_lv );
344 gtk_container_add( GTK_CONTAINER(port_lv_frame) , port_lv_sw );
345 gtk_box_pack_start( GTK_BOX(content_vbox) , port_lv_frame , TRUE , TRUE , 0 );
346 g_signal_connect_swapped( G_OBJECT(commit_button) , "ap-commit" ,
347 G_CALLBACK(i_configure_ev_portlv_commit) , port_lv );
348
349 /* MIXER CARD/CONTROL COMBOBOXES */
350 mixer_card_store = gtk_list_store_new( LISTCARD_N_COLUMNS , G_TYPE_STRING , G_TYPE_INT , G_TYPE_POINTER );
351 mixer_card_cmb = gtk_combo_box_new_with_model( GTK_TREE_MODEL(mixer_card_store) ); /* soundcard combo box */
352 mixer_ctl_cmb = gtk_combo_box_new(); /* mixer control combo box */
353 g_signal_connect( mixer_card_cmb , "changed" , G_CALLBACK(i_configure_ev_cardcmb_changed) , mixer_ctl_cmb );
354 while ( scards != NULL )
355 {
356 GtkListStore *mixer_ctl_store;
357 GtkTreeIter itermix;
358 data_bucket_t * cardinfo = (data_bucket_t *)scards->data;
359 GSList *mixctl_list = cardinfo->bpointer[0];
360 mixer_ctl_store = gtk_list_store_new( LISTMIXER_N_COLUMNS , G_TYPE_STRING , G_TYPE_INT );
361 while ( mixctl_list != NULL )
362 {
363 data_bucket_t * mixctlinfo = (data_bucket_t *)mixctl_list->data;
364 gtk_list_store_append( mixer_ctl_store , &itermix );
365 gtk_list_store_set( mixer_ctl_store , &itermix ,
366 LISTMIXER_NAME_COLUMN , mixctlinfo->bcharp[0] ,
367 LISTMIXER_ID_COLUMN , mixctlinfo->bint[0] , -1 );
368 mixctl_list = mixctl_list->next; /* on with next mixer control */
369 }
370 gtk_list_store_append( mixer_card_store , &iter );
371 gtk_list_store_set( mixer_card_store , &iter ,
372 LISTCARD_NAME_COLUMN , cardinfo->bcharp[0] ,
373 LISTCARD_ID_COLUMN , cardinfo->bint[0] ,
374 LISTCARD_MIXERPTR_COLUMN , mixer_ctl_store , -1 );
375 /* check if this corresponds to the value previously selected by user */
376 if ( cardinfo->bint[0] == alsacfg->alsa_mixer_card_id )
377 gtk_combo_box_set_active_iter( GTK_COMBO_BOX(mixer_card_cmb) , &iter );
378 scards = scards->next; /* on with next card */
379 }
380 g_object_unref( mixer_card_store ); /* free a reference, no longer needed */
381 /* create renderer to display text in the mixer combo box */
382 mixer_card_cmb_text_rndr = gtk_cell_renderer_text_new();
383 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr , TRUE );
384 gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr ,
385 "text" , LISTCARD_NAME_COLUMN );
386 mixer_ctl_cmb_text_rndr = gtk_cell_renderer_text_new();
387 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(mixer_ctl_cmb) , mixer_ctl_cmb_text_rndr , TRUE );
388 gtk_cell_layout_set_cell_data_func( GTK_CELL_LAYOUT(mixer_ctl_cmb) , mixer_ctl_cmb_text_rndr ,
389 i_configure_gui_ctlcmb_datafunc , NULL , NULL );
390 /* the event box is needed to display a tooltip for the mixer combo box */
391 mixer_card_cmb_evbox = gtk_event_box_new();
392 gtk_container_add( GTK_CONTAINER(mixer_card_cmb_evbox) , mixer_card_cmb );
393 mixer_ctl_cmb_evbox = gtk_event_box_new();
394 gtk_container_add( GTK_CONTAINER(mixer_ctl_cmb_evbox) , mixer_ctl_cmb );
395 mixer_card_label = gtk_label_new( _("Soundcard: ") );
396 gtk_misc_set_alignment( GTK_MISC(mixer_card_label) , 0 , 0.5 );
397 mixer_ctl_label = gtk_label_new( _("Mixer control: ") );
398 gtk_misc_set_alignment( GTK_MISC(mixer_ctl_label) , 0 , 0.5 );
399 mixer_table = gtk_table_new( 3 , 2 , FALSE );
400 gtk_container_set_border_width( GTK_CONTAINER(mixer_table), 4 );
401 gtk_table_attach( GTK_TABLE(mixer_table) , mixer_card_label , 0 , 1 , 0 , 1 ,
402 GTK_FILL , 0 , 1 , 2 );
403 gtk_table_attach( GTK_TABLE(mixer_table) , mixer_card_cmb_evbox , 1 , 2 , 0 , 1 ,
404 GTK_EXPAND | GTK_FILL , 0 , 1 , 2 );
405 gtk_table_attach( GTK_TABLE(mixer_table) , mixer_ctl_label , 0 , 1 , 1 , 2 ,
406 GTK_FILL , 0 , 1 , 2 );
407 gtk_table_attach( GTK_TABLE(mixer_table) , mixer_ctl_cmb_evbox , 1 , 2 , 1 , 2 ,
408 GTK_EXPAND | GTK_FILL , 0 , 1 , 2 );
409 mixer_frame = gtk_frame_new( _("Mixer settings") );
410 gtk_container_add( GTK_CONTAINER(mixer_frame) , mixer_table );
411 gtk_box_pack_start( GTK_BOX(content_vbox) , mixer_frame , TRUE , TRUE , 0 );
412 g_signal_connect_swapped( G_OBJECT(commit_button) , "ap-commit" ,
413 G_CALLBACK(i_configure_ev_cardcmb_commit) , mixer_card_cmb );
414 g_signal_connect_swapped( G_OBJECT(commit_button) , "ap-commit" ,
415 G_CALLBACK(i_configure_ev_mixctlcmb_commit) , mixer_ctl_cmb );
416
417 free_card_list( scards_h );
418 free_port_list( wports_h );
419 g_module_close( alsa_module );
420
421 gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , port_lv ,
422 _("* Select ALSA output ports *\n"
423 "MIDI events will be sent to the ports selected here. In example, if your "
424 "audio card provides a hardware synth and you want to play MIDI with it, "
425 "you'll probably want to select the wavetable synthesizer ports.") , "" );
426 gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , mixer_card_cmb_evbox ,
427 _("* Select ALSA mixer card *\n"
428 "The ALSA backend outputs directly through ALSA, it doesn't use effect "
429 "and ouput plugins from the player. During playback, the player volume"
430 "slider will manipulate the mixer control you select here. "
431 "If you're using wavetable synthesizer ports, you'll probably want to "
432 "select the Synth control here.") , "" );
433 gtk_tooltips_set_tip( GTK_TOOLTIPS(tips) , mixer_ctl_cmb_evbox ,
434 _("* Select ALSA mixer control *\n"
435 "The ALSA backend outputs directly through ALSA, it doesn't use effect "
436 "and ouput plugins from the player. During playback, the player volume "
437 "slider will manipulate the mixer control you select here. "
438 "If you're using wavetable synthesizer ports, you'll probably want to "
439 "select the Synth control here.") , "" );
440 }
441 else
442 {
443 /* display "not available" information */
444 GtkWidget * info_label;
445 info_label = gtk_label_new( _("ALSA Backend not loaded or not available") );
446 gtk_box_pack_start( GTK_BOX(alsa_page_vbox) , info_label , FALSE , FALSE , 2 );
447 }
448
449 gtk_box_pack_start( GTK_BOX(alsa_page_vbox) , content_vbox , TRUE , TRUE , 2 );
450 gtk_container_add( GTK_CONTAINER(alsa_page_alignment) , alsa_page_vbox );
451 }
452
453
454 void i_configure_gui_tablabel_alsa( GtkWidget * alsa_page_alignment ,
455 gpointer backend_list_p ,
456 gpointer commit_button )
457 {
458 GtkWidget *pagelabel_vbox, *pagelabel_image, *pagelabel_label;
459 GdkPixbuf *pagelabel_image_pix;
460 pagelabel_vbox = gtk_vbox_new( FALSE , 1 );
461 pagelabel_image_pix = gdk_pixbuf_new_from_xpm_data( (const gchar **)backend_alsa_icon_xpm );
462 pagelabel_image = gtk_image_new_from_pixbuf( pagelabel_image_pix ); g_object_unref( pagelabel_image_pix );
463 pagelabel_label = gtk_label_new( "" );
464 gtk_label_set_markup( GTK_LABEL(pagelabel_label) , "<span size=\"smaller\">ALSA\nbackend</span>" );
465 gtk_label_set_justify( GTK_LABEL(pagelabel_label) , GTK_JUSTIFY_CENTER );
466 gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_image , FALSE , FALSE , 1 );
467 gtk_box_pack_start( GTK_BOX(pagelabel_vbox) , pagelabel_label , FALSE , FALSE , 1 );
468 gtk_container_add( GTK_CONTAINER(alsa_page_alignment) , pagelabel_vbox );
469 gtk_widget_show_all( alsa_page_alignment );
470 return;
471 }
472
473
474 gchar * i_configure_read_seq_ports_default( void )
475 {
476 FILE * fp = NULL;
477 /* first try, get seq ports from proc on card0 */
478 fp = fopen( "/proc/asound/card0/wavetableD1" , "rb" );
479 if ( fp )
480 {
481 gchar buffer[100];
482 while ( !feof( fp ) )
483 {
484 fgets( buffer , 100 , fp );
485 if (( strlen( buffer ) > 11 ) && ( !strncasecmp( buffer , "addresses: " , 11 ) ))
486 {
487 /* change spaces between ports (65:0 65:1 65:2 ...)
488 into commas (65:0,65:1,65:2,...) */
489 g_strdelimit( &buffer[11] , " " , ',' );
490 /* remove lf and cr from the end of the string */
491 g_strdelimit( &buffer[11] , "\r\n" , '\0' );
492 /* ready to go */
493 DEBUGMSG( "init, default values for seq ports detected: %s\n" , &buffer[11] );
494 fclose( fp );
495 return g_strdup( &buffer[11] );
496 }
497 }
498 fclose( fp );
499 }
500
501 /* second option: do not set ports at all, let the user
502 select the right ones in the nice config window :) */
503 return g_strdup( "" );
504 }
505
506
507
508 void i_configure_cfg_alsa_alloc( void )
509 {
510 amidiplug_cfg_alsa_t * alsacfg = g_malloc(sizeof(amidiplug_cfg_alsa_t));
511 amidiplug_cfg_backend->alsa = alsacfg;
512 }
513
514
515 void i_configure_cfg_alsa_free( void )
516 {
517 amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
518 g_free( alsacfg->alsa_seq_wports );
519 g_free( alsacfg->alsa_mixer_ctl_name );
520 g_free( amidiplug_cfg_backend->alsa );
521 }
522
523
524 void i_configure_cfg_alsa_read( pcfg_t * cfgfile )
525 {
526 amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
527
528 if (!cfgfile)
529 {
530 /* alsa backend defaults */
531 alsacfg->alsa_seq_wports = i_configure_read_seq_ports_default();
532 alsacfg->alsa_mixer_card_id = 0;
533 alsacfg->alsa_mixer_ctl_name = g_strdup( "Synth" );
534 alsacfg->alsa_mixer_ctl_id = 0;
535 }
536 else
537 {
538 i_pcfg_read_string( cfgfile , "alsa" , "alsa_seq_wports" , &alsacfg->alsa_seq_wports , NULL );
539 if ( alsacfg->alsa_seq_wports == NULL )
540 alsacfg->alsa_seq_wports = i_configure_read_seq_ports_default(); /* pick default values */
541 i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_card_id" , &alsacfg->alsa_mixer_card_id , 0 );
542 i_pcfg_read_string( cfgfile , "alsa" , "alsa_mixer_ctl_name" , &alsacfg->alsa_mixer_ctl_name , "Synth" );
543 i_pcfg_read_integer( cfgfile , "alsa" , "alsa_mixer_ctl_id" , &alsacfg->alsa_mixer_ctl_id , 0 );
544 }
545 }
546
547
548 void i_configure_cfg_alsa_save( pcfg_t * cfgfile )
549 {
550 amidiplug_cfg_alsa_t * alsacfg = amidiplug_cfg_backend->alsa;
551
552 i_pcfg_write_string( cfgfile , "alsa" , "alsa_seq_wports" , alsacfg->alsa_seq_wports );
553 i_pcfg_write_integer( cfgfile , "alsa" , "alsa_mixer_card_id" , alsacfg->alsa_mixer_card_id );
554 i_pcfg_write_string( cfgfile , "alsa" , "alsa_mixer_ctl_name" , alsacfg->alsa_mixer_ctl_name );
555 i_pcfg_write_integer( cfgfile , "alsa" , "alsa_mixer_ctl_id" , alsacfg->alsa_mixer_ctl_id );
556 }