Making MIDI Mappings persistent - Alex
authorterminatorX <>
Mon, 2 Dec 2002 20:03:35 +0000 (20:03 +0000)
committerterminatorX <>
Mon, 2 Dec 2002 20:03:35 +0000 (20:03 +0000)
terminatorX/ChangeLog
terminatorX/THANKS
terminatorX/src/tX_audiodevice.cc
terminatorX/src/tX_global.h
terminatorX/src/tX_midiin.cc
terminatorX/src/tX_midiin.h
terminatorX/src/tX_seqpar.cc
terminatorX/src/tX_seqpar.h
terminatorX/src/tX_vtt.cc
terminatorX/src/tX_vttgui.cc

index 6ee2047151d775675f288462ed2777a8877fff93..70d4c162dc3b6f42b65ff5a70934cb5ea8a937ea 100644 (file)
@@ -3,9 +3,21 @@ All changes were done by me (Alexander K
 This is not a GNU-style ChangeLog but you sort of get the idea what was
 changed.
 
-[v3.74 - prerelase]
+[v3.80 - prerelease]
+- Reworked the mastergui for better usabilty and less space consumption, yes,
+  terminatorX now features a boring menubar - which helps using it on small
+  displays quite a bit, and should be easier to handle for first time users.
+- Implemented a suggestions from Darrick Servis <darrick@dcn.davis.ca.us> that
+  stops clipping in the mixer routine. The outgoing signal is now limited as it
+  should be, which improves the output quality for signals too loud
+  significantly.
+- MIDI mappings are now store with the (new) tX set files.
+- Applied a patch from Arthur Peters <amp@singingwizard.org> which brings
+  preliminary MIDI support to terminatorX. This is realized via the ALSA
+  sequencer interface, so in order for it to compile you have to have
+  the ALSA devel packages installed. ./configure will autodetect them.
 - Fixed a bug in XML serialization that dropped strings' contents.
-- You can now hit "F11" to turn fullscreen mode on off - this will help using
+- You can now hit "F11" to turn fullscreen mode on/off - this will help using
   terminatorX on small DJ laptops. Note that the key will have no effect in 
   scratch - hit it before you get that engine running.
 - terminatorX now stores set files as XML documents, too - so terminatorX has
@@ -26,7 +38,7 @@ changed.
   longer builds with gtk+ 1.2 - you have to upgrade to gtk+ Version 2 to be
   able to build terminatorX.
 - fixed a gcc 3.2 compilation bug - thanks to 
-  Adam Duck <duck@informatik.uni-frankfurt.de>
+  Adam Duck <duck@informatik.uni-frankfurt.de> and other reporters
 
 [v3.73]
 - Fixed a compilation bug ocurring on big endian systems only.
index 55b9d324f7d86c935da6001d2f5e07c20eadee1b..e8e678213e2568c3885ecac43dd0a9e0e6a55d03 100644 (file)
@@ -10,30 +10,42 @@ I'd like to thank:
 
 - All users who send feedback
 
-- Andy Lo A Foe <andy@alsa-project.org> for good tips, autoconf inspiration
-  and a really cool program: alsaplayer
-  (checkout: http://www.alsa-project.org/~andy/)
+In politically correct alphabetical order:
 
 - Adrian Reber <adrian@fht-esslingen.de> for being the *BEST* Linux 
   sysadmin ;), for numerous code contributions and the fabrication of
   terminatorX-rpms.
 
-- Paul Kellett <paul.kellett@maxim.abel.co.uk> for his lowpass filter published
-  in reso_lop.txt
-  (checkout: http://www.abel.co.uk/~maxim/)
+- Andy Lo A Foe <andy@alsa-project.org> for good tips, autoconf inspiration
+  and a really cool program: alsaplayer
+  (checkout: http://www.alsa-project.org/~andy/)
+
+- Arthur Peters <amp@singingwizard.org> for contributing the ALSA MIDI
+  support
+
+- Darrick Servis <darrick@dcn.davis.ca.us> for telling me to implement the 
+  Anti-Clip-Device (checkout his audio file library:
+  http://osalp.sourceforge.net)
 
 - Benno Senoner <sbenno@gardena.net> for his mmap() patch, all the low
   latency kernel work and tips
   (checkout: http://www.gardena.net/benno/linux/audio/) 
 
-- Michael Kahl <m.kahl@student.hu-berlin.de> for the cool MK II icon
+- Michael Kahl <m.kahl@student.hu-berlin.de> for the cool MK II icon that I
+  no longer use
+
+- Paul Kellett <paul.kellett@maxim.abel.co.uk> for his lowpass filter published
+  in reso_lop.txt
+  (checkout: http://www.abel.co.uk/~maxim/)
 
-- Robert Dale <rob@nb.net> for makeing his already gone 3DNow!-Header
+- Robert Dale <rob@nb.net> for making his already gone 3DNow!-Header
   temporarily available again
   
 - Scott C. Knight <scknight@indiana.edu> for helping me to get this thing
   running on big endian machines again.
 
+And:
+
 - Everybody who contributed scratches...
 
 - The LAD people for all the help and support
index 5f305d000f117295a0a4afb75d27b68e4c23fdff..5a042e18189be92988169d3b3215a1af05a989ac 100644 (file)
 #      include <unistd.h>
 #endif
 
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
 void tX_audiodevice :: init()
 {
        samples_per_buffer=0;
@@ -159,7 +163,11 @@ void tX_audiodevice_oss :: play(int16_t *buffer)
 #ifdef BIG_ENDIAN_MACHINE
        swapbuffer (buffer, samples_per_buffer);
 #endif
-       write(fd, buffer, blocksize);   
+       int res=write(fd, buffer, blocksize);   
+       if (res==-1) {
+               tX_error("failed to write to audiodevice: %s", strerror(errno));
+               exit(-1);
+       }
 }
 
 #endif //USE_OSS
index 4c89b12ea29b571e3b36ba529c265b97bb3f0f9f..b9a129ed48fe873999dd79d4777a09eb34e0e67d 100644 (file)
@@ -154,9 +154,9 @@ extern char *encode_xml(char *dest, const char *src);
 #define restore_string_ac(s, i, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {strcpy(i, (const char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); init; }}
 #define restore_bool_ac(s, i, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {if (xmlStrcmp(xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), (const xmlChar *) "true")==0) i=true; else i=false; init; }}
 
-#define restore_int_id(s, i, sp, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) { sscanf((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), "%i", &i); pid_attr=(char* ) xmlGetProp(cur, (xmlChar *) "id"); if (pid_attr) { sscanf(pid_attr, "%i",  &pid); sp.set_persistence_id(pid); } init; }}
-#define restore_float_id(s, i, sp, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if  (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {sscanf((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), "%lf", &dvalue); i=dvalue; pid_attr=(char* ) xmlGetProp(cur, (xmlChar *) "id"); if (pid_attr) { sscanf(pid_attr, "%i",  &pid); sp.set_persistence_id(pid); } init; }}
-#define restore_bool_id(s, i, sp, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {if (xmlStrcmp(xmlNodeListGetString(doc, cur->xmlChildrenNode, 1),  (const xmlChar *) "true")==0) i=true; else i=false; pid_attr=(char* ) xmlGetProp(cur,  (xmlChar *)"id"); if (pid_attr) { sscanf(pid_attr, "%i",  &pid); sp.set_persistence_id(pid); } init; }}
+//#define restore_int_id(s, i, sp, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) { sscanf((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), "%i", &i); pid_attr=(char* ) xmlGetProp(cur, (xmlChar *) "id"); if (pid_attr) { sscanf(pid_attr, "%i",  &pid); sp.set_persistence_id(pid); } init; }}
+//#define restore_float_id(s, i, sp, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if  (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {sscanf((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), "%lf", &dvalue); i=dvalue; pid_attr=(char* ) xmlGetProp(cur, (xmlChar *) "id"); if (pid_attr) { sscanf(pid_attr, "%i",  &pid); sp.set_persistence_id(pid); } init; }}
+//#define restore_bool_id(s, i, sp, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {if (xmlStrcmp(xmlNodeListGetString(doc, cur->xmlChildrenNode, 1),  (const xmlChar *) "true")==0) i=true; else i=false; pid_attr=(char* ) xmlGetProp(cur,  (xmlChar *)"id"); if (pid_attr) { sscanf(pid_attr, "%i",  &pid); sp.set_persistence_id(pid); } init; }}
 
 #define store_int(s, i); fprintf(rc, "%s<%s>%i</%s>\n", indent, s,(int) i, s);
 #define store_float(s, i); fprintf(rc, "%s<%s>%lf</%s>\n", indent, s,(double) i, s);
@@ -168,6 +168,14 @@ extern char *encode_xml(char *dest, const char *src);
 #define store_float_id(s, i, id); fprintf(rc, "%s<%s id=\"%i\">%lf</%s>\n", indent, s, id, (double) i, s);
 #define store_bool_id(s, i, id); fprintf(rc, "%s<%s id=\"%i\">%s</%s>\n", indent, s, id, i ? "true" : "false", s);
 
+#define store_int_sp(name, i, sp); { fprintf(rc, "%s<%s ", indent, name); sp.store_meta(rc); fprintf(rc, ">%i</%s>\n", (int) i, name); }
+#define store_float_sp(name, i, sp); { fprintf(rc, "%s<%s ", indent, name); sp.store_meta(rc); fprintf(rc, ">%lf</%s>\n", (double) i, name); }
+#define store_bool_sp(name, i, sp); { fprintf(rc, "%s<%s ", indent, name); sp.store_meta(rc); fprintf(rc, ">%s</%s>\n", i ? "true" : "false", name); }
+
+#define restore_int_id(s, i, sp, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) { sscanf((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), "%i", &i);  init; } sp.restore_meta(cur); }
+#define restore_float_id(s, i, sp, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if  (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {sscanf((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), "%lf", &dvalue); i=dvalue; init; } sp.restore_meta(cur);}
+#define restore_bool_id(s, i, sp, init); if ((!elementFound) && (!xmlStrcmp(cur->name, (const xmlChar *) s))) { elementFound=1; if (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {if (xmlStrcmp(xmlNodeListGetString(doc, cur->xmlChildrenNode, 1),  (const xmlChar *) "true")==0) i=true; else i=false; init; } sp.restore_meta(cur);}
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index d870f44e90e9080761de1714486e251df8cb73ea..d1d379a2a5ccec00485ac2e70ca3621ed6b0859f 100644 (file)
 
 using namespace std;
 
+/*
+ disabled
 void tX_midievent::print( const char* prefix ) const
 {
        cerr << prefix << ": channel=" << channel << ", type=" << type << ", number=" << number
                 << ", value=" << value << ", is_noteon=" << is_noteon << endl;          
 }
-
+*/
 
 tX_midiin::tX_midiin()
 {
@@ -43,7 +45,7 @@ tX_midiin::tX_midiin()
        int portid;
 
        if (snd_seq_open(&ALSASeqHandle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
-               tX_error("tx_midiin(): failed to open the default sequencer device.");
+               tX_error("tX_midiin(): failed to open the default sequencer device.");
                return;
        }
        snd_seq_set_client_name(ALSASeqHandle, "TerminatorX");
@@ -54,7 +56,7 @@ tX_midiin::tX_midiin()
                                                                   | SND_SEQ_PORT_CAP_SUBS_WRITE,
                                                                   SND_SEQ_PORT_TYPE_APPLICATION);
        if (portid < 0) {
-               cerr << "Error creating sequencer port." << endl;
+               tX_error("tX_midiin(): error creating sequencer port.");
                return;
        }
 
index 54febe3fd3382e004e4b6443761bcd7da27f0c22..903550b954747c6fa86cc922ccc2f6524c77c50b 100644 (file)
 #ifndef _tx_midiin_h
 #define _tx_midiin_h 1
 
-#include <config.h>
-#ifdef USE_ALSA_MIDI_IN
-
-#include <alsa/asoundlib.h>
-#include <gtk/gtk.h>
-
 class vtt_class;
 
 class tX_midievent
@@ -58,10 +52,17 @@ class tX_midievent
                value = 0;
                is_noteon = false;
        }
-
-       void print( const char* prefix ) const;
+       
+       /* not being used anyway */
+       // void print( const char* prefix ) const;
 };
 
+#include <config.h>
+#ifdef USE_ALSA_MIDI_IN
+
+#include <alsa/asoundlib.h>
+#include <gtk/gtk.h>
+
 class tX_midiin
 {
        snd_seq_t *ALSASeqHandle;
index ddd55c60e299341ffec754233fe4e0ba08967e10..833591155962519ae62151e7cc412bc18ae8f939 100644 (file)
@@ -254,6 +254,56 @@ char * tX_seqpar :: get_vtt_name()
         else return "Master Track";
 }
 
+void tX_seqpar :: restore_meta(xmlNodePtr node) {
+       char *buffer;
+       
+       buffer=(char *) xmlGetProp(node, (xmlChar *) "id");
+       if (buffer) { sscanf(buffer, "%i", &persistence_id); }
+       else { tX_error("no ID for seqpar %s", this->get_name()); }
+       
+       buffer=(char *) xmlGetProp(node, (xmlChar *) "midiType");
+       if (buffer) {
+               if (strcmp("cc", buffer)==0) {
+                       bound_midi_event.type=tX_midievent::CC;
+               } else if (strcmp("note", buffer)==0) {
+                       bound_midi_event.type=tX_midievent::NOTE;
+               } else if (strcmp("pitchbend", buffer)==0) {
+                       bound_midi_event.type=tX_midievent::PITCHBEND;
+               } else {
+                       tX_error("unknown midiType \"%s\" for seqpar %s", buffer, this->get_name());
+               }
+               
+               buffer=(char *) xmlGetProp(node, (xmlChar *) "midiChannel");
+               if (buffer) { sscanf(buffer, "%i", &bound_midi_event.channel); }
+               else { tX_error("no midiChannel for seqpar %s", this->get_name()); }
+                       
+               buffer=(char *) xmlGetProp(node, (xmlChar *) "midiNumber");
+               if (buffer) { sscanf(buffer, "%i", &bound_midi_event.number); }
+               else { tX_error("no midiNumber for seqpar %s", this->get_name()); }
+       } 
+       /* else: no MIDI init.... */
+}
+
+void tX_seqpar :: store_meta(FILE *output) {
+       char buffer[256];
+       
+       if (bound_midi_event.type!=tX_midievent::NONE) {
+               char *type;
+               
+               switch (bound_midi_event.type) {
+                       case tX_midievent::NOTE: type="note"; break;
+                       case tX_midievent::CC: type="cc"; break;
+                       case tX_midievent::PITCHBEND: type="pitchbend"; break;
+                       default: type="error";
+               }
+               sprintf(buffer, "id=\"%i\" midiType=\"%s\" midiChannel=\"%i\" midiNumber=\"%i\"", persistence_id, type, bound_midi_event.channel, bound_midi_event.number);
+       } else {
+               sprintf(buffer, "id=\"%i\"", persistence_id);
+       }
+       fprintf(output, buffer);
+}
+
+
 const char * tX_seqpar :: get_name()
 {
         return "This string means trouble!";
index 311bda19d60cefdd84b597bd6546c72cc0a69c38..ec110d5044e3f6bac79d85ace0d22e8ad2a1eeb4 100644 (file)
@@ -26,6 +26,7 @@
 #include <gtk/gtk.h>
 #include "tX_extdial.h"
 #include "tX_midiin.h"
+#include "tX_global.h"
 
 #ifndef _tx_seqpar_h
 #define _tx_seqpar_h 1
@@ -33,6 +34,9 @@
 #define NO_MOUSE_MAPPING 0
 #define MOUSE_MAPPING_OK 1
 
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
 /* required for gcc>=3.0 */
 using namespace std;
 
@@ -42,9 +46,8 @@ class tX_seqpar
        static list <tX_seqpar *> all;
        void *vtt; /* have to make this void as tX_vtt.h includes this */
 
-#ifdef USE_ALSA_MIDI_IN
        tX_midievent bound_midi_event;
-#endif 
+
        protected:
        static list <tX_seqpar *> update;
        static pthread_mutex_t update_lock;
@@ -130,6 +133,8 @@ class tX_seqpar
        
        public:
        int is_mappable;        
+       void restore_meta(xmlNodePtr node);
+       void store_meta(FILE *output);
 };
 
 class tX_seqpar_update : public tX_seqpar
index ac9f0ec3b180fe2bb82ae337af897d953c1a4bc5..83570024665a60a99a581c80c2abff2d07aa7b45 100644 (file)
@@ -1581,26 +1581,26 @@ int  vtt_class :: save(FILE *rc, char *indent) {
        }
        store_bool("sync_master", is_sync_master);
        store_bool("autotrigger", autotrigger);
-       store_bool_id("loop", loop, sp_loop.get_persistence_id());
+       store_bool_sp("loop", loop, sp_loop);
 
-       store_bool_id("sync_client", is_sync_client, sp_sync_client.get_persistence_id());
-       store_int_id("sync_cycles", sync_cycles, sp_sync_cycles.get_persistence_id());
+       store_bool_sp("sync_client", is_sync_client, sp_sync_client);
+       store_int_sp("sync_cycles", sync_cycles, sp_sync_cycles);
 
-       store_float_id("volume", rel_volume, sp_volume.get_persistence_id());
-       store_float_id("pitch", rel_pitch, sp_pitch.get_persistence_id());      
-       store_bool_id("mute", mute, sp_mute.get_persistence_id());
-       store_float_id("pan", pan, sp_pan.get_persistence_id());
+       store_float_sp("volume", rel_volume, sp_volume);
+       store_float_sp("pitch", rel_pitch, sp_pitch);   
+       store_bool_sp("mute", mute, sp_mute);
+       store_float_sp("pan", pan, sp_pan);
        
-       store_bool_id("lowpass_enable", lp_enable, sp_lp_enable.get_persistence_id());
-       store_float_id("lowpass_gain", lp_gain, sp_lp_gain.get_persistence_id());
-       store_float_id("lowpass_reso", lp_reso, sp_lp_reso.get_persistence_id());
-       store_float_id("lowpass_freq", lp_freq, sp_lp_freq.get_persistence_id());
+       store_bool_sp("lowpass_enable", lp_enable, sp_lp_enable);
+       store_float_sp("lowpass_gain", lp_gain, sp_lp_gain);
+       store_float_sp("lowpass_reso", lp_reso, sp_lp_reso);
+       store_float_sp("lowpass_freq", lp_freq, sp_lp_freq);
 
-       store_bool_id("echo_enable", ec_enable, sp_ec_enable.get_persistence_id());
-       store_float_id("echo_length", ec_length, sp_ec_length.get_persistence_id());
-       store_float_id("echo_feedback", ec_feedback, sp_ec_feedback.get_persistence_id());
-       store_float_id("echo_pan", ec_pan, sp_ec_pan.get_persistence_id());
-       store_float_id("echo_volume", ec_volume, sp_ec_volume.get_persistence_id());
+       store_bool_sp("echo_enable", ec_enable, sp_ec_enable);
+       store_float_sp("echo_length", ec_length, sp_ec_length);
+       store_float_sp("echo_feedback", ec_feedback, sp_ec_feedback);
+       store_float_sp("echo_pan", ec_pan, sp_ec_pan);
+       store_float_sp("echo_volume", ec_volume, sp_ec_volume);
        
        store_id("speed", sp_speed.get_persistence_id());
        store_id("trigger", sp_trigger.get_persistence_id());
@@ -1655,8 +1655,8 @@ int  vtt_class :: save_all(FILE* rc) {
 
        //store_int(vtt_amount); obsolete
 
-       store_float_id("master_volume", master_volume, sp_master_volume.get_persistence_id());
-       store_float_id("master_pitch", globals.pitch, sp_master_pitch.get_persistence_id());
+       store_float_sp("master_volume", master_volume, sp_master_volume);
+       store_float_sp("master_pitch", globals.pitch, sp_master_pitch);
 
        for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
                res+=(*vtt)->save(rc, indent);
index e4caaf2815da676b2194578567365b8478c27182..4870ec1a2987d5ee17566ee4eb1f2b025cd59c22 100644 (file)
@@ -1351,6 +1351,15 @@ void vg_init_all_non_seqpars()
 f_prec gui_get_audio_x_zoom(vtt_class *vtt) {
        return gtk_tx_get_zoom(GTK_TX(vtt->gui.display));
 }
+
+int vttgui_zoom_depth=0;
+
 extern void gui_set_audio_x_zoom(vtt_class *vtt, f_prec value) {
-       gtk_tx_set_zoom(GTK_TX(vtt->gui.display), value);
+       if (vttgui_zoom_depth==0) {
+               vttgui_zoom_depth=1;
+               gtk_range_set_value(GTK_RANGE(vtt->gui.zoom), value);
+               vttgui_zoom_depth=0;
+       } else {
+               gtk_tx_set_zoom(GTK_TX(vtt->gui.display), value);
+       }
 }