Hi,

I have made a small program to read out MIDI commands for my Numark iDJLive II,
DJ mixer (USB).  I got rid of all my Apple software on Apple Hardware and there
I had used Algoriddim DJ Pro software to take commands from this mixer.

I pretty well made a crossfader and menu out of curses to make something like
it and did some reverse engineering to get the controls for the MIDI output
of the iDJLive II equipment.  Granted not everyone has this hardware so I'm
trying my best to explain what I'm doing by giving the source code of this.

Basically the program works with 2 childs, where one child is the foreground
and does the curses and input output to the mixer and the other child waits
for commands passed to it via a shared memory (mmap).  I can't manage to
get it to make a sound when I select a song on the right play pad (#2), the
worst I hear is just a small pop of the speakers and then silence so I'm
doing something wrong.  Let me explain the program lines and then I'll paste
the program itself maybe someone who is experienced with music and sndio can
help me a little?

lines
263-282 - set up the mmap's for 100 MB each (this is both sides of the cross
                fader)
283 - is where it forks and the child continues on to waiting instructions to
        play what's in the mmap

299 - indicates where I'M having some problems feeding data to sio_setpar()
        the data stems from data gotten through getheader() which parses
        WAV files and placed at offset 2 on the mmap.

The action at this point is really in the child and I don't know what I'm
doing wrong so lines 283 through 340 which is in a continuous loop.  Obviously
the program isn't finished but I was hoping I'd pad out the rest when I'd get
something playing on #2 at least.

If you do have this equipment and start it, wiggle the crossfader a little for
it to flash the leds for a while and then it will list any .WAV's to be selected
with the "push" button, the "browse" buttons will select the songs of which 
only #2 is currently programmed to do anything.

If I get this equipment working, I have another DJ mixer which is more portable
that has different MIDI commands that I still need to sit down on and figure
out.  But I figured I'd make one work first before working on the other.

Thanks for any hints regarding the playing of the WAV, the program follows, it
gets built with:

cc -g -o numark numark.c -lsndio -lcurses

Regards,
-peter

     1  /* 
     2   * Copyright (c) 2020 Peter J. Philipp
     3   * All rights reserved.
     4   *
     5   * Redistribution and use in source and binary forms, with or without
     6   * modification, are permitted provided that the following conditions
     7   * are met:
     8   * 1. Redistributions of source code must retain the above copyright
     9   *    notice, this list of conditions and the following disclaimer.
    10   * 2. Redistributions in binary form must reproduce the above copyright
    11   *    notice, this list of conditions and the following disclaimer in 
the
    12   *    documentation and/or other materials provided with the 
distribution.
    13   * 3. The name of the author may not be used to endorse or promote 
products
    14   *    derived from this software without specific prior written 
permission
    15   *
    16   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    17   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES
    18   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED.
    19   * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    20   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT
    21   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 
USE,
    22   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    23   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    24   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
USE OF
    25   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    26   * 
    27   */
    28  
    29  #include <sys/param.h>
    30  #include <sys/select.h>
    31  #include <sys/mman.h>
    32  
    33  #include <dirent.h>
    34  #include <unistd.h>
    35  #include <fcntl.h>
    36  #include <stdio.h>
    37  #include <stdlib.h>
    38  #include <string.h>
    39  
    40  #include <ncurses.h>
    41  #include <sndio.h>
    42  #include <signal.h>
    43  
    44  
    45  
    46  
    47  
    48  #define INQUIRESTRING   "\xF0\x7E\x00\x06\x01\xF7" /* MMC device 
enquiry */
    49  #define INQUIRESTRINGLEN        6
    50  
    51  #define HUNDREDMB       (100 * 1024 * 1024)
    52  
    53  #define MIDI_NOTEON     0x90
    54  #define MIDI_NOTEOFF    0x80
    55  
    56  #define BUTTON_DOWN     0x90
    57  #define BUTTON_UP       0x80
    58  #define FADER           0xb0
    59  
    60  #define NUMARK_DEVICE_2E_LEFTVOLUME             0x8
    61  #define NUMARK_DEVICE_2E_RIGHTVOLUME            0x9
    62  #define NUMARK_DEVICE_2E_CROSSFADER             0xA
    63  #define NUMARK_DEVICE_2E_LEFTPITCH              0xD
    64  #define NUMARK_DEVICE_2E_RIGHTPITCH             0xE
    65  #define NUMARK_DEVICE_2E_LEFTTREBLE             0x10
    66  #define NUMARK_DEVICE_2E_RIGHTTREBLE            0x11
    67  #define NUMARK_DEVICE_2E_LEFTBASS               0x14
    68  #define NUMARK_DEVICE_2E_RIGHTBASS              0x15
    69  #define NUMARK_DEVICE_2E_MASTERVOLUME           0x17
    70  #define NUMARK_DEVICE_2E_RIGHTWHEEL             0x18
    71  #define NUMARK_DEVICE_2E_LEFTWHEEL              0x19
    72  #define NUMARK_DEVICE_2E_BROWSE                 0x1A
    73  #define NUMARK_DEVICE_2E_LEFTCUE                0x33
    74  #define NUMARK_DEVICE_2E_RIGHTLOAD              0x34
    75  #define NUMARK_DEVICE_2E_LEFTRETURNTOCUE        0x3B
    76  #define NUMARK_DEVICE_2E_RIGHTCUE               0x3C
    77  #define NUMARK_DEVICE_2E_LEFTSYNC               0x40
    78  #define NUMARK_DEVICE_2E_RIGHTRETURNTOCUE       0x42
    79  #define NUMARK_DEVICE_2E_LEFTPITCHBENDPLUS      0x43
    80  #define NUMARK_DEVICE_2E_LEFTPITCHBENDMINUS     0x44
    81  #define NUMARK_DEVICE_2E_RIGHTPITCHBENDPLUS     0x45
    82  #define NUMARK_DEVICE_2E_RIGHTPITCHBENDMINUS    0x46
    83  #define NUMARK_DEVICE_2E_RIGHTSYNC              0x47
    84  #define NUMARK_DEVICE_2E_SCRATCH                0x48
    85  #define NUMARK_DEVICE_2E_LEFTPLAY               0x4A
    86  #define NUMARK_DEVICE_2E_LEFTLOAD               0x4B
    87  #define NUMARK_DEVICE_2E_RIGHTPLAY              0x4C
    88  #define NUMARK_DEVICE_2E_LEFTWHEELTAP           0x4D
    89  #define NUMARK_DEVICE_2E_RIGHTWHEELTAP          0x4E
    90  #define NUMARK_DEVICE_2E_BROWSEPUSHBUTTON       0x4F
    91  
    92  struct midi_reply {
    93          u_int8_t nrm;           /* non real-time message */
    94          u_int8_t channel;       /* channel to inquire */
    95          u_int8_t inquiry;       /* inquiry message */
    96          u_int8_t response;      /* inquiry response */
    97  };
    98  
    99  struct midi_manuf {
   100          u_int8_t manufacturer[3];
   101          u_int8_t product;
   102  };
   103  
   104  struct midi_len {
   105          u_int8_t hibyte;
   106          u_int8_t lobyte;
   107  };
   108  
   109  struct reply {
   110          uint32_t version;
   111          uint8_t  devid;
   112          uint32_t serial;
   113          char manufacturer[16];
   114  };
   115  
   116  struct mywav {
   117          char *map;
   118          size_t size;
   119          size_t songsize;
   120          off_t pos;
   121  };
   122  
   123  struct wff {
   124          char id[4];     /* RIFF */
   125          uint32_t chunksize;     /* chunk size */
   126          char waveid[4];         /* wave id */
   127  } waveheader;
   128  
   129  struct chk {
   130          char chunkid[4];        /* "fmt " */
   131          uint32_t cksize;        /* chunk size 16, 18, or 40 */
   132  } chunkheader;
   133  
   134  struct fmt16 {
   135          char chunkid[4];        /* "fmt " */
   136          uint32_t cksize;        /* chunk size 16, 18, or 40 */
   137          uint16_t fcode;         /* format code */
   138          uint16_t channels;      /* number of channels */
   139          uint32_t sps;           /* samples per second */
   140          uint32_t datarate;      /* datarate */
   141          uint16_t datablock;     /* data block size */
   142          uint16_t bps;           /* bits per sample */
   143  
   144          uint16_t size;          /* size of extension */
   145          uint16_t validbits;     /* valid # of bits */
   146          uint16_t channelmask;   /* mask of speaker position */
   147          char subformat[16];     /* GUID */
   148  } format16;
   149  
   150  struct mywaveheader {
   151          struct wff waveheader;
   152          struct chk chunkheader;
   153          struct fmt16 formathdr;
   154          struct chk filler;
   155          struct chk data;
   156  
   157          uint32_t dataoffset;
   158  };
   159  
   160  struct numarktab {
   161          int id;
   162          char *string;
   163  } myntab[] = { { NUMARK_DEVICE_2E_LEFTVOLUME, "left volume" },
   164          { NUMARK_DEVICE_2E_RIGHTVOLUME, "right volume" },
   165          { NUMARK_DEVICE_2E_CROSSFADER, "crossfader" },
   166          { NUMARK_DEVICE_2E_LEFTPITCH, "left pitch" },
   167          { NUMARK_DEVICE_2E_RIGHTPITCH, "right pitch" },
   168          { NUMARK_DEVICE_2E_LEFTTREBLE,  "left treble" },
   169          { NUMARK_DEVICE_2E_RIGHTTREBLE, "right treble" },
   170          { NUMARK_DEVICE_2E_LEFTBASS, "left bass" },
   171          { NUMARK_DEVICE_2E_RIGHTBASS, "right bass" },
   172          { NUMARK_DEVICE_2E_MASTERVOLUME, "master volume" },
   173          { NUMARK_DEVICE_2E_RIGHTWHEEL, "right wheel" },
   174          { NUMARK_DEVICE_2E_LEFTWHEEL, "left wheel" },
   175          { NUMARK_DEVICE_2E_BROWSE, "browse" },
   176          { NUMARK_DEVICE_2E_LEFTCUE, "left cue" },
   177          { NUMARK_DEVICE_2E_RIGHTLOAD, "right load" },
   178          { NUMARK_DEVICE_2E_LEFTRETURNTOCUE, "left return to cue" },
   179          { NUMARK_DEVICE_2E_RIGHTCUE, "right cue" },
   180          { NUMARK_DEVICE_2E_LEFTSYNC, "left sync" },
   181          { NUMARK_DEVICE_2E_RIGHTRETURNTOCUE, "right return to cue" },
   182          { NUMARK_DEVICE_2E_LEFTPITCHBENDPLUS, "left pitch bend plus" },
   183          { NUMARK_DEVICE_2E_LEFTPITCHBENDMINUS, "left pitch bend minus" 
},
   184          { NUMARK_DEVICE_2E_RIGHTPITCHBENDPLUS, "right pitch bend plus" 
},
   185          { NUMARK_DEVICE_2E_RIGHTPITCHBENDMINUS, "right pitch bend 
minus" },
   186          { NUMARK_DEVICE_2E_RIGHTSYNC, "right sync" },
   187          { NUMARK_DEVICE_2E_SCRATCH, "scratch" },
   188          { NUMARK_DEVICE_2E_LEFTPLAY, "left play" },
   189          { NUMARK_DEVICE_2E_LEFTLOAD, "left load" },
   190          { NUMARK_DEVICE_2E_RIGHTPLAY, "right play" },
   191          { NUMARK_DEVICE_2E_LEFTWHEELTAP, "left wheel tap" },
   192          { NUMARK_DEVICE_2E_RIGHTWHEELTAP, "right wheel tap" },
   193          { NUMARK_DEVICE_2E_BROWSEPUSHBUTTON, "browse push button" }};
   194  
   195  
   196  /* prototypes */
   197  int probe_midi(int, struct midi_manuf *);
   198  char * numark_controllid(u_int8_t id);
   199  int update_fader(WINDOW *crossfader, u_int8_t command);
   200  int write_songs(WINDOW *, int);
   201  char * get_songs(int selected);
   202  struct mywaveheader * getheader(int);
   203  void set_led_on(int midi, int deviceid);
   204  void set_led_off(int midi, int deviceid);
   205  
   206  /* defines */
   207  WINDOW *mixerwindow;
   208  
   209  int
   210  main(void)
   211  {
   212          char buf[512];
   213          char *song;
   214  
   215          struct mywaveheader *waveheader, *lwavhdr, *rwavhdr;
   216          struct mywav leftwav, rightwav;
   217          struct midi_manuf mm;
   218          struct sio_hdl *hdl;
   219          struct sio_par spar;
   220  
   221          int midi;
   222          int sel;
   223          int i, fd;
   224          int len;
   225          int faderpos = 50;
   226          int leftvolume = 127;
   227          int rightvolume = 127;
   228          int selectedsong = 1;
   229          int rightplay = 0;
   230          int leftplay = 0;
   231          uint32_t *loffset, *roffset;
   232  
   233          
   234          fd_set rset;
   235          pid_t pid;
   236  
   237          u_int8_t command[3];
   238  
   239          WINDOW *crossfader, *songselect, *leftsong, *rightsong;
   240          off_t offset;
   241          
   242          initscr();
   243          cbreak();
   244          noecho();
   245  
   246          start_color();
   247  
   248          init_pair(COLOR_BLACK, COLOR_BLACK, 0);
   249          init_pair(COLOR_GREEN, COLOR_GREEN, 0);
   250          init_pair(COLOR_RED, COLOR_RED, 0);
   251  
   252          mixerwindow = newwin(23, 80, 0, 0);
   253          idlok(mixerwindow, TRUE);
   254          scrollok(mixerwindow, TRUE);
   255  
   256          wclear(mixerwindow);
   257          wrefresh(mixerwindow);
   258  
   259          wattrset(mixerwindow, COLOR_PAIR(COLOR_GREEN));
   260  
   261          /* start the program */
   262          
   263          leftwav.map = (char *)mmap(NULL, HUNDREDMB + 2 + sizeof(struct 
mywaveheader), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
   264          if (leftwav.map == MAP_FAILED) {
   265                  perror("mmap");
   266                  exit(1);
   267          }
   268          leftwav.size = HUNDREDMB;
   269          leftwav.map[0] = '*';
   270          leftwav.map[1] = 127;
   271          lwavhdr = (struct mywaveheader *)&leftwav.map[2];
   272  
   273          rightwav.map = (char *)mmap(NULL, HUNDREDMB + 2 + sizeof(struct 
mywaveheader), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
   274          if (rightwav.map == MAP_FAILED) {
   275                  perror("mmap");
   276                  exit(1);
   277          }
   278          rightwav.size = HUNDREDMB;
   279          rightwav.map[0] = '*';
   280          rightwav.map[1] = 127;
   281          rwavhdr = (struct mywaveheader *)&rightwav.map[2];
   282  
   283          pid = fork();
   284          /* ze child */
   285          if (pid == 0) {
   286                  for (;;) {
   287                          while (rightwav.map[0] == '*')                  
   288                                  usleep(40);
   289  
   290                          hdl = sio_open("snd/0", SIO_PLAY, 0);   
   291                          if (hdl == NULL) {
   292                                  perror("sio_open");
   293                                  killpg(-1, SIGINT);
   294                          }
   295  
   296                          sio_initpar(&spar);
   297                          spar.rate =  rwavhdr->formathdr.datarate;
   298  #if 0
   299                          THIS IS THE PART WHERE I'M HAVING PROBLEMS
   300  
   301                          spar.rate = 44100;
   302                          spar.bits = 16;
   303                          spar.pchan = 2;
   304                          spar.appbufsz = 2048;
   305  #endif
   306                          spar.bits = rwavhdr->formathdr.bps;
   307                          spar.pchan = rwavhdr->formathdr.channels;
   308                          spar.appbufsz = 10240;
   309  
   310                          //wprintw(mixerwindow, "%d\n", spar.rate);
   311  
   312                          sio_setpar(hdl, &spar);
   313                          if (sio_getpar(hdl, &spar) == 0) {
   314                                  perror("sio_getpar");
   315                                  killpg(-1, SIGINT);
   316                          }
   317  
   318                          sio_start(hdl);
   319  
   320                          while (rightwav.map[0] == 'p') {
   321                                  int n;
   322  
   323                                  sio_setvol(hdl, SIO_MAXVOL);
   324                                  n = sio_write(hdl, 
&rightwav.map[rwavhdr->dataoffset], 10240);
   325                                  if (n == 0) {
   326                                          perror("sio_write");
   327                                          killpg(-1, SIGINT);
   328                                  }
   329                                  rwavhdr->dataoffset += 10240;
   330                                  if (rwavhdr->dataoffset >= 
rightwav.size) {
   331                                          rwavhdr->dataoffset = 0;
   332                                          break;
   333                                  }
   334  
   335                                  usleep(40);
   336                          }
   337                          
   338                          sio_close(hdl);
   339                  } /* for() */
   340          } /* if pid == 0 */
   341  
   342          wprintw(mixerwindow, "opening rmidi0\n");
   343          wrefresh(mixerwindow);
   344          midi = open("/dev/rmidi0", O_RDWR, 0);
   345  
   346          if (midi < 0) {
   347                  perror("midi");
   348                  exit(1);
   349          }
   350  
   351  
   352          if (probe_midi(midi, &mm) < 0) {
   353                  perror("probe_midi");
   354                  close(midi);
   355                  exit(1);
   356          }
   357  
   358          if (mm.manufacturer[0] != 0x00 || mm.manufacturer[1] != 0x1 ||
   359                  mm.manufacturer[2] != 0x3f || mm.product != 0x2e) {
   360                  wprintw(mixerwindow, "this is not a Numark iDJ Live 2 
product, exit.\n");
   361                  wrefresh(mixerwindow);
   362                  close(midi);
   363                  exit(1);
   364          }
   365  
   366          /* set up a crossfader menu */
   367  
   368          crossfader = newwin(3, 22, 20, 30);
   369          box(crossfader, '|', '-');
   370          
   371          wmove(crossfader, 1, 10);
   372          wprintw(crossfader, "||");
   373          wrefresh(crossfader);
   374  
   375  
   376          /* let's let the lights blink a little */
   377  
   378          wprintw(mixerwindow, "blinking lights...\n");
   379          wrefresh(mixerwindow);
   380          for (i = 0; i < 4; i++) {
   381                  set_led_on(midi, NUMARK_DEVICE_2E_LEFTPLAY);
   382                  usleep(350);
   383                  set_led_on(midi, NUMARK_DEVICE_2E_RIGHTPLAY);
   384                  usleep(350);
   385                  set_led_on(midi, NUMARK_DEVICE_2E_RIGHTSYNC);
   386                  usleep(350);
   387                  set_led_on(midi, NUMARK_DEVICE_2E_LEFTSYNC);
   388  
   389                  sleep(1);
   390  
   391                  set_led_off(midi, NUMARK_DEVICE_2E_LEFTPLAY);
   392                  usleep(350);
   393                  set_led_off(midi, NUMARK_DEVICE_2E_RIGHTPLAY);
   394                  usleep(350);
   395                  set_led_off(midi, NUMARK_DEVICE_2E_RIGHTSYNC);
   396                  usleep(350);
   397                  set_led_off(midi, NUMARK_DEVICE_2E_LEFTSYNC);
   398                  sleep(1);
   399          }
   400          wprintw(mixerwindow, "done blinking lights\n");
   401          wrefresh(mixerwindow);
   402                  
   403  
   404          wprintw(mixerwindow, "waiting for input from the device\n");
   405          wrefresh(mixerwindow);
   406  
   407          /* set up a songselect window */
   408          
   409          songselect = newwin(8, 30, 2, 25);
   410          box(songselect, '|', '-');
   411          selectedsong = write_songs(songselect, selectedsong);
   412          wrefresh(songselect);
   413  
   414          leftsong = newwin(10, 25, 0, 0);
   415          box(leftsong, '|', '-');
   416          wrefresh(leftsong);
   417          
   418          rightsong = newwin(10, 25, 0, 55);
   419          box(rightsong, '|', '-');
   420          wrefresh(rightsong);
   421  
   422          for (;;) {
   423                  FD_ZERO(&rset);
   424                  FD_SET(midi, &rset);
   425  
   426                  sel = select(midi + 1, &rset, NULL, NULL, NULL);
   427  
   428                  if (sel == -1) {
   429                          perror("select");
   430                          return (-1);
   431                  }
   432  
   433                  if (FD_ISSET(midi, &rset)) {
   434                          read(midi, command, 3);
   435  #ifdef DEBUG
   436                          switch ((u_int8_t)command[0]) {
   437                          case BUTTON_DOWN:
   438                                  wprintw(mixerwindow, "button down ");
   439                                  break;
   440                          case BUTTON_UP:
   441                                  wprintw(mixerwindow, "button up ");
   442                                  break;
   443                          case FADER:
   444                                  wprintw(mixerwindow, "POT or FADER ");
   445                                  break;
   446                          default:
   447                                  wprintw(mixerwindow, "unknown event 
%02x", (u_int8_t)buf[0] & 0xff);    
   448                                  break;
   449                          }
   450  
   451                          wprintw(mixerwindow, "controlid: %02x (%s)\n", 
command[1] & 0xff, numark_controllid((u_int8_t)command[1]));
   452  
   453  #endif
   454                          if (command[0] == FADER && command[1] == 
NUMARK_DEVICE_2E_CROSSFADER) { 
   455                                  
   456                                  faderpos = update_fader(crossfader, 
command[2]);
   457                          }
   458                          if (command[0] == FADER && command[1] == 
NUMARK_DEVICE_2E_BROWSE) {
   459                                  if (command[2] == 127)
   460                                          selectedsong++;
   461                                  else
   462                                          selectedsong--;
   463                                  
   464                                  selectedsong = write_songs(songselect, 
selectedsong);
   465                                  wrefresh(songselect);
   466                          }
   467                          if (command[0] == BUTTON_DOWN && command[1] == 
NUMARK_DEVICE_2E_LEFTLOAD) {
   468                                  wmove(leftsong, 1, 1);
   469                                  song = get_songs(selectedsong);
   470                                  fd = open(song, O_RDONLY, 0);
   471                                  if (fd < 0) {
   472                                          perror("open");
   473                                          exit(1);
   474                                  }
   475  
   476                                  waveheader = getheader(fd);
   477                                  if (waveheader == NULL) {
   478                                          perror("not a WAV file");
   479                                          exit(1); 
   480                                  }
   481  
   482                                  leftwav.pos = 2;
   483                                  offset = waveheader->dataoffset;
   484                                  lseek(fd, offset, SEEK_SET);
   485                                  
   486                                  /* write song to memory */
   487                                  while ((len = read(fd, buf, 
sizeof(buf))) > 0) {
   488                                          memcpy(buf, 
&leftwav.map[rightwav.pos], len);
   489                                          leftwav.pos += len;
   490                                          leftwav.size = rightwav.pos;
   491                                          
   492                                          if (leftwav.pos >= HUNDREDMB)
   493                                                  break;
   494                                  }
   495  
   496                                  close(fd);
   497                                  song[20] = '\0';
   498                                  wprintw(leftsong, "%s", song);
   499                                  wrefresh(leftsong);
   500                          }
   501                          if (command[0] == BUTTON_DOWN && command[1] == 
NUMARK_DEVICE_2E_RIGHTLOAD) {
   502                                  wmove(rightsong, 1, 1);
   503                                  song = get_songs(selectedsong);
   504  
   505                                  fd = open(song, O_RDONLY, 0);
   506                                  if (fd < 0) {
   507                                          perror("open");
   508                                          exit(1);
   509                                  }
   510  
   511                                  waveheader = getheader(fd);
   512                                  if (waveheader == NULL) {
   513                                          perror("not a WAV file");
   514                                          exit(1); 
   515                                  }
   516  
   517                                  rightwav.pos = 2;
   518                                  offset = waveheader->dataoffset;
   519                                  lseek(fd, offset, SEEK_SET);
   520                                  
   521                                  /* write song to memory */
   522                                  while ((len = read(fd, buf, 
sizeof(buf))) > 0) {
   523                                          memcpy(buf, 
&rightwav.map[rightwav.pos], len);
   524                                          rightwav.pos += len;
   525                                          rightwav.songsize = 
rightwav.pos;
   526                                          
   527                                          if (rightwav.pos >= HUNDREDMB)
   528                                                  break;
   529                                  }
   530  
   531                                  close(fd);
   532  
   533                                  memcpy(rwavhdr, waveheader, 
sizeof(struct mywaveheader));
   534                                  //rwavhdr->dataoffset = sizeof(struct 
mywaveheader) + 2;
   535                                  
   536  
   537                                  song[20] = '\0';
   538                                  wprintw(rightsong, "%s", song);
   539                                  wmove(rightsong, 2, 0);
   540                                  wprintw(rightsong, "%llu", 
rwavhdr->dataoffset);
   541                                  wrefresh(rightsong);
   542                          }
   543                          if (command[0] == BUTTON_DOWN && command[1] == 
NUMARK_DEVICE_2E_RIGHTPLAY) {
   544                                  if (rightplay == 0)
   545                                          rightplay = 1;
   546                                  else 
   547                                          rightplay = 0;
   548  
   549                                  if (rightplay) {
   550                                          rightwav.map[0] = 'p';
   551                                          set_led_on(midi, 
NUMARK_DEVICE_2E_RIGHTPLAY);
   552                                  } else {
   553                                          rightwav.map[0] = '*';
   554                                          set_led_off(midi, 
NUMARK_DEVICE_2E_RIGHTPLAY);
   555                                  }
   556                          }
   557                          wrefresh(mixerwindow);
   558                  } /* if */
   559          } /* for */
   560                  
   561          close(midi);
   562          exit(0);
   563  
   564  }
   565  
   566  
   567  
   568  int
   569  probe_midi(int midi, struct midi_manuf *manufacturer)
   570  {
   571          struct reply *rply;
   572          struct midi_reply *mr;
   573          struct midi_manuf *mm;
   574          struct midi_len *ml;
   575          struct timeval tv;
   576          
   577          u_char buf[512];
   578          char *inquire = INQUIRESTRING;
   579  
   580          int sel;
   581          int mlen, len;
   582          int i;
   583          int gotf7;
   584  
   585          fd_set rfdset;
   586  
   587          wprintw(mixerwindow, "now sending inquire string\n");
   588          wrefresh(mixerwindow);
   589          write(midi, inquire, INQUIRESTRINGLEN);
   590          wprintw(mixerwindow, "selecting for reponse\n");        
   591          wrefresh(mixerwindow);
   592          
   593          tv.tv_sec = 10;
   594          tv.tv_usec = 0;
   595  
   596          FD_ZERO(&rfdset);
   597          FD_SET(midi, &rfdset);
   598  
   599          sel = select(midi + 1, &rfdset, NULL, NULL, &tv);
   600  
   601          if (sel == -1) {
   602                  perror("select");
   603                  return (-1);
   604          }
   605  
   606          if (sel == 0) {
   607                  wprintw(mixerwindow, "no response for 10 seconds\n");
   608                  wrefresh(mixerwindow);
   609                  return (-1);
   610          }
   611  
   612          if (FD_ISSET(midi, &rfdset)) {
   613                  read(midi, buf, 1);
   614                  if ((uint8_t)buf[0] == 0xF0) {
   615                          if ((len = read(midi, buf, sizeof(*mr))) != 
sizeof(*mr)) {
   616                                  wprintw(mixerwindow, "expected %d bytes 
but %d came back\n", sizeof(*mr), len);
   617                                  wrefresh(mixerwindow);
   618                                  return (-1);
   619                          }
   620  
   621                          mr = (struct midi_reply *)buf;
   622  
   623                          if (mr->response != 0x2) {
   624                                  wprintw(mixerwindow, "midi reply is not 
a response, exit...\n");
   625                                  wrefresh(mixerwindow);
   626                                  return(-1);
   627                          }
   628                                  
   629                          if ((len = read(midi, buf, sizeof(*mm))) != 
sizeof(*mm)) {
   630                                  wprintw(mixerwindow, "expected %d bytes 
but %d came back\n", sizeof(*mm), len);
   631                                  wrefresh(mixerwindow);
   632                                  return (-1);
   633                          }
   634                  
   635                          mm = (struct midi_manuf *)buf;
   636  
   637                          wprintw(mixerwindow, "manufacturer 
%02x:%02x:%02x product %02x\n", mm->manufacturer[0], mm->manufacturer[1], 
mm->manufacturer[2], mm->product);
   638                          wrefresh(mixerwindow);
   639                          memcpy(manufacturer, mm, sizeof(struct 
midi_manuf));
   640                          
   641                          if ((len = read(midi, buf, sizeof(struct 
midi_len))) != sizeof(struct midi_len)) {
   642                                  wprintw(mixerwindow, "expected %d bytes 
but %d came back\n", sizeof(*ml), len);
   643                                  wrefresh(mixerwindow);
   644                                  return(-1);
   645                          }
   646                  
   647                          ml = (struct midi_len *)buf;
   648  
   649                          if (ml->hibyte != 0) {
   650                                  wprintw(mixerwindow, "message is more 
than 255 bytes, exiting\n");
   651                                  wrefresh(mixerwindow);
   652                                  return(-1);
   653                          }
   654  
   655                          mlen = ml->lobyte;
   656                          if ((len = read(midi, buf, mlen)) != mlen) {
   657                                  fprintf(stderr, "expected %d bytes but 
%d came back instead\n", mlen, len);
   658                                  return(-1);
   659                          }
   660  
   661                          rply = (struct reply *)&buf[0];
   662          
   663                          wprintw(mixerwindow, "version: %lu\nDEVID: 
%u\nSerial: %lu\n", 
   664                                  rply->version, rply->devid, 
rply->serial);
   665                          wrefresh(mixerwindow);
   666  
   667                          wprintw(mixerwindow, "manufacturer: ");
   668                          wrefresh(mixerwindow);
   669                          for (i = 9;  i < mlen; i++) {
   670                                  if (buf[i] == 0xf7) {
   671                                          gotf7 = 1;
   672                                          break;
   673                                  }
   674  
   675                                  wprintw(mixerwindow, "%c", buf[i]);
   676                                  wrefresh(mixerwindow);
   677                          }
   678                          wprintw(mixerwindow, "\n");
   679                          wrefresh(mixerwindow);
   680  
   681                          if (!gotf7)
   682                                  while (buf[0] != 0xf7)
   683                                          read(midi, buf, 1);
   684                          
   685                          read(midi, buf, 1);
   686                  }
   687          }
   688  
   689          return 0;
   690  }
   691  
   692  char *
   693  numark_controllid(u_int8_t id)
   694  {
   695          static char buf[512];
   696          struct numarktab *ptab = myntab;
   697          int i;
   698  
   699          strlcpy(buf, "unknown", sizeof(buf));
   700  
   701          for (i = 0; i < nitems(myntab); i++) {
   702                  if (ptab->id == id) {
   703                          strlcpy(buf, ptab->string, sizeof(buf));
   704                          break;
   705                  }
   706                  
   707                  ptab++;
   708          }
   709  
   710          return (buf);
   711  }
   712  
   713  
   714  int
   715  update_fader(WINDOW *crossfader, u_int8_t command)
   716  {
   717          float pos = command;
   718          float newpos;
   719          int ret;
   720          
   721          newpos = (1 - (pos / 127)) * 20;
   722          ret = (pos * 100) / 127;
   723  
   724  #if 0
   725          wprintw(mixerwindow, "%d, ", newpos);
   726          wrefresh(mixerwindow);
   727  #endif
   728  
   729          wmove(crossfader, 1, 1);
   730          wprintw(crossfader, "                    ");
   731          wmove(crossfader, 1, (int)newpos);
   732          wprintw(crossfader, "||");
   733          wrefresh(crossfader);
   734  
   735          return (ret);
   736  }
   737  
   738  int
   739  write_songs(WINDOW *songs, int selected)
   740  {
   741          DIR *dirp;
   742          struct dirent *dp;
   743          char *p;
   744          int i;
   745          char song[29];
   746  
   747          dirp = opendir(".");
   748          if (dirp) {
   749                  i = 1;
   750                  while ((dp = readdir(dirp)) != NULL) {
   751                          if (i > 8)
   752                                  break;
   753  
   754                          if ((p = strrchr(dp->d_name, '.')) == NULL)
   755                                  continue;
   756                  
   757                          if (strcmp(p, ".wav"))
   758                                  continue;
   759  
   760                          if (strlen(dp->d_name) > 28)
   761                                  dp->d_name[27] = '\0';
   762          
   763                          memset(song, ' ', sizeof(song));
   764                          song[28] = '\0';
   765                          memcpy(song, dp->d_name, 
MIN(strlen(dp->d_name), 28));
   766                          
   767                          if (i == selected)
   768                                  wattrset(songs, A_STANDOUT|A_REVERSE);
   769                          else 
   770                                  wattrset(songs, A_NORMAL);
   771                          
   772                          wmove(songs, i, 1);
   773                          wprintw(songs, "%s", song);
   774                          
   775                          i++;
   776                  }
   777  
   778                  closedir(dirp);
   779          }
   780  
   781          return selected;
   782  }
   783  
   784  char *
   785  get_songs(int selected)
   786  {
   787          DIR *dirp;
   788          struct dirent *dp;
   789          char *p;
   790          int i;
   791          static char song[128];
   792  
   793          dirp = opendir(".");
   794          if (dirp) {
   795                  i = 1;
   796                  while ((dp = readdir(dirp)) != NULL) {
   797                          if (i > 8)
   798                                  break;
   799  
   800                          if ((p = strrchr(dp->d_name, '.')) == NULL)
   801                                  continue;
   802                  
   803                          if (strcmp(p, ".wav"))
   804                                  continue;
   805  
   806                          if (i == selected) {
   807                                  strlcpy(song, dp->d_name, sizeof(song));
   808                                  break;
   809                          }
   810                          i++;
   811                  }
   812  
   813                  closedir(dirp);
   814          }
   815  
   816          return (song);
   817  }
   818  
   819  
   820  struct mywaveheader *
   821  getheader(int fd)
   822  {
   823          char buf[512];
   824          struct mywaveheader *mwh;
   825          struct wff *wh;
   826          struct chk *chk;
   827          struct fmt16 *fmt16;
   828  
   829          mwh = calloc(1, sizeof(struct mywaveheader));
   830          if (mwh == NULL)
   831                  return NULL;
   832  
   833          read(fd, buf, sizeof(struct wff));      
   834          wh = (struct wff *)&buf[0];
   835          
   836          if (memcmp(wh->id, "RIFF", 4) != 0) {
   837                  free (mwh);
   838                  return NULL;
   839          }
   840  
   841          memcpy(&mwh->waveheader.id, wh->id, 4);
   842          mwh->waveheader.chunksize = wh->chunksize;
   843          
   844          memcpy(&mwh->waveheader.waveid, wh->waveid, 4);
   845  
   846          /* 8 + 16 */
   847          if (read(fd, buf, 24) <= 0) {
   848                  free(mwh);
   849                  return NULL;
   850          }
   851  
   852          chk = (struct chk *)&buf[0];
   853  
   854          if (memcmp(chk->chunkid, "fmt ", 4) != 0) {
   855                  free(mwh);
   856                  return NULL;
   857          }
   858  
   859          fmt16 = (struct fmt16 *)&buf[0];
   860  
   861  
   862          memcpy(&mwh->formathdr.chunkid, fmt16->chunkid, 4);
   863          mwh->formathdr.cksize = fmt16->cksize;
   864  
   865          if (fmt16->fcode != 1) {
   866                  free(mwh);
   867                  return NULL;
   868          }
   869  
   870          mwh->formathdr.fcode = fmt16->fcode;
   871          
   872          mwh->formathdr.channels = fmt16->channels;
   873          mwh->formathdr.sps = fmt16->sps;
   874          mwh->formathdr.datarate = fmt16->datarate;
   875          mwh->formathdr.datablock = fmt16->datablock;
   876          mwh->formathdr.bps = fmt16->bps;
   877  
   878          switch (fmt16->cksize) {
   879          case 16:
   880                  break;
   881          case 40:
   882                  mwh->formathdr.validbits = fmt16->validbits;
   883                  mwh->formathdr.channelmask = fmt16->channelmask;
   884          case 18:
   885                  mwh->formathdr.size = fmt16->size;
   886                  break;
   887          default:
   888                  fprintf(stderr, "chunksize %d not supported yet\n", 
fmt16->cksize);
   889                  free(mwh);
   890                  return NULL;
   891                  break;
   892          }
   893  
   894          if (read(fd, buf, 8) <= 0) {
   895                  free(mwh);
   896                  return NULL;
   897          }
   898  
   899          chk = (struct chk *)&buf[0];
   900  
   901          if (memcmp(chk->chunkid, "FLLR ", 4) != 0) {
   902                  chk = NULL;
   903                  goto nofllr;
   904          }
   905  
   906          memcpy(&mwh->filler.chunkid, chk->chunkid, 4);
   907          mwh->filler.cksize = chk->cksize;
   908  
   909          if (lseek(fd, chk->cksize, SEEK_CUR) < 0) {
   910                  perror("lseek");
   911                  free(mwh);
   912                  return NULL;
   913          }
   914  
   915  
   916          if (read(fd, buf, 8) <= 0) {
   917                  free(mwh);
   918                  return NULL;
   919          }
   920  
   921  nofllr:
   922          chk = (struct chk *)&buf[0];
   923  
   924          if (memcmp(chk->chunkid, "data", 4) != 0) {
   925                  free(mwh);
   926                  return NULL;
   927          }
   928          
   929          memcpy(&mwh->data.chunkid, chk->chunkid, 4);
   930          mwh->data.cksize = chk->cksize;
   931  
   932          mwh->dataoffset = lseek(fd, 0, SEEK_CUR);
   933          
   934  
   935          return (mwh);
   936  }
   937  
   938  
   939  void
   940  set_led_on(int midi, int deviceid)
   941  {
   942          u_int8_t blinkenlights[3];
   943  
   944          blinkenlights[0] = MIDI_NOTEON;
   945          blinkenlights[1] = deviceid;
   946          blinkenlights[2] = 0x7f;        
   947  
   948          write(midi, blinkenlights, 3);
   949  }
   950  
   951  void
   952  set_led_off(int midi, int deviceid)
   953  {
   954          u_int8_t blinkenlights[3];
   955  
   956          blinkenlights[0] = MIDI_NOTEOFF;
   957          blinkenlights[1] = deviceid;
   958          blinkenlights[2] = 0x7f;        
   959  
   960          write(midi, blinkenlights, 3);
   961  }

Reply via email to