Main Page | Alphabetical List | Class List | Directories | File List | Class Members | File Members

netmusic_receiver.cpp

Go to the documentation of this file.
00001 
00029 #include <sys/time.h>
00030 #include <netdb.h>
00031 #include <pthread.h>
00032 #include <sys/socket.h>
00033 #include <sys/types.h>
00034 #include <sys/wait.h>
00035 #include <sys/msg.h>
00036 #include <sys/ipc.h>
00037 #include <arpa/inet.h>
00038 #include <netinet/in.h>
00039 
00040 #include "include/Netmusic.hh"
00041 #include "include/Mini.hh"
00042 
00046 snd_seq_t* receiverSeqHandler = NULL;
00050 int npfd;
00054 struct pollfd* pfd;
00058 int portId;
00062 int mini;
00066 int midiPort;
00070 int miniPort;
00074 int startKey;
00078 int pgmChange = 1;
00082 int velocity = 127;
00086 int syncPort = 29998;
00090 pthread_t miniThread, midiThread, syncThread;
00091 
00092 
00093 //********************************************************************
00098 void handler(int signal)
00099 {
00100         if ( signal == SIGINT)
00101                 _exit(0); // kills the process and all the threads
00102 }
00103 
00104 //********************************************************************
00105 /*
00106  * \brief midiThread function
00107  * \param ptr empty pointer
00108  *
00109  * The midi_function is executed by the midi thread. This thread is generated
00110  * if mini==0. It receives messages from the sender, in form of
00111  * snd_seq_event_t values. They can be sent to the port directly.
00112  *
00113  */
00114 void *midi_function(void *ptr)
00115 {
00116         // welcome msg
00117   std::cout << "RECEIVER: MIDI Thread started..." << std::endl
00118         << std::endl << std::endl;
00119   
00120   // variables
00121   struct sockaddr_in senderAddr, receiverAddr;
00122   int sd, rc, n;
00123   snd_seq_event_t* ev = new snd_seq_event;
00124   
00125   // socket creation
00126         sd = socket(AF_INET, SOCK_DGRAM, 0);
00127         Netmusic::check_error(sd, "Error creating midi socket");
00128         // bind receiver
00129         receiverAddr.sin_family = AF_INET;
00130         receiverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00131         receiverAddr.sin_port = htons(midiPort);
00132         rc = bind(sd, (struct sockaddr *) &receiverAddr, sizeof(receiverAddr));
00133         Netmusic::check_error(rc, "Error binding midi to receiverAddr");
00134         
00135         // receive midi
00136         while(1)
00137         {
00138                 // read note
00139                 n = recvfrom(sd, ev, sizeof(snd_seq_event_t), 0,
00140                         (struct sockaddr *) &senderAddr, (socklen_t *)sizeof(receiverAddr));
00141                 
00142                 std::cout << DELIMITER << std::endl;
00143                 std::cout << "RECEIVER: Received ";
00144                         
00145                 if((*ev).type == SND_SEQ_EVENT_NOTEON )
00146                 {
00147                         if((*ev).data.note.velocity != 0)
00148                                 std::cout << "Note On:  " << (int)(*ev).data.note.note << std::endl;
00149                         else
00150                                 std::cout << "Note Off: " << (int)(*ev).data.note.note << std::endl;
00151                 }
00152                 else if((*ev).type == SND_SEQ_EVENT_NOTEOFF )
00153                         std::cout << "Note Off: " << (int)(*ev).data.note.note << std::endl;
00154                 else if((*ev).type == SND_SEQ_EVENT_PGMCHANGE )
00155                         std::cout << "Program Change: " <<  (int)(*ev).data.control.value << std::endl;
00156                         
00157                 // output event directly
00158                 snd_seq_ev_set_subs(ev);
00159                 snd_seq_ev_set_direct(ev);
00160                 snd_seq_ev_set_source(ev, portId);
00161                 snd_seq_event_output_direct(receiverSeqHandler, ev);
00162                 snd_seq_free_event(ev);
00163         }
00164   pthread_exit(NULL);
00165 }
00166 
00167 //********************************************************************
00177 void *mini_function(void *ptr)
00178 {
00179         // welcome msg
00180   std::cout << "RECEIVER: MINI Thread..." << std::endl;
00181         
00182         // variables
00183         struct sockaddr_in senderAddr, receiverAddr;
00184         int sd, rc, n;
00185         int* noteArray;
00186         char* firstRead = new char;
00187         mpz_t chordCode;
00188         mpz_init(chordCode);
00189         char* secondRead;
00190         int k, noteOff, readSize;
00191         
00192         // socket creation
00193         sd = socket(AF_INET, SOCK_DGRAM, 0);
00194         Netmusic::check_error(sd, "Error creating mini socket");
00195         // bind receiver
00196         receiverAddr.sin_family = AF_INET;
00197         receiverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00198         receiverAddr.sin_port = htons(miniPort);
00199         rc = bind(sd, (struct sockaddr *) &receiverAddr, sizeof(receiverAddr));
00200         Netmusic::check_error(rc, "Error binding mini to receiverAddr");
00201 
00202         // output MIDI Event PGM Change
00203         snd_seq_event_t* event = new snd_seq_event_t;
00204         snd_seq_ev_clear(event);
00205         snd_seq_ev_set_pgmchange(event, 0, pgmChange);
00206         snd_seq_ev_set_subs(event);
00207         snd_seq_ev_set_direct(event);
00208         snd_seq_ev_set_source(event, portId);
00209         snd_seq_event_output_direct(receiverSeqHandler, event);
00210         snd_seq_free_event(event);
00211         std::cout << "Send PGMChange" << std::endl;
00212 
00213         
00214         // receive mini words
00215         while(1)
00216         {
00217                 // read firstRead
00218                 n =recvfrom(sd, firstRead, (sizeof(char)), 0,
00219                         (struct sockaddr *) &senderAddr, (socklen_t *)sizeof(senderAddr));
00220                 std::cout << DELIMITER << std::endl;
00221                 std::cout << "RECEIVER: Received 1st read..." << std::endl;
00222 
00223                 // extract size, k, noteOff
00224                 Mini::extract_size(firstRead[0], &readSize);
00225 
00226                 // secondRead
00227                 secondRead = (char*)new char[readSize-1];
00228                 n = recvfrom(sd, secondRead, ((readSize-1)*sizeof(char)), 0,
00229                         (struct sockaddr *) &senderAddr, (socklen_t *)sizeof(senderAddr));
00230                 std::cout << "RECEIVER: Received 2nd read... " << std::endl << std::endl;
00231 
00232                 //extract value
00233                 char* miniWord = (char*)new char[readSize];
00234                 miniWord[0] = firstRead[0];
00235                 for(int i=1;i<readSize;i++)
00236                         miniWord[i] = secondRead[i-1];
00237                 Mini::print_mem( miniWord, readSize);
00238                 mpz_set_ui(chordCode,0);
00239                 Mini::bin_2_mpz(miniWord, &k, chordCode, &noteOff);
00240 
00241                 // convert to int array
00242                 noteArray = new int[k];
00243                 Mini::ksub_unrank(k, noteArray, chordCode);
00244 
00245                 // print results
00246                 gmp_printf(" rank:     %Zd\n", chordCode);
00247                 Mini::print_array(noteArray, k, startKey);
00248                 std::cout << " mpz_size: " << readSize << std::endl;
00249                 std::cout << " k:        " << k << std::endl;
00250                 std::cout << " noteOff:  " << noteOff << std::endl;
00251                 //mpz_clear(chordCode);
00252 
00253                 snd_seq_event_t* ev = new snd_seq_event_t;
00254                 
00255                 // read mini word noteOff, to check if it is a mini noteOn or off word
00256                 if(noteOff==0)
00257                 {
00258                         // generate noteOns
00259                         for(int i=0;i<k;i++)
00260                         {
00261                           snd_seq_ev_clear(ev);
00262                           snd_seq_ev_set_noteon(ev, 0, noteArray[i]+startKey, velocity);
00263                                 snd_seq_ev_set_subs(ev);
00264                                 snd_seq_ev_set_direct(ev);
00265                                 snd_seq_ev_set_source(ev, portId);
00266                                 snd_seq_event_output_direct(receiverSeqHandler, ev);
00267                                 std::cout << " output NOTE ON: " << (int)(*ev).data.note.note
00268                                         << std::endl;
00269                                 snd_seq_free_event(ev);
00270                         }
00271                 }
00272                 // MINI noteOffword
00273                 else if(noteOff==1)
00274                 {
00275                         // generate noteOffs
00276                         for(int i=0;i<k;i++)
00277                         {
00278                           snd_seq_ev_clear(ev);
00279                           snd_seq_ev_set_noteoff(ev, 0, noteArray[i]+startKey, velocity);
00280                                 snd_seq_ev_set_subs(ev);
00281                                 snd_seq_ev_set_direct(ev);
00282                                 snd_seq_ev_set_source(ev, portId);
00283                                 snd_seq_event_output_direct(receiverSeqHandler, ev);
00284                                 std::cout << " output NOTE OFF: " << (int)(*ev).data.note.note
00285                                         << std::endl;
00286                                 snd_seq_free_event(ev);
00287                         }
00288                 }
00289         }
00290         
00291         pthread_exit(NULL); 
00292 }
00293 
00294 //********************************************************************
00295 /*
00296  * \brief syncThread function
00297  * \param ptr empty pointer
00298  *
00299  * Function listens for input on the sync_socket. Then the values
00300  * are set, according to the received values.
00301  *
00302  */
00303 void *sync_function(void *ptr)
00304 {
00305         // variables
00306         int* arrayPointer = new int[4];
00307         struct sockaddr_in senderAddr, receiverAddr;
00308         int sd, rc, n;
00309 
00310         // socket creation
00311         sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00312         Netmusic::check_error(sd, "Error creating snyc socket");
00313         // bind receiver
00314         receiverAddr.sin_family = AF_INET;
00315         receiverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00316         receiverAddr.sin_port = htons(syncPort);
00317         rc = bind(sd, (struct sockaddr *) &receiverAddr, sizeof(receiverAddr));
00318         Netmusic::check_error(rc, "Error binding sync socket to receiverAddr");
00319         // receive message
00320         std::cout << DELIMITER << std::endl;
00321         std::cout << "Waiting on port "<< syncPort <<" for sync data from the sender..." << std::endl;
00322         n = recvfrom(sd, arrayPointer, (4*sizeof(int)), 0,
00323                 (struct sockaddr *) &senderAddr, (socklen_t *)sizeof(senderAddr));
00324         //      set parameters
00325         mini = arrayPointer[0];
00326         midiPort = arrayPointer[1];
00327         miniPort = arrayPointer[2];
00328         startKey = arrayPointer[3];
00329         std::cout << "Sync complete!" << std::endl;
00330         
00331         close(sd);
00332         
00333         // end thread
00334         pthread_exit(NULL);
00335 }
00336 
00337 //********************************************************************
00346 int main(int argc, char** argv)
00347 {
00348         signal(SIGINT, handler);
00349 
00350         int miniRet, midiRet, syncRet;
00351         
00352         // set arguments
00353         Netmusic::receiver_check_args(argc, argv, 
00354                 &syncPort, 
00355                 &pgmChange, &velocity);
00356 
00357         // set alsa
00358         receiverSeqHandler = Netmusic::receiver_open_seq(&portId);
00359         npfd = snd_seq_poll_descriptors_count(receiverSeqHandler, POLLOUT);
00360         pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
00361         snd_seq_poll_descriptors(receiverSeqHandler, pfd, npfd, POLLOUT);
00362         
00363         // print welcome message
00364         Netmusic::receiver_print_welcome_msg();
00365         
00366         // create sync thread
00367         syncRet = pthread_create( &syncThread, NULL, sync_function, NULL);
00368         // wait for syncThread
00369         pthread_join(syncThread, NULL);
00370         
00371         // print parameters
00372         Netmusic::receiver_print_param(
00373                 mini,
00374                 midiPort, miniPort, syncPort,
00375                 startKey, pgmChange, velocity);
00376         
00377         // create other threads
00378         if(mini==0)
00379                 midiRet = pthread_create( &midiThread, NULL, midi_function, NULL);
00380         if(mini==1)
00381                 miniRet = pthread_create( &miniThread, NULL, mini_function, NULL);
00382         
00383         if(mini==0)
00384                 pthread_join( midiThread, NULL);
00385         if(mini==1)
00386                 pthread_join( miniThread, NULL);
00387 
00388         return 0;
00389 }
00390 

Generated on Mon Jun 13 22:06:59 2005 for Netmusic by  doxygen 1.4.3