Blame envy24control/midi.c

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