]> lisas.de Git - terminatorX.git/blob - src/tX_midiin.cc
Fix preferences for UI colors.
[terminatorX.git] / src / tX_midiin.cc
1 /*
2   terminatorX - realtime audio scratching software
3   Copyright (C) 2002 Arthur Peters
4         
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9  
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14  
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  
18   File: tX_midiin.cc
19  
20   Description: Implements MIDI input to control turntable parameters.
21 */    
22
23 #include "tX_midiin.h"
24 #include "tX_vtt.h"
25 #include "tX_ui_interface.h"
26 #include "tX_ui_support.h"
27 #include "tX_dialog.h"
28 #include "tX_mastergui.h"
29
30 #ifdef USE_ALSA_MIDI_IN
31 #include "tX_global.h"
32 #include <iostream>
33 #include "tX_engine.h"
34
35 using namespace std;
36
37 static gboolean midi_callback(GIOChannel *source, GIOCondition condition, gpointer data) {
38         tX_midiin *midi=(tX_midiin *) data;
39         midi->check_event();
40         
41         return TRUE;
42 }
43
44 tX_midiin::tX_midiin()
45 {
46         is_open=false;
47         sp_to_learn=NULL;
48         learn_dialog=NULL;
49         
50         if (snd_seq_open(&ALSASeqHandle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
51                 tX_error("tX_midiin(): failed to open the default sequencer device.");
52                 return;
53         }
54         snd_seq_set_client_name(ALSASeqHandle, "terminatorX");
55         portid =
56                 snd_seq_create_simple_port(ALSASeqHandle,
57                                                                    "Control Input",
58                                                                    SND_SEQ_PORT_CAP_WRITE
59                                                                    | SND_SEQ_PORT_CAP_SUBS_WRITE,
60                                                                    SND_SEQ_PORT_TYPE_APPLICATION);
61         if (portid < 0) {
62                 tX_error("tX_midiin(): error creating sequencer port.");
63                 return;
64         }
65
66         snd_seq_nonblock( ALSASeqHandle, 1 );
67         
68         struct pollfd fds[32];
69         
70         int res=snd_seq_poll_descriptors (ALSASeqHandle, fds, 32, POLLIN);
71
72         if (res!=1) {
73                 tX_error("Failed to poll ALSA descriptors: %i.\n", res);
74         }
75         
76         GIOChannel *ioc=g_io_channel_unix_new(fds[0].fd);
77         g_io_add_watch(ioc, (GIOCondition)( G_IO_IN ), midi_callback, (gpointer) this);
78         g_io_channel_unref(ioc);
79         
80         is_open=true;
81
82         tX_debug("tX_midiin(): sequencer successfully opened."); 
83 }
84
85 tX_midiin::~tX_midiin()
86 {
87         if (is_open) {
88                 snd_seq_close(ALSASeqHandle);
89                 tX_debug("tX_midiin(): sequencer closed.");
90         }
91 }
92
93 int tX_midiin::check_event()
94 {
95         snd_seq_event_t *ev;
96                 
97         while( snd_seq_event_input(ALSASeqHandle, &ev) != -EAGAIN )
98         {
99
100                 //MidiEvent::type MessageType=MidiEvent::NONE;
101                 //int Volume=0,Note=0,EventDevice=0;
102                 tX_midievent event;
103                 event.is_noteon = false;
104                 bool event_usable = true;
105
106                 switch (ev->type) {
107                         case SND_SEQ_EVENT_CONTROLLER: 
108                                 event.type = tX_midievent::CC;
109                                 event.number = ev->data.control.param;
110                                 event.value = ev->data.control.value / 127.0;
111                                 event.channel = ev->data.control.channel;
112                                 break;
113                         case SND_SEQ_EVENT_PITCHBEND:
114                                 event.type = tX_midievent::PITCHBEND;
115                                 event.number = ev->data.control.param;
116                                 event.value = (ev->data.control.value + 8191.0) / 16382.0; // 127.0;
117                                 event.channel = ev->data.control.channel;
118                                 break;
119                         case SND_SEQ_EVENT_CONTROL14:
120                                 event.type = tX_midievent::CC14;
121                                 event.number = ev->data.control.param;
122                                 event.value = ev->data.control.value / 16383.0;
123                                 event.channel = ev->data.control.channel;
124                                 break;
125                         case SND_SEQ_EVENT_REGPARAM:
126                                 event.type = tX_midievent::RPN;
127                                 event.number = ev->data.control.param;
128                                 event.value = ev->data.control.value / 16383.0;
129                                 event.channel = ev->data.control.channel;
130                                 break;
131                         case SND_SEQ_EVENT_NONREGPARAM:
132                                 event.type = tX_midievent::NRPN;
133                                 event.number = ev->data.control.param;
134                                 event.value = ev->data.control.value / 16383.0;
135                                 event.channel = ev->data.control.channel;
136                                 break;                                          
137                         case SND_SEQ_EVENT_NOTEON:
138                                 event.type = tX_midievent::NOTE;
139                                 event.number = ev->data.note.note;
140                                 event.value = ev->data.note.velocity / 127.0;
141                                 event.channel = ev->data.note.channel;
142
143                                 event.is_noteon = true;
144                                 if( event.value == 0 )
145                                         event.is_noteon = false;
146                                 break;
147                         case SND_SEQ_EVENT_NOTEOFF: 
148                                 event.type = tX_midievent::NOTE;
149                                 event.number = ev->data.note.note;
150                                 event.value = ev->data.note.velocity / 127.0;
151                                 event.channel = ev->data.note.channel;
152                                 
153                                 event.is_noteon = false;
154                                 break;
155                         default:
156                                 event_usable = false;
157                 }
158
159                 snd_seq_free_event(ev);
160                 
161                 if( event_usable ) {
162                         if (event.channel<0 || event.channel>15) {
163                                 tX_error("tX_midiin::check_event(): invaild event channel %i.", event.channel);
164                                 return -1;
165                         }
166
167                         if (sp_to_learn) {
168                                 sp_to_learn->bound_midi_event=event;
169                                 sp_to_learn=NULL;
170                                 
171                                 if (learn_dialog) {
172                                         gtk_widget_destroy(learn_dialog);
173                                         learn_dialog=NULL;
174                                 }
175                         } else {
176                                 // This should be solved with a hash table. Possibly.
177                                 
178                                 list <tX_seqpar *> :: iterator sp;                      
179                                 
180                                 for (sp=tX_seqpar::all->begin(); sp!=tX_seqpar::all->end(); sp++) {
181                                         if ( (*sp)->bound_midi_event.type_matches (event) ) {
182                                                 (*sp)->handle_midi_input (event);
183                                         }
184                                 }
185                         }
186                         
187                         last_event = event;
188                 }
189
190         }
191         return 1;
192 }
193
194 void tX_midiin::configure_bindings( vtt_class* vtt )
195 {
196         list <tX_seqpar *> :: iterator sp;
197
198         GType types[3] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER };
199         GtkListStore* model = gtk_list_store_newv(3, types);
200         GtkTreeIter iter;
201         char tempstr[128];
202         
203         for (sp=tX_seqpar::all->begin(); sp!=tX_seqpar::all->end(); sp++) {
204                 if (((*sp)->is_mappable) && ((*sp)->vtt) == (void*) vtt) {
205                         
206                         snprintf( tempstr, sizeof(tempstr), "Type: %d, Number: %d, Channel: %d",
207                                           (*sp)->bound_midi_event.type, (*sp)->bound_midi_event.number,
208                                           (*sp)->bound_midi_event.channel );
209
210                         gtk_list_store_append( model, &iter );
211                         gtk_list_store_set( model, &iter,
212                                                                 0, (*sp)->get_name(),
213                                                                 1, tempstr,
214                                                                 2, (*sp),
215                                                                 -1 );
216                 }
217         }
218
219         // it will delete itself.
220         new midi_binding_gui(GTK_TREE_MODEL(model), this);
221 }
222
223 tX_midiin::midi_binding_gui::midi_binding_gui ( GtkTreeModel* _model, tX_midiin* _midi )
224         : model(_model), midi( _midi )
225 {
226         GtkWidget *hbox1;
227         GtkWidget *scrolledwindow1;
228         GtkWidget *vbox1;
229         GtkWidget *label1;
230         GtkWidget *frame1;
231         
232         window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
233         gtk_window_set_title (GTK_WINDOW (window), "Configure MIDI Bindings");
234         gtk_window_set_default_size(GTK_WINDOW(window), 600, 260);
235         
236         hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
237         gtk_widget_show (hbox1);
238         gtk_container_add (GTK_CONTAINER (window), hbox1);
239         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
240         
241         scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
242         gtk_widget_show (scrolledwindow1);
243         gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow1, TRUE, TRUE, 0);
244         
245         parameter_treeview = gtk_tree_view_new_with_model (model);
246         gtk_widget_show (parameter_treeview);
247         gtk_container_add (GTK_CONTAINER (scrolledwindow1), parameter_treeview);
248         
249         GtkCellRenderer   *renderer = gtk_cell_renderer_text_new ();
250         gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW( parameter_treeview ),
251                                                                                            -1, "Parameter", renderer,
252                                                                                            "text", 0,
253                                                                                            NULL );
254         gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW( parameter_treeview ),
255                                                                                            -1, "Event", renderer,
256                                                                                            "text", 1,
257                                                                                            NULL );
258         gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(parameter_treeview), TRUE );
259         
260         vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
261         gtk_widget_show (vbox1);
262         gtk_box_pack_start (GTK_BOX (hbox1), vbox1, FALSE, FALSE, 0);
263         
264         label1 = gtk_label_new ("Selected MIDI Event:");
265         gtk_widget_show (label1);
266         gtk_box_pack_start (GTK_BOX (vbox1), label1, FALSE, FALSE, 0);
267         gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_LEFT);
268         
269         frame1 = gtk_frame_new (NULL);
270         gtk_widget_show (frame1);
271         gtk_box_pack_start (GTK_BOX (vbox1), frame1, TRUE, TRUE, 0);
272         gtk_container_set_border_width (GTK_CONTAINER (frame1), 2);
273         gtk_frame_set_label_align (GTK_FRAME (frame1), 0, 0);
274         gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
275         
276         midi_event_info = gtk_label_new ("Use a MIDI thing to select it.");
277         gtk_widget_show (midi_event_info);
278         gtk_container_add (GTK_CONTAINER (frame1), midi_event_info);
279         gtk_label_set_justify (GTK_LABEL (midi_event_info), GTK_JUSTIFY_LEFT);
280         
281         bind_button = gtk_button_new_with_mnemonic ("Bind");
282         gtk_widget_show (bind_button);
283         gtk_box_pack_start (GTK_BOX (vbox1), bind_button, FALSE, FALSE, 0);
284         
285         GtkWidget* unbind_button = gtk_button_new_with_mnemonic ("Remove Binding");
286         gtk_widget_show (unbind_button);
287         gtk_box_pack_start (GTK_BOX (vbox1), unbind_button, FALSE, FALSE, 0);   
288         
289         GtkWidget* close_button = gtk_button_new_with_mnemonic ("Close");
290         gtk_widget_show (close_button);
291         gtk_box_pack_start (GTK_BOX (vbox1), close_button, FALSE, FALSE, 0);
292         
293         g_signal_connect(G_OBJECT(bind_button), "clicked", (GCallback) bind_clicked, (void *) this);
294         g_signal_connect(G_OBJECT(unbind_button), "clicked", (GCallback) unbind_clicked, (void *) this);        
295         g_signal_connect(G_OBJECT(close_button), "clicked", (GCallback) close_clicked, (void *) this);
296         g_signal_connect(G_OBJECT(window), "destroy", (GCallback) close_clicked, (void *) this);
297         
298         timer_tag = g_timeout_add( 100, (GSourceFunc) timer, (void *) this);
299         
300         gtk_widget_show_all( GTK_WIDGET( window ) );
301 }
302
303 void tX_midiin::midi_binding_gui::window_closed(GtkWidget *widget, gpointer _this )
304 {
305         tX_midiin::midi_binding_gui* this_ = (tX_midiin::midi_binding_gui*)_this;
306
307         delete this_;
308 }
309
310 void tX_midiin::midi_binding_gui::unbind_clicked( GtkButton *button, gpointer _this )
311 {
312         tX_midiin::midi_binding_gui* this_ = (tX_midiin::midi_binding_gui*)_this;
313         GtkTreeModel* model;
314         GtkTreeSelection* selection;
315         GtkTreeIter iter;
316         char tmpstr[128];
317         tX_seqpar* param;
318
319         selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(this_->parameter_treeview) );
320         
321         if (gtk_tree_selection_get_selected( selection, &model, &iter)) {
322                 gtk_tree_model_get( model, &iter, 2, &param, -1 );
323                 
324                 param->bound_midi_event.type=tX_midievent::NONE;
325                 param->bound_midi_event.number=0;
326                 param->bound_midi_event.channel=0;
327                 
328                 snprintf( tmpstr, sizeof(tmpstr), "Type: %d, Number: %d, Channel: %d",
329                                         param->bound_midi_event.type, param->bound_midi_event.number,
330                                         param->bound_midi_event.channel );
331
332                 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, param->get_name(), 1, tmpstr, 2, param, -1 );
333         } else {
334                 tx_note("Please select a parameter to unbind first.", true, GTK_WINDOW(this_->window));
335         }
336 }
337
338
339 void tX_midiin::midi_binding_gui::bind_clicked( GtkButton *button, gpointer _this )
340 {
341         tX_midiin::midi_binding_gui* this_ = (tX_midiin::midi_binding_gui*)_this;
342         GtkTreeModel* model;
343         GtkTreeSelection* selection;
344         GtkTreeIter iter;
345         char tmpstr[128];
346         tX_seqpar* param;
347
348         selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(this_->parameter_treeview) );
349         
350         if (gtk_tree_selection_get_selected( selection, &model, &iter )) {
351                 gtk_tree_model_get( model, &iter, 2, &param, -1 );
352                 if (this_->last_event.type != tX_midievent::NONE) {
353                         param->bound_midi_event = this_->last_event;
354                         snprintf( tmpstr, sizeof(tmpstr), "Type: %d, Number: %d, Channel: %d",
355                                         param->bound_midi_event.type, param->bound_midi_event.number,
356                                         param->bound_midi_event.channel );
357                                         
358                         gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, param->get_name(), 1, tmpstr, 2, param, -1 );       
359                 } else {
360                         tx_note("Please send midi event to bind first.", true, GTK_WINDOW(this_->window));
361                 }
362         } else {
363                 tx_note("Please select a parameter to bind first.", true, GTK_WINDOW(this_->window));
364         }
365 }
366
367 void tX_midiin::midi_binding_gui::close_clicked( GtkButton *button, gpointer _this )
368 {
369         tX_midiin::midi_binding_gui* this_ = (tX_midiin::midi_binding_gui*)_this;
370         
371         gtk_widget_destroy( this_->window );
372 }
373
374 gint tX_midiin::midi_binding_gui::timer( gpointer _this )
375 {
376         tX_midiin::midi_binding_gui* this_ = (tX_midiin::midi_binding_gui*)_this;
377         tX_midievent tmpevent = this_->midi->get_last_event();
378
379         if( tmpevent.type_matches( this_->last_event ) )
380                 return TRUE;
381         
382         this_->last_event = tmpevent;
383         this_->last_event.clear_non_type();
384
385         snprintf( this_->tempstr, sizeof(this_->tempstr),
386                           "Type: %d (CC=%d, NOTE=%d)\nNumber: %d\nChannel: %d\n",
387                           this_->last_event.type, tX_midievent::CC, tX_midievent::NOTE,
388                           this_->last_event.number,
389                           this_->last_event.channel );
390
391         gtk_label_set_text( GTK_LABEL(this_->midi_event_info), this_->tempstr );
392
393         return TRUE;
394 }
395
396 tX_midiin::midi_binding_gui::~midi_binding_gui ()
397 {
398         g_source_remove( timer_tag );
399 }
400
401 void tX_midiin::set_midi_learn_sp(tX_seqpar *sp)
402 {
403         char buffer[512];
404         
405         if (learn_dialog) {
406                 gtk_widget_destroy(learn_dialog);
407         }
408         
409         sp_to_learn=sp;
410         
411         if (!sp_to_learn) return;
412         
413         learn_dialog=create_tX_midilearn();
414         tX_set_icon(learn_dialog);
415         GtkWidget *label=lookup_widget(learn_dialog, "midilabel");
416         
417         sprintf(buffer, "Learning MIDI mapping for <b>%s</b>\nfor turntable <b>%s</b>.\n\nWaiting for MIDI event...", sp->get_name(), sp->get_vtt_name());
418         gtk_label_set_markup(GTK_LABEL(label), buffer);
419         gtk_widget_show(learn_dialog);
420         
421         g_signal_connect(G_OBJECT(lookup_widget(learn_dialog, "cancel")), "clicked", G_CALLBACK (tX_midiin::midi_learn_cancel), this);
422         g_signal_connect(G_OBJECT(learn_dialog), "destroy", G_CALLBACK (tX_midiin::midi_learn_destroy), this);
423 }
424
425 void tX_midiin::cancel_midi_learn()
426 {
427         sp_to_learn=NULL;
428         learn_dialog=NULL;
429 }
430
431 gboolean tX_midiin::midi_learn_cancel(GtkWidget *widget, tX_midiin *midi)
432 {
433         midi->sp_to_learn=NULL;
434         gtk_widget_destroy(midi->learn_dialog);
435         
436         return FALSE;
437 }
438
439 gboolean tX_midiin::midi_learn_destroy(GtkWidget *widget, tX_midiin *midi)
440 {
441         midi->cancel_midi_learn();
442         
443         return FALSE;
444 }
445
446 void tX_midiin::store_connections(FILE *rc, char *indent) 
447 {
448         gzFile rz=NULL;
449         
450         tX_store("%s<midi_connections>\n", indent);
451
452         if (ALSASeqHandle != NULL) {
453                 strcat(indent, "\t");
454                 snd_seq_addr_t my_addr;
455                 my_addr.client=snd_seq_client_id(ALSASeqHandle);
456                 my_addr.port=portid;
457
458                 snd_seq_query_subscribe_t *subs;
459                 snd_seq_query_subscribe_alloca(&subs);
460                 snd_seq_query_subscribe_set_root(subs, &my_addr);
461                 snd_seq_query_subscribe_set_type(subs, SND_SEQ_QUERY_SUBS_WRITE);
462                 snd_seq_query_subscribe_set_index(subs, 0);
463         
464                 while (snd_seq_query_port_subscribers(ALSASeqHandle, subs) >= 0) {
465                         const snd_seq_addr_t *addr;
466                         addr = snd_seq_query_subscribe_get_addr(subs);
467                 
468                         tX_store("%s<link client=\"%i\" port=\"%i\"/>\n", indent, addr->client, addr->port);
469                         snd_seq_query_subscribe_set_index(subs, snd_seq_query_subscribe_get_index(subs) + 1);
470                 }       
471                 
472                 indent[strlen(indent)-1]=0;
473         }
474
475         tX_store("%s</midi_connections>\n", indent);    
476 }
477
478 void tX_midiin::restore_connections(xmlNodePtr node)
479 {
480         snd_seq_addr_t my_addr;
481         
482         if (ALSASeqHandle != NULL) {
483                 my_addr.client=snd_seq_client_id(ALSASeqHandle);
484                 my_addr.port=portid;
485                 
486                 if (xmlStrcmp(node->name, (xmlChar *) "midi_connections")==0) {
487                         for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
488                                 if (cur->type == XML_ELEMENT_NODE) {
489                                         if (xmlStrcmp(cur->name, (xmlChar *) "link")==0) {
490                                                 char *buffer;
491                                                 int client=-1;
492                                                 int port=-1;
493                                                 
494                                                 buffer=(char *) xmlGetProp(cur, (xmlChar *) "client");
495                                                 if (buffer) {
496                                                         sscanf(buffer, "%i", &client);
497                                                 }
498                                                 
499                                                 buffer=(char *) xmlGetProp(cur, (xmlChar *) "port");
500                                                 if (buffer) {
501                                                         sscanf(buffer, "%i", &port);
502                                                 }
503                                                 
504                                                 if ((port>=0) && (client>=0)) {
505                                                         snd_seq_addr_t sender_addr;
506                                                         sender_addr.client=client;
507                                                         sender_addr.port=port;
508                                                         
509                                                         snd_seq_port_subscribe_t *subs;
510                                                         snd_seq_port_subscribe_alloca(&subs);
511                                                         snd_seq_port_subscribe_set_sender(subs, &sender_addr);
512                                                         snd_seq_port_subscribe_set_dest(subs, &my_addr);
513         
514                                                         if (snd_seq_subscribe_port(ALSASeqHandle, subs) < 0) {
515                                                                 tX_error("tX_midiin::restore_connections() -> failed to connect to: %d:%d.", port, client);
516                                                         }
517                                                 } else {
518                                                         tX_error("tX_midiin::restore_connections() -> invalid port: %d:%d.", port, client);
519                                                 }
520                                                 
521                                         } else {
522                                                 tX_error("tX_midiin::restore_connections() -> invalid element: %s.", cur->name);
523                                         }
524                                 }
525                         }
526                 } else {
527                         tX_error("tX_midiin::restore_connections() -> invalid XML element.");
528                 }
529         } else {
530                 tX_error("tX_midiin::restore_connections() -> Couldn't get ALSA sequencer handle - snd-seq module not loaded?.");
531         }
532 }
533
534 extern "C" {
535         void tX_midiin_store_connections(FILE *rc, char *indent);
536         void tX_midiin_restore_connections(xmlNodePtr node);
537 };
538
539 void tX_midiin_store_connections(FILE *rc, char *indent) 
540 {
541         tX_engine::get_instance()->get_midi()->store_connections(rc, indent);
542 }
543
544 void tX_midiin_restore_connections(xmlNodePtr node) 
545 {
546         tX_engine::get_instance()->get_midi()->restore_connections(node);
547 }
548
549 static inline void cc_map(tX_seqpar *sp, int channel, int number) {
550         if (sp->bound_midi_event.type==tX_midievent::NONE) {
551                 sp->bound_midi_event.type=tX_midievent::CC;
552                 sp->bound_midi_event.channel=channel;
553                 sp->bound_midi_event.number=number;
554                 sp->reset_upper_midi_bound();
555                 sp->reset_lower_midi_bound();
556         }
557 }
558
559 static inline void cc_note(tX_seqpar *sp, int channel, int number) {
560         if (sp->bound_midi_event.type==tX_midievent::NONE) {
561                 sp->bound_midi_event.type=tX_midievent::NOTE;
562                 sp->bound_midi_event.channel=channel;
563                 sp->bound_midi_event.number=number;
564                 sp->reset_upper_midi_bound();
565                 sp->reset_lower_midi_bound();
566         }
567 }
568
569 void tX_midiin::auto_assign_midi_mappings(GtkWidget *widget, gpointer dummy)
570 {
571         std::list<vtt_class *>::iterator vtt;
572         int ctr=0;
573         
574 /*      if (dummy) {
575                 GtkWidget *dialog=gtk_message_dialog_new(GTK_WINDOW(main_window), 
576                 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO,
577                 "Assigning the default mappings will overwrite existing MIDI mappings. OK, to overwrite existing MIDI mappings?");
578                 
579                 int res=gtk_dialog_run(GTK_DIALOG(dialog));
580                 gtk_widget_destroy(dialog);
581                         
582                 if (res!=GTK_RESPONSE_YES) {
583                         return;
584                 }               
585         } */
586         
587         /* Works on my hardware :) */
588         cc_map(&sp_master_volume, 0, 28);
589         cc_map(&sp_master_volume, 0, 29);       
590         
591         for (vtt=vtt_class::main_list.begin(); (vtt!=vtt_class::main_list.end()) && (ctr<16); vtt++, ctr++) {
592                 /* These are pretty standard... */
593                 cc_map((&(*vtt)->sp_volume),            ctr, 07);
594                 cc_map((&(*vtt)->sp_pan),                       ctr, 10);
595                 cc_map((&(*vtt)->sp_lp_freq),           ctr, 13);
596                 cc_map((&(*vtt)->sp_lp_reso),           ctr, 12);
597                 
598                 /* These are on "general purpose"... */
599                 cc_map((&(*vtt)->sp_lp_gain),           ctr, 16);
600                 cc_map((&(*vtt)->sp_speed),             ctr, 17);
601                 cc_map((&(*vtt)->sp_pitch),             ctr, 18);
602                 cc_map((&(*vtt)->sp_sync_cycles),       ctr, 19);
603                 
604                 /* Sound Controller 6-10 */
605                 cc_map((&(*vtt)->sp_ec_length),         ctr, 75);
606                 cc_map((&(*vtt)->sp_ec_feedback),       ctr, 76);
607                 cc_map((&(*vtt)->sp_ec_volume),         ctr, 77);
608                 cc_map((&(*vtt)->sp_ec_pan),            ctr, 78);
609                 
610                 /* The toggles mapped to notes... */
611                 cc_note((&(*vtt)->sp_trigger),          0, 60+ctr);
612                 cc_note((&(*vtt)->sp_sync_client),      1, 60+ctr);
613                 cc_note((&(*vtt)->sp_loop),             2, 60+ctr);
614                 cc_note((&(*vtt)->sp_lp_enable),        3, 60+ctr);
615                 cc_note((&(*vtt)->sp_ec_enable),        4, 60+ctr);
616                 cc_note((&(*vtt)->sp_mute),             5, 60+ctr);
617                 cc_note((&(*vtt)->sp_spin),             6, 60+ctr);
618         }
619 }
620
621 void tX_midiin::clear_midi_mappings(GtkWidget *widget, gpointer dummy)
622 {
623         std::list<tX_seqpar *>::iterator sp;
624         
625         if (dummy) {
626                 GtkWidget *dialog=gtk_message_dialog_new(GTK_WINDOW(main_window), 
627                 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO,
628                 "Really clear all current MIDI mappings?");
629                 
630                 int res=gtk_dialog_run(GTK_DIALOG(dialog));
631                 gtk_widget_destroy(dialog);
632                         
633                 if (res!=GTK_RESPONSE_YES) {
634                         return;
635                 }               
636         }
637         
638         for (sp=tX_seqpar::all->begin(); sp!=tX_seqpar::all->end(); sp++) {
639                 (*sp)->bound_midi_event.type=tX_midievent::NONE;
640                 (*sp)->bound_midi_event.channel=0;
641                 (*sp)->bound_midi_event.number=0;
642                 (*sp)->reset_upper_midi_bound();
643                 (*sp)->reset_lower_midi_bound();
644         }
645 }
646 #endif // USE_ALSA_MIDI_IN