Mercurial > audlegacy
view Plugins/Input/amidi-plug/i_configure.c @ 950:008bf9a501b1 trunk
[svn] Moral, always compile before checking in.
author | nemo |
---|---|
date | Tue, 18 Apr 2006 07:00:25 -0700 |
parents | ee25017cb472 |
children | bc14606391fc |
line wrap: on
line source
/* * * Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006 * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "i_configure.h" /* internals */ void i_configure_upd_portlist( void ); void i_configure_upd_mixercardlist( void ); gchar * i_configure_read_seq_ports_default( void ); gboolean i_configure_ev_checktoggle( GtkTreeModel * , GtkTreePath * , GtkTreeIter * , gpointer ); void i_configure_ev_changetoggle( GtkCellRendererToggle * , gchar * , gpointer ); void i_configure_gui( GSList * wports , GSList * scards ) { GtkWidget *configwin_vbox; GtkWidget *port_lv, *port_lv_sw, *port_frame; GtkWidget *mixer_card_cmb_evbox, *mixer_card_cmb, *mixer_vbox, *mixer_frame; GtkWidget *advanced_precalc_checkbt, *advanced_vbox, *advanced_frame; GtkWidget *hseparator, *hbuttonbox, *button_ok, *button_cancel; GtkListStore *port_liststore, *mixer_card_liststore; GtkTreeIter iter; GtkTreeSelection *port_lv_sel; GtkCellRenderer *port_lv_toggle_rndr, *port_lv_text_rndr, *mixer_card_cmb_text_rndr; GtkTreeViewColumn *port_lv_toggle_col, *port_lv_portnum_col; GtkTreeViewColumn *port_lv_clientname_col, *port_lv_portname_col; gchar **portstring_from_cfg = NULL; if ( amidiplug_gui_prefs.config_win ) return; if ( strlen( amidiplug_cfg.seq_writable_ports ) > 0 ) portstring_from_cfg = g_strsplit( amidiplug_cfg.seq_writable_ports , "," , 0 ); amidiplug_gui_prefs.config_win = gtk_window_new( GTK_WINDOW_TOPLEVEL ); gtk_window_set_type_hint( GTK_WINDOW(amidiplug_gui_prefs.config_win), GDK_WINDOW_TYPE_HINT_DIALOG ); gtk_window_set_title( GTK_WINDOW(amidiplug_gui_prefs.config_win), _("AMIDI-Plug - configuration") ); gtk_container_set_border_width( GTK_CONTAINER(amidiplug_gui_prefs.config_win), 10 ); g_signal_connect( G_OBJECT(amidiplug_gui_prefs.config_win) , "destroy" , G_CALLBACK(i_configure_ev_destroy) , NULL ); configwin_vbox = gtk_vbox_new( FALSE , 0 ); gtk_container_add( GTK_CONTAINER(amidiplug_gui_prefs.config_win) , configwin_vbox ); port_liststore = gtk_list_store_new( LISTPORT_N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING , G_TYPE_STRING , G_TYPE_STRING , G_TYPE_POINTER ); /* append ALSA MIDI ports */ while ( wports != NULL ) { gint i = 0; gboolean toggled = FALSE; data_bucket_t * portinfo = (data_bucket_t *)wports->data; GString * portstring = g_string_new(""); G_STRING_PRINTF( portstring , "%i:%i" , portinfo->bint[0] , portinfo->bint[1] ); gtk_list_store_append( port_liststore , &iter ); /* in the existing configuration there may be previously selected ports */ if ( portstring_from_cfg ) { /* check if current row contains a port selected by user */ for ( i = 0 ; portstring_from_cfg[i] != NULL ; i++ ) { /* if it's one of the selected ports, toggle its checkbox */ if ( !strcmp( portstring->str, portstring_from_cfg[i] ) ) toggled = TRUE; } } gtk_list_store_set( port_liststore , &iter , LISTPORT_TOGGLE_COLUMN , toggled , LISTPORT_PORTNUM_COLUMN , portstring->str , LISTPORT_CLIENTNAME_COLUMN , portinfo->bcharp[0] , LISTPORT_PORTNAME_COLUMN , portinfo->bcharp[1] , LISTPORT_POINTER_COLUMN , portinfo , -1 ); g_string_free( portstring , TRUE ); /* on with next */ wports = wports->next; } /* this string array is not needed anymore */ g_strfreev( portstring_from_cfg ); port_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(port_liststore) ); amidiplug_gui_prefs.port_treeview = port_lv; g_object_unref( port_liststore ); port_lv_toggle_rndr = gtk_cell_renderer_toggle_new(); gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , FALSE ); gtk_cell_renderer_toggle_set_active( GTK_CELL_RENDERER_TOGGLE(port_lv_toggle_rndr) , TRUE ); g_signal_connect( port_lv_toggle_rndr , "toggled" , G_CALLBACK(i_configure_ev_changetoggle) , port_liststore ); port_lv_text_rndr = gtk_cell_renderer_text_new(); port_lv_toggle_col = gtk_tree_view_column_new_with_attributes( "", port_lv_toggle_rndr, "active", LISTPORT_TOGGLE_COLUMN, NULL ); port_lv_portnum_col = gtk_tree_view_column_new_with_attributes( _("Port"), port_lv_text_rndr, "text", LISTPORT_PORTNUM_COLUMN, NULL ); port_lv_clientname_col = gtk_tree_view_column_new_with_attributes( _("Client name"), port_lv_text_rndr, "text", LISTPORT_CLIENTNAME_COLUMN, NULL ); port_lv_portname_col = gtk_tree_view_column_new_with_attributes( _("Port name"), port_lv_text_rndr, "text", LISTPORT_PORTNAME_COLUMN, NULL ); gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_toggle_col ); gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portnum_col ); gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_clientname_col ); gtk_tree_view_append_column( GTK_TREE_VIEW(port_lv), port_lv_portname_col ); port_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(port_lv) ); gtk_tree_selection_set_mode( GTK_TREE_SELECTION(port_lv_sel) , GTK_SELECTION_SINGLE ); port_lv_sw = gtk_scrolled_window_new( NULL , NULL ); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(port_lv_sw), GTK_POLICY_NEVER, GTK_POLICY_NEVER ); port_frame = gtk_frame_new( _("ALSA output ports") ); gtk_container_add( GTK_CONTAINER(port_lv_sw) , port_lv ); gtk_container_set_border_width( GTK_CONTAINER(port_lv_sw) , 5 ); gtk_container_add( GTK_CONTAINER(port_frame) , port_lv_sw ); gtk_box_pack_start( GTK_BOX(configwin_vbox) , port_frame , TRUE , TRUE , 2 ); /**********************/ /*** MIXER SETTINGS ***/ mixer_card_liststore = gtk_list_store_new( LISTMIXER_N_COLUMNS , G_TYPE_STRING , G_TYPE_INT , G_TYPE_INT , G_TYPE_STRING ); mixer_card_cmb = gtk_combo_box_new_with_model( GTK_TREE_MODEL(mixer_card_liststore) ); amidiplug_gui_prefs.mixercard_combo = mixer_card_cmb; /* fill models with sound cards and relative mixer controls */ while ( scards != NULL ) { data_bucket_t * cardinfo = (data_bucket_t *)scards->data; GString * desc_cardmix_string = g_string_new( "" ); GSList * mixctl_list = cardinfo->bpointer[0]; while ( mixctl_list != NULL ) { data_bucket_t * mixctlinfo = (data_bucket_t *)mixctl_list->data; G_STRING_PRINTF( desc_cardmix_string , "%s - ctl: %s (ID %i)" , cardinfo->bcharp[0] , mixctlinfo->bcharp[0] , mixctlinfo->bint[0] ); gtk_list_store_append( mixer_card_liststore , &iter ); gtk_list_store_set( mixer_card_liststore , &iter , LISTMIXER_DESC_COLUMN , desc_cardmix_string->str , LISTMIXER_CARDID_COLUMN , cardinfo->bint[0] , LISTMIXER_MIXCTLID_COLUMN , mixctlinfo->bint[0] , LISTMIXER_MIXCTLNAME_COLUMN , mixctlinfo->bcharp[0] , -1 ); /* check if this corresponds to the value previously selected by user */ if ( ( cardinfo->bint[0] == amidiplug_cfg.mixer_card_id ) && ( !strcasecmp( mixctlinfo->bcharp[0] , amidiplug_cfg.mixer_control_name ) ) && ( mixctlinfo->bint[0] == amidiplug_cfg.mixer_control_id ) ) gtk_combo_box_set_active_iter( GTK_COMBO_BOX(mixer_card_cmb) , &iter ); mixctl_list = mixctl_list->next; } g_string_free( desc_cardmix_string , TRUE ); /* on with next */ scards = scards->next; } /* free the instance of liststore, we already have one in the combo box */ g_object_unref( mixer_card_liststore ); /* create renderer to display text in the mixer combo box */ mixer_card_cmb_text_rndr = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr , TRUE ); gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(mixer_card_cmb) , mixer_card_cmb_text_rndr , "text" , 0 ); /* the event box is needed to display a tooltip for the mixer combo box */ mixer_card_cmb_evbox = gtk_event_box_new(); gtk_container_add( GTK_CONTAINER(mixer_card_cmb_evbox) , mixer_card_cmb ); mixer_vbox = gtk_vbox_new( FALSE , 0 ); gtk_container_set_border_width( GTK_CONTAINER(mixer_vbox) , 5 ); gtk_box_pack_start( GTK_BOX(mixer_vbox) , mixer_card_cmb_evbox , TRUE , TRUE , 0 ); mixer_frame = gtk_frame_new( _("Mixer settings") ); gtk_container_add( GTK_CONTAINER(mixer_frame) , mixer_vbox ); gtk_box_pack_start( GTK_BOX(configwin_vbox) , mixer_frame , TRUE , TRUE , 2 ); /*************************/ /*** ADVANCED SETTINGS ***/ advanced_vbox = gtk_vbox_new( FALSE , 0 ); gtk_container_set_border_width( GTK_CONTAINER(advanced_vbox) , 5 ); advanced_precalc_checkbt = gtk_check_button_new_with_label( _("pre-calculate length of MIDI files in playlist") ); amidiplug_gui_prefs.precalc_checkbt = advanced_precalc_checkbt; if ( amidiplug_cfg.length_precalc_enable ) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(advanced_precalc_checkbt) , TRUE ); gtk_box_pack_start( GTK_BOX(advanced_vbox) , advanced_precalc_checkbt , TRUE , TRUE , 0 ); advanced_frame = gtk_frame_new( _("Advanced settings") ); gtk_container_add( GTK_CONTAINER(advanced_frame) , advanced_vbox ); gtk_box_pack_start( GTK_BOX(configwin_vbox) , advanced_frame , TRUE , TRUE , 2 ); /* horizontal separator and buttons */ hseparator = gtk_hseparator_new(); gtk_box_pack_start( GTK_BOX(configwin_vbox) , hseparator , FALSE , FALSE , 4 ); hbuttonbox = gtk_hbutton_box_new(); gtk_button_box_set_layout( GTK_BUTTON_BOX(hbuttonbox) , GTK_BUTTONBOX_END ); button_cancel = gtk_button_new_from_stock( GTK_STOCK_CANCEL ); g_signal_connect( G_OBJECT(button_cancel) , "clicked" , G_CALLBACK(i_configure_ev_bcancel) , NULL ); gtk_container_add( GTK_CONTAINER(hbuttonbox) , button_cancel ); button_ok = gtk_button_new_from_stock( GTK_STOCK_OK ); g_signal_connect( G_OBJECT(button_ok) , "clicked" , G_CALLBACK(i_configure_ev_bok) , NULL ); gtk_container_add( GTK_CONTAINER(hbuttonbox) , button_ok ); gtk_box_pack_start( GTK_BOX(configwin_vbox) , hbuttonbox , FALSE , FALSE , 0 ); /* tooltips */ amidiplug_gui_prefs.config_tips = gtk_tooltips_new(); gtk_tooltips_set_tip( GTK_TOOLTIPS(amidiplug_gui_prefs.config_tips) , port_lv , _("* Select ALSA output ports *\n" "MIDI events will be sent to the ports selected here. At least one " "port must be selected in order to play MIDI with AMIDI-Plug. Unless " "you know what you're doing, you'll probably want to use the " "wavetable synthesizer ports.") , "" ); gtk_tooltips_set_tip( GTK_TOOLTIPS(amidiplug_gui_prefs.config_tips) , mixer_card_cmb_evbox , _("* Select ALSA mixer control *\n" "AMIDI-Plug outputs directly through ALSA, it doesn't use effect " "and ouput plugins from the player. While playing with AMIDI-Plug, " "the player volume will manipulate the control you select here. " "Unless you know what you're doing, you'll probably want to select " "the Synth control here.") , "" ); gtk_tooltips_set_tip( GTK_TOOLTIPS(amidiplug_gui_prefs.config_tips) , advanced_precalc_checkbt , _("* Pre-calculate MIDI length *\n" "If this option is enabled, AMIDI-Plug will calculate the MIDI file " "length as soon as the player requests it, instead of doing that only " "when the the MIDI file is being played. In example, MIDI length " "will be calculated straight after adding MIDI files in a playlist. " "Disable this option if you want faster playlist loading (when a lot " "of MIDI files are added), enable it to display more information " "in the playlist straight after loading.") , "" ); gtk_widget_show_all( amidiplug_gui_prefs.config_win ); } void i_configure_upd_portlist( void ) { GtkTreeModel * liststore; GString *wp = g_string_new( "" ); /* get the model of the port list control */ liststore = gtk_tree_view_get_model( GTK_TREE_VIEW(amidiplug_gui_prefs.port_treeview) ); /* after the following foreach, wp contains a comma-separated list of selected ports */ gtk_tree_model_foreach( liststore , i_configure_ev_checktoggle , wp ); /* free previous */ g_free( amidiplug_cfg.seq_writable_ports ); /* update point amidiplug_cfg.seq_writable_ports so it points to the new list of ports */ amidiplug_cfg.seq_writable_ports = g_strdup( wp->str ); /* not needed anymore */ g_string_free( wp , TRUE ); return; } void i_configure_upd_mixercardlist( void ) { GtkTreeModel * liststore; GtkTreeIter iter; /* get the model of the card-mixer list control */ liststore = gtk_combo_box_get_model( GTK_COMBO_BOX(amidiplug_gui_prefs.mixercard_combo) ); /* get the selected item */ if ( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(amidiplug_gui_prefs.mixercard_combo) , &iter ) ) { /* free previous */ g_free( amidiplug_cfg.mixer_control_name ); /* update amidiplug_cfg.mixer_card_id and amidiplug_cfg.mixer_control_name */ gtk_tree_model_get( GTK_TREE_MODEL(liststore) , &iter , LISTMIXER_CARDID_COLUMN , &amidiplug_cfg.mixer_card_id , LISTMIXER_MIXCTLID_COLUMN , &amidiplug_cfg.mixer_control_id , LISTMIXER_MIXCTLNAME_COLUMN , &amidiplug_cfg.mixer_control_name , -1 ); } return; } gboolean i_configure_ev_checktoggle( GtkTreeModel * model , GtkTreePath * path , GtkTreeIter * iter , gpointer wpp ) { gboolean toggled = FALSE; gchar * portstring; GString * wps = wpp; gtk_tree_model_get ( model , iter , LISTPORT_TOGGLE_COLUMN , &toggled , LISTPORT_PORTNUM_COLUMN , &portstring , -1 ); /* check if the row points to an enabled port */ if ( toggled ) { /* if this is not the first port added to wp, use comma as separator */ if ( wps->str[0] != '\0' ) g_string_append_c( wps , ',' ); g_string_append( wps , portstring ); } g_free( portstring ); return FALSE; } void i_configure_ev_changetoggle( GtkCellRendererToggle * rdtoggle , gchar * path_str , gpointer data ) { GtkTreeModel *model = (GtkTreeModel *)data; GtkTreeIter iter; GtkTreePath *path = gtk_tree_path_new_from_string( path_str ); gboolean toggled; gtk_tree_model_get_iter( model , &iter , path ); gtk_tree_model_get( model , &iter , LISTPORT_TOGGLE_COLUMN , &toggled , -1); toggled ^= 1; gtk_list_store_set( GTK_LIST_STORE(model), &iter , LISTPORT_TOGGLE_COLUMN , toggled , -1); gtk_tree_path_free (path); } void i_configure_ev_destroy( void ) { g_object_unref( amidiplug_gui_prefs.config_tips ); amidiplug_gui_prefs.config_tips = NULL; amidiplug_gui_prefs.config_win = NULL; } void i_configure_ev_bcancel( void ) { gtk_widget_destroy(amidiplug_gui_prefs.config_win); } void i_configure_ev_bok( void ) { /* update amidiplug_cfg.seq_writable_ports using the selected values from the port list */ i_configure_upd_portlist(); /* update amidiplug_cfg.mixer_card_id and amidiplug_cfg.mixer_control_name using the selected values from the card-mixer combo list */ i_configure_upd_mixercardlist(); /* update amidiplug_cfg.length_precalc_enable using the check control in the advanced settings frame */ if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(amidiplug_gui_prefs.precalc_checkbt) ) ) amidiplug_cfg.length_precalc_enable = 1; else amidiplug_cfg.length_precalc_enable = 0; /* save settings */ i_configure_cfg_save(); gtk_widget_destroy(amidiplug_gui_prefs.config_win); } gchar * i_configure_read_seq_ports_default( void ) { FILE * fp = NULL; /* first try, get seq ports from proc on card0 */ fp = fopen( "/proc/asound/card0/wavetableD1" , "rb" ); if ( fp ) { gchar buffer[100]; while ( !feof( fp ) ) { fgets( buffer , 100 , fp ); if (( strlen( buffer ) > 11 ) && ( !strncasecmp( buffer , "addresses: " , 11 ) )) { /* change spaces between ports (65:0 65:1 65:2 ...) into commas (65:0,65:1,65:2,...) */ g_strdelimit( &buffer[11] , " " , ',' ); /* remove lf and cr from the end of the string */ g_strdelimit( &buffer[11] , "\r\n" , '\0' ); /* ready to go */ DEBUGMSG( "init, default values for seq ports detected: %s\n" , &buffer[11] ); fclose( fp ); return g_strdup( &buffer[11] ); } } fclose( fp ); } /* second option: do not set ports at all, let the user select the right ones in the nice preferences dialog :) */ return g_strdup( "" ); } void i_configure_cfg_read( void ) { ConfigFile *cfgfile; cfgfile = xmms_cfg_open_default_file(); if (!cfgfile) { /* use defaults */ amidiplug_cfg.seq_writable_ports = i_configure_read_seq_ports_default(); amidiplug_cfg.mixer_card_id = 0; amidiplug_cfg.mixer_control_name = g_strdup( "Synth" ); amidiplug_cfg.mixer_control_id = 0; amidiplug_cfg.length_precalc_enable = 0; } else { if ( !xmms_cfg_read_string( cfgfile , "amidi-plug" , "writable_ports" , &amidiplug_cfg.seq_writable_ports ) ) amidiplug_cfg.seq_writable_ports = i_configure_read_seq_ports_default(); /* default value */ if ( !xmms_cfg_read_int( cfgfile , "amidi-plug" , "mixer_card_id" , &amidiplug_cfg.mixer_card_id ) ) amidiplug_cfg.mixer_card_id = 0; /* default value */ if ( !xmms_cfg_read_string( cfgfile , "amidi-plug" , "mixer_control_name" , &amidiplug_cfg.mixer_control_name ) ) amidiplug_cfg.mixer_control_name = g_strdup( "Synth" ); /* default value */ if ( !xmms_cfg_read_int( cfgfile , "amidi-plug" , "mixer_control_id" , &amidiplug_cfg.mixer_control_id ) ) amidiplug_cfg.mixer_control_id = 0; /* default value */ if ( !xmms_cfg_read_int( cfgfile , "amidi-plug" , "length_precalc_enable" , &amidiplug_cfg.length_precalc_enable ) ) amidiplug_cfg.length_precalc_enable = 0; /* default value */ xmms_cfg_free(cfgfile); } } void i_configure_cfg_save( void ) { ConfigFile *cfgfile; cfgfile = xmms_cfg_open_default_file(); if (!cfgfile) cfgfile = xmms_cfg_new(); xmms_cfg_write_string( cfgfile , "amidi-plug" , "writable_ports" , amidiplug_cfg.seq_writable_ports ); xmms_cfg_write_int( cfgfile , "amidi-plug" , "mixer_card_id" , amidiplug_cfg.mixer_card_id ); xmms_cfg_write_string( cfgfile , "amidi-plug" , "mixer_control_name" , amidiplug_cfg.mixer_control_name ); xmms_cfg_write_int( cfgfile , "amidi-plug" , "mixer_control_id" , amidiplug_cfg.mixer_control_id ); xmms_cfg_write_int( cfgfile , "amidi-plug" , "length_precalc_enable" , amidiplug_cfg.length_precalc_enable ); xmms_cfg_write_default_file(cfgfile); xmms_cfg_free(cfgfile); }