Blame envy24control/midi.c

Packit 427e91
/*****************************************************************************
Packit 427e91
   envy24control.c - Env24 chipset (ICE1712) control utility
Packit 427e91
   midi controller code
Packit 427e91
   (c) 2004, 2005 by Dirk Jagdmann <doj@cubic.org>
Packit 427e91
Packit 427e91
   This program is free software; you can redistribute it and/or
Packit 427e91
   modify it under the terms of the GNU General Public License
Packit 427e91
   as published by the Free Software Foundation; either version 2
Packit 427e91
   of the License, or (at your option) any later version.
Packit 427e91
Packit 427e91
   This program is distributed in the hope that it will be useful,
Packit 427e91
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 427e91
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 427e91
   GNU General Public License for more details.
Packit 427e91
Packit 427e91
   You should have received a copy of the GNU General Public License
Packit 427e91
   along with this program; if not, write to the Free Software
Packit 427e91
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 427e91
******************************************************************************/
Packit 427e91
Packit 427e91
#include <string.h>
Packit 427e91
#include <alsa/asoundlib.h>
Packit 427e91
#include "midi.h"
Packit 427e91
#include <gtk/gtk.h>
Packit 427e91
#include <stdint.h>
Packit 427e91
Packit 427e91
static const int midi2slider_lin[128] = {
Packit 427e91
  96, 96, 95, 94, 93, 93, 92, 91,
Packit 427e91
  90, 90, 89, 88, 87, 87, 86, 85,
Packit 427e91
  84, 84, 83, 82, 81, 81, 80, 79,
Packit 427e91
  78, 78, 77, 76, 75, 75, 74, 73,
Packit 427e91
  72, 72, 71, 70, 69, 69, 68, 67,
Packit 427e91
  66, 66, 65, 64, 63, 62, 62, 61,
Packit 427e91
  60, 59, 59, 58, 57, 56, 56, 55,
Packit 427e91
  54, 53, 53, 52, 51, 50, 50, 49,
Packit 427e91
  48, 47, 47, 46, 45, 44, 44, 43,
Packit 427e91
  42, 41, 41, 40, 39, 38, 38, 37,
Packit 427e91
  36, 35, 35, 34, 33, 32, 31, 31,
Packit 427e91
  30, 29, 28, 28, 27, 26, 25, 25,
Packit 427e91
  24, 23, 22, 22, 21, 20, 19, 19,
Packit 427e91
  18, 17, 16, 16, 15, 14, 13, 13,
Packit 427e91
  12, 11, 10, 10, 9, 8, 7, 7,
Packit 427e91
  6, 5, 4, 4, 3, 2, 1, 0,
Packit 427e91
};
Packit 427e91
static const int slider2midi_lin[97] = {
Packit 427e91
  0, 1, 2, 3, 5, 6, 7, 9,
Packit 427e91
  10, 11, 13, 14, 15, 17, 18, 19,
Packit 427e91
  21, 22, 23, 25, 26, 27, 29, 30,
Packit 427e91
  31, 33, 34, 35, 37, 38, 39, 41,
Packit 427e91
  42, 43, 44, 46, 47, 48, 50, 51,
Packit 427e91
  52, 54, 55, 56, 58, 59, 60, 62,
Packit 427e91
  63, 64, 66, 67, 68, 70, 71, 72,
Packit 427e91
  74, 75, 76, 78, 79, 80, 82, 83,
Packit 427e91
  84, 85, 87, 88, 89, 91, 92, 93,
Packit 427e91
  95, 96, 97, 99, 100, 101, 103, 104,
Packit 427e91
  105, 107, 108, 109, 111, 112, 113, 115,
Packit 427e91
  116, 117, 119, 120, 121, 123, 124, 125,
Packit 427e91
  127,
Packit 427e91
};
Packit 427e91
Packit 427e91
static const int midi2slider_enh[128] = {
Packit 427e91
  96, 95, 94, 93, 91, 90, 89, 87,
Packit 427e91
  86, 85, 83, 82, 81, 79, 78, 77,
Packit 427e91
  75, 74, 73, 72, 70, 69, 68, 66,
Packit 427e91
  65, 64, 62, 61, 60, 58, 57, 56,
Packit 427e91
  54, 53, 52, 51, 49, 48, 47, 45,
Packit 427e91
  44, 43, 41, 40, 39, 37, 36, 35,
Packit 427e91
  33, 32, 31, 30, 28, 27, 26, 24,
Packit 427e91
  23, 22, 20, 19, 18, 16, 15, 14,
Packit 427e91
  12, 12, 12, 12, 12, 11, 11, 11,
Packit 427e91
  11, 11, 10, 10, 10, 10, 10, 9,
Packit 427e91
  9, 9, 9, 9, 8, 8, 8, 8,
Packit 427e91
  8, 7, 7, 7, 7, 7, 6, 6,
Packit 427e91
  6, 6, 6, 5, 5, 5, 5, 5,
Packit 427e91
  4, 4, 4, 4, 4, 3, 3, 3,
Packit 427e91
  3, 3, 2, 2, 2, 2, 2, 1,
Packit 427e91
  1, 1, 1, 1, 0, 0, 0, 0,
Packit 427e91
};
Packit 427e91
static const int slider2midi_enh[97] = {
Packit 427e91
  0, 1, 2, 3, 4, 4, 5, 6,
Packit 427e91
  7, 7, 8, 9, 10, 10, 11, 12,
Packit 427e91
  13, 13, 14, 15, 16, 16, 17, 18,
Packit 427e91
  19, 20, 20, 21, 22, 23, 23, 24,
Packit 427e91
  25, 26, 26, 27, 28, 29, 29, 30,
Packit 427e91
  31, 32, 32, 33, 34, 35, 36, 36,
Packit 427e91
  37, 38, 39, 39, 40, 41, 42, 42,
Packit 427e91
  43, 44, 45, 45, 46, 47, 48, 48,
Packit 427e91
  49, 50, 51, 52, 52, 53, 54, 55,
Packit 427e91
  55, 56, 57, 58, 58, 59, 60, 61,
Packit 427e91
  61, 62, 63, 68, 68, 73, 78, 83,
Packit 427e91
  88, 93, 98, 103, 108, 113, 118, 123,
Packit 427e91
  127,
Packit 427e91
};
Packit 427e91
Packit 427e91
static const int *midi2slider, *slider2midi;
Packit 427e91
static snd_seq_t *seq=0;
Packit 427e91
static int client, clientId, port, ch;
Packit 427e91
static char *portname=0, *appname=0;
Packit 427e91
static int maxstreams=0;
Packit 427e91
static int currentvalue[128];
Packit 427e91
Packit 427e91
void midi_maxstreams(int m)
Packit 427e91
{
Packit 427e91
  maxstreams=m*2;
Packit 427e91
}
Packit 427e91
Packit 427e91
int midi_close()
Packit 427e91
{
Packit 427e91
  int i=0;
Packit 427e91
  if(seq)
Packit 427e91
    i=snd_seq_close(seq);
Packit 427e91
Packit 427e91
  seq=0;
Packit 427e91
  client=port=0;
Packit 427e91
  if(portname)
Packit 427e91
    free(portname), portname=0;
Packit 427e91
  if(appname)
Packit 427e91
    free(appname), appname=0;
Packit 427e91
Packit 427e91
  return i;
Packit 427e91
}
Packit 427e91
Packit 427e91
static void do_controller(int c, int v)
Packit 427e91
{
Packit 427e91
  snd_seq_event_t ev;
Packit 427e91
  if(!seq) return;
Packit 427e91
  if(currentvalue[c]==v) return;
Packit 427e91
#if 0
Packit 427e91
  fprintf(stderr, "do_controller(%i,%i)\n",c,v);
Packit 427e91
#endif
Packit 427e91
  snd_seq_ev_clear(&ev;;
Packit 427e91
  snd_seq_ev_set_source(&ev, port);
Packit 427e91
  snd_seq_ev_set_subs(&ev;;
Packit 427e91
  snd_seq_ev_set_direct(&ev;;
Packit 427e91
  snd_seq_ev_set_controller(&ev,ch,c,v);
Packit 427e91
  snd_seq_event_output(seq, &ev;;
Packit 427e91
  snd_seq_drain_output(seq);
Packit 427e91
Packit 427e91
  currentvalue[c]=v;
Packit 427e91
}
Packit 427e91
Packit 427e91
int midi_controller(int c, int v)
Packit 427e91
{
Packit 427e91
  int v2;
Packit 427e91
Packit 427e91
  if (! seq)
Packit 427e91
    return 0;
Packit 427e91
Packit 427e91
  if(c<0 || c>127) return 0;
Packit 427e91
Packit 427e91
  if(v<0) v=0;
Packit 427e91
  else if(v>96) v=96;
Packit 427e91
  v2=slider2midi[v];
Packit 427e91
#if 0
Packit 427e91
  fprintf(stderr, "midi_controller(%i,%i)->%i\n",c,v,v2);
Packit 427e91
#endif
Packit 427e91
  do_controller(c,v2);
Packit 427e91
  return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
int midi_button(int b, int v)
Packit 427e91
{
Packit 427e91
  if(b<0) return 0;
Packit 427e91
  b+=maxstreams;
Packit 427e91
  if(b>127) return 0;
Packit 427e91
  do_controller(b, v?127:0);
Packit 427e91
  return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
int midi_init(char *appname, int channel, int midi_enhanced)
Packit 427e91
{
Packit 427e91
  snd_seq_client_info_t *clientinfo;
Packit 427e91
  int npfd;
Packit 427e91
  struct pollfd *pfd;
Packit 427e91
Packit 427e91
  if(seq)
Packit 427e91
    return 0;
Packit 427e91
Packit 427e91
  for(npfd=0; npfd!=128; ++npfd)
Packit 427e91
    currentvalue[npfd]=-1;
Packit 427e91
Packit 427e91
  ch=channel;
Packit 427e91
  if(midi_enhanced)
Packit 427e91
    {
Packit 427e91
      midi2slider=midi2slider_enh;
Packit 427e91
      slider2midi=slider2midi_enh;
Packit 427e91
    }
Packit 427e91
  else
Packit 427e91
    {
Packit 427e91
      midi2slider=midi2slider_lin;
Packit 427e91
      slider2midi=slider2midi_lin;
Packit 427e91
    }
Packit 427e91
Packit 427e91
  if(snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0)
Packit 427e91
    {
Packit 427e91
      g_warning("could not init ALSA sequencer\n");
Packit 427e91
      seq=0;
Packit 427e91
      return -1;
Packit 427e91
    }
Packit 427e91
Packit 427e91
  snd_seq_set_client_name(seq, appname);
Packit 427e91
  snd_seq_client_info_alloca(&clientinfo);
Packit 427e91
  snd_seq_get_client_info (seq, clientinfo);
Packit 427e91
  client=snd_seq_client_info_get_client(clientinfo);
Packit 427e91
  clientId = snd_seq_client_id(seq);
Packit 427e91
Packit 427e91
  portname=g_strdup_printf("%s Mixer Control", appname);
Packit 427e91
  port=snd_seq_create_simple_port(seq, portname,
Packit 427e91
				  SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE|SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
Packit 427e91
				  SND_SEQ_PORT_TYPE_APPLICATION);
Packit 427e91
  if(port < 0)
Packit 427e91
    {
Packit 427e91
      g_warning("could not create ALSA sequencer port\n");
Packit 427e91
      midi_close();
Packit 427e91
      return -1;
Packit 427e91
    }
Packit 427e91
Packit 427e91
  npfd=snd_seq_poll_descriptors_count(seq, POLLIN);
Packit 427e91
  if(npfd<=0)
Packit 427e91
    {
Packit 427e91
      g_warning("could not get number of ALSA sequencer poll descriptors\n");
Packit 427e91
      midi_close();
Packit 427e91
      return -1;
Packit 427e91
    }
Packit 427e91
Packit 427e91
  pfd=(struct pollfd*)alloca(npfd * sizeof(struct pollfd));
Packit 427e91
  if(pfd==0)
Packit 427e91
    {
Packit 427e91
      g_warning("could not alloc memory for ALSA sequencer poll descriptors\n");
Packit 427e91
      midi_close();
Packit 427e91
      return -1;
Packit 427e91
    }
Packit 427e91
  if(snd_seq_poll_descriptors(seq, pfd, npfd, POLLIN) != npfd)
Packit 427e91
    {
Packit 427e91
      g_warning("number of returned poll desc is not equal of request poll desc\n");
Packit 427e91
      midi_close();
Packit 427e91
      return -1;
Packit 427e91
    }
Packit 427e91
Packit 427e91
  return pfd[0].fd;
Packit 427e91
}
Packit 427e91
Packit 427e91
void mixer_adjust(GtkAdjustment *adj, gpointer data);
Packit 427e91
void mixer_set_mute(int stream, int left, int right);
Packit 427e91
Packit 427e91
void midi_process(gpointer data, gint source, GdkInputCondition condition)
Packit 427e91
{
Packit 427e91
  snd_seq_event_t *ev;
Packit 427e91
  static GtkAdjustment *adj=0;
Packit 427e91
  if(!adj)
Packit 427e91
    adj=(GtkAdjustment*) gtk_adjustment_new(0, 0, 96, 1, 1, 10);
Packit 427e91
Packit 427e91
  do
Packit 427e91
    {
Packit 427e91
      snd_seq_event_input(seq, &ev;;
Packit 427e91
      if(!ev) continue;
Packit 427e91
      switch(ev->type)
Packit 427e91
	{
Packit 427e91
	case SND_SEQ_EVENT_CONTROLLER:
Packit 427e91
#if 0
Packit 427e91
	  fprintf(stderr, "Channel %02d: Controller %03d: Value:%d\n",
Packit 427e91
		  ev->data.control.channel, ev->data.control.param, ev->data.control.value);
Packit 427e91
#endif
Packit 427e91
	  if(ev->data.control.channel == ch)
Packit 427e91
	    {
Packit 427e91
	      currentvalue[ev->data.control.param]=ev->data.control.value;
Packit 427e91
	      if(ev->data.control.param < maxstreams)
Packit 427e91
		{
Packit 427e91
		  int stream=ev->data.control.param;
Packit 427e91
		  long data=((stream/2+1)<<16)|(stream&1;;
Packit 427e91
		  gtk_adjustment_set_value(adj, midi2slider[ev->data.control.value]);
Packit 427e91
		  mixer_adjust(adj, (gpointer)data);
Packit 427e91
		}
Packit 427e91
	      else if(ev->data.control.param < maxstreams*2)
Packit 427e91
		{
Packit 427e91
		  int b=ev->data.control.param-maxstreams;
Packit 427e91
		  int left=-1, right=-1;
Packit 427e91
		  if(b&1)
Packit 427e91
		    right=ev->data.control.value;
Packit 427e91
		  else
Packit 427e91
		    left=ev->data.control.value;
Packit 427e91
		  mixer_set_mute(b/2+1, left, right);
Packit 427e91
		}
Packit 427e91
	    }
Packit 427e91
	  break;
Packit 427e91
Packit 427e91
	case SND_SEQ_EVENT_PORT_SUBSCRIBED:
Packit 427e91
#if 0
Packit 427e91
	  fprintf(stderr, "event subscribed send.client:%i dest.client:%i clientId:%i\n",
Packit 427e91
		  (int)ev->data.connect.sender.client, (int)ev->data.connect.dest.client, clientId);
Packit 427e91
#endif
Packit 427e91
	  if(ev->data.connect.dest.client!=clientId)
Packit 427e91
	    {
Packit 427e91
	      int i;
Packit 427e91
	      for(i=0; i!=128; ++i)
Packit 427e91
		if(currentvalue[i] >= 0)
Packit 427e91
		  {
Packit 427e91
		    /* set currentvalue[i] to a fake value, so the check in do_controller does not trigger */
Packit 427e91
		    int v=currentvalue[i];
Packit 427e91
		    currentvalue[i]=-1;
Packit 427e91
		    do_controller(i, v);
Packit 427e91
		  }
Packit 427e91
	    }
Packit 427e91
	  break;
Packit 427e91
	}
Packit 427e91
      snd_seq_free_event(ev);
Packit 427e91
    }
Packit 427e91
  while (snd_seq_event_input_pending(seq, 0) > 0);
Packit 427e91
}
Packit 427e91
Packit 427e91
/* ************************************************* */
Packit 427e91
/* C++ code to help calculating midi<->slider tables */
Packit 427e91
#if 0
Packit 427e91
#include <iostream>
Packit 427e91
#include <map>
Packit 427e91
#include <vector>
Packit 427e91
using namespace std;
Packit 427e91
int main()
Packit 427e91
{
Packit 427e91
  int i;
Packit 427e91
  int midi2slider[128];
Packit 427e91
  ///// your midi to slider conversion should be calculated here
Packit 427e91
  for(i=0; i<64; ++i)
Packit 427e91
    midi2slider[i]=(i*84)/64;
Packit 427e91
  for(i=0; i<64; ++i)
Packit 427e91
    midi2slider[i+64]=(i*13)/64+84;
Packit 427e91
  ///// end of your calculation
Packit 427e91
Packit 427e91
  // print map
Packit 427e91
  map<int,int> m;
Packit 427e91
  int z=-1;
Packit 427e91
  cout << "static const int midi2slider_enh[128] = {" << endl;
Packit 427e91
  for(i=0; i<128; ++i)
Packit 427e91
    {
Packit 427e91
      int v=96-midi2slider[i];
Packit 427e91
      cout << v << ", ";
Packit 427e91
      if(((++z)%8)==7)
Packit 427e91
	cout << endl;
Packit 427e91
      m[v]=z;
Packit 427e91
    }
Packit 427e91
  cout << "};" << endl;
Packit 427e91
Packit 427e91
  // now generate the reverse map
Packit 427e91
  vector<int> rm;
Packit 427e91
  cout << "static const int slider2midi_enh[97] = {" << endl;
Packit 427e91
  int last=0;
Packit 427e91
  for(i=0; i<97; ++i)
Packit 427e91
    {
Packit 427e91
      int v=m[i];
Packit 427e91
      if(v==0) v=last;
Packit 427e91
      last=v;
Packit 427e91
      rm.push_back(v);
Packit 427e91
    }
Packit 427e91
  z=-1;
Packit 427e91
  for(i=96; i>=0; --i)
Packit 427e91
    {
Packit 427e91
      cout << rm[i] << ", ";
Packit 427e91
      if(((++z)%8)==7)
Packit 427e91
	cout << endl;
Packit 427e91
    }
Packit 427e91
  cout << "};" << endl;
Packit 427e91
  return 0;
Packit 427e91
}
Packit 427e91
#endif