mirror of
https://github.com/alsa-project/alsa-tools.git
synced 2026-02-21 01:40:16 -05:00
envy24control: midi support for mixer
Hello devlopers, I have made the mixer sliders in envy24control react to MIDI controllers. This way the hardware mixer can be controlled from a sequencer program or some external MIDI controller hardware. envy24control became a standard ALSA sequencer client which you can connect to arbitrary other MIDI sources/sinks. Signed-off-by: Dirk Jagdmann <doj@cubic.org>
This commit is contained in:
parent
465acb88f4
commit
1be230856c
6 changed files with 269 additions and 41 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
AM_CFLAGS = @ENVY24CONTROL_CFLAGS@
|
AM_CFLAGS = @ENVY24CONTROL_CFLAGS@
|
||||||
bin_PROGRAMS = envy24control
|
bin_PROGRAMS = envy24control
|
||||||
man_MANS = envy24control.1
|
man_MANS = envy24control.1
|
||||||
envy24control_SOURCES = envy24control.c envy24control.h levelmeters.c \
|
envy24control_SOURCES = envy24control.c envy24control.h levelmeters.c midi.c \
|
||||||
mixer.c patchbay.c hardware.c driverevents.c volume.c \
|
mixer.c patchbay.c hardware.c driverevents.c volume.c \
|
||||||
profiles.c profiles.h
|
profiles.c profiles.h
|
||||||
envy24control_LDFLAGS = @ENVY24CONTROL_LIBS@
|
envy24control_LDFLAGS = @ENVY24CONTROL_LIBS@
|
||||||
|
|
|
||||||
|
|
@ -1,72 +1,75 @@
|
||||||
.TH "envy24control" 1 "16 May 2004"
|
.TH "envy24control" "1" "16 May 2004" "" ""
|
||||||
.SH NAME
|
.SH "NAME"
|
||||||
envy24control \- GUI control tool for Envy24 (ice1712) based
|
envy24control \- GUI control tool for Envy24 (ice1712) based
|
||||||
soundcards, under ALSA.
|
soundcards, under ALSA.
|
||||||
|
|
||||||
.SH SYNOPSIS
|
.SH "SYNOPSIS"
|
||||||
\fBenvy24control\fP [\fI\-c\fP card-number] [\fI\-D\fP control-name] [\fI\-o\fP 0-num DACs max 8] [\fI\-i\fP 0-num ADCs max 8] [\fI\-p\fP 0-8] [\fI\-s\fP 0-2] [\fI\-f\fP <profiles file name>] [\fI\-v\fP] [<profile number>|<profile name>]
|
\fBenvy24control\fP [\fI\-c\fP card\-number] [\fI\-D\fP control\-name] [\fI\-o\fP 0\-num DACs max 8] [\fI\-i\fP 0\-num ADCs max 8] [\fI\-p\fP 0\-8] [\fI\-s\fP 0\-2] [\fI\-f\fP <profiles file name>] [\fI\-v\fP] [<profile number>|<profile name>] [\fI\-m\fP midi\-channel]
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH "DESCRIPTION"
|
||||||
\fBenvy24control\fP allows control of the digital mixer, channel gains
|
\fBenvy24control\fP allows control of the digital mixer, channel gains
|
||||||
and other hardware settings for sound cards based on the ice1712
|
and other hardware settings for sound cards based on the ice1712
|
||||||
chipset (Midiman Delta series, Terratec EWS and EWX series). It also
|
chipset (Midiman Delta series, Terratec EWS and EWX series). It also
|
||||||
displays a level meter for each input and output channel.
|
displays a level meter for each input and output channel.
|
||||||
|
|
||||||
.SH INVOKING
|
.SH "INVOKING"
|
||||||
|
\fBenvy24control\fP [\fI\-c\fP card\-number] [\fI\-D\fP control\-name] [\fI\-o\fP 0\-num DACs max 8] [\fI\-i\fP 0\-num ADCs max 8] [\fI\-p\fP 0\-8] [\fI\-s\fP 0\-2] [\fI\-f\fP <profiles file name>] [\fI\-v\fP] [<profile number>|<profile name>] [\fI\-m\fP midi\-channel]
|
||||||
\fBenvy24control\fP [\fI\-c\fP card-number] [\fI\-D\fP control-name] [\fI\-o\fP 0-num DACs max 8] [\fI\-i\fP 0-num ADCs max 8] [\fI\-p\fP 0-8] [\fI\-s\fP 0-2] [\fI\-f\fP <profiles file name>] [\fI\-v\fP] [<profile number>|<profile name>]
|
.TP
|
||||||
.TP
|
If no control\-name is given, then the first sound card is used.
|
||||||
If no control-name is given, then the first sound card is used.
|
|
||||||
|
|
||||||
.SS Options
|
.SS Options
|
||||||
.TP
|
.TP
|
||||||
\fI\-c\fP card-number
|
\fI\-c\fP card\-number
|
||||||
Use the card specified by card-number rather than the first card.
|
Use the card specified by card\-number rather than the first card.
|
||||||
This is equivalent with \fI\-Dhw:n\fP option where \fIn\fP is the card number.
|
This is equivalent with \fI\-Dhw:n\fP option where \fIn\fP is the card number.
|
||||||
.TP
|
.TP
|
||||||
\fI\-D\fP control-name
|
\fI\-D\fP control\-name
|
||||||
Use the card specified by control-name rather than the first card,
|
Use the card specified by control\-name rather than the first card,
|
||||||
normally this will be of the form hw:\fIn\fP where \fIn\fP is the sound
|
normally this will be of the form hw:\fIn\fP where \fIn\fP is the sound
|
||||||
card number (zero-based). This is only needed if you have more than one
|
card number (zero\-based). This is only needed if you have more than one
|
||||||
Envy24-based card or if your Envy24 card is not configured as the first
|
Envy24\-based card or if your Envy24 card is not configured as the first
|
||||||
card in your ALSA driver setup.
|
card in your ALSA driver setup.
|
||||||
.TP
|
.TP
|
||||||
\fI\-o\fP outputs
|
\fI\-o\fP outputs
|
||||||
Limit number of analog line outputs to display. Default is the number of
|
Limit number of analog line outputs to display. Default is the number of
|
||||||
DACs in the driver specification. Maximum is 8.
|
DACs in the driver specification. Maximum is 8.
|
||||||
The number of analog output lines can only be reduced from the available
|
The number of analog output lines can only be reduced from the available
|
||||||
number of output lines.
|
number of output lines.
|
||||||
.TP
|
.TP
|
||||||
\fI\-i\fP inputs
|
\fI\-i\fP inputs
|
||||||
Limit number of analog line inputs to display. Default is the number of
|
Limit number of analog line inputs to display. Default is the number of
|
||||||
ADCs in the driver specification. Maximum is 8.
|
ADCs in the driver specification. Maximum is 8.
|
||||||
The number of analog input lines can only be reduced from the available
|
The number of analog input lines can only be reduced from the available
|
||||||
number of input lines.
|
number of input lines.
|
||||||
.TP
|
.TP
|
||||||
\fI\-p\fP pcm outputs
|
\fI\-p\fP pcm outputs
|
||||||
Limit number of PCM outputs to display. Default is 8.
|
Limit number of PCM outputs to display. Default is 8.
|
||||||
.TP
|
.TP
|
||||||
\fI\-s\fP spdif inputs/outputs
|
\fI\-s\fP spdif inputs/outputs
|
||||||
Limit number of SPDIF inputs/outputs to display. Default is 2.
|
Limit number of SPDIF inputs/outputs to display. Default is 2.
|
||||||
.TP
|
.TP
|
||||||
\fI\-f\fP name and path of the profiles file name.
|
\fI\-f\fP name and path of the profiles file name.
|
||||||
From/to this file will envy24control read/write the alsactl settings.
|
From/to this file will envy24control read/write the alsactl settings.
|
||||||
If is not given DEFAULT_PROFILERC or for restore if DEFAULT_PROFILERC
|
If is not given DEFAULT_PROFILERC or for restore if DEFAULT_PROFILERC
|
||||||
doesn't exists SYS_PROFILERC will be used.
|
doesn't exists SYS_PROFILERC will be used.
|
||||||
.TP
|
.TP
|
||||||
\fI\-v\fP view spdif playback channels in the mixer.
|
\fI\-v\fP view spdif playback channels in the mixer.
|
||||||
It is not possible to manage something (muting, volume levels).
|
It is not possible to manage something (muting, volume levels).
|
||||||
It is only to view the levelmeters.
|
It is only to view the levelmeters.
|
||||||
Default is no view of spdif playback channels in the mixer.
|
Default is no view of spdif playback channels in the mixer.
|
||||||
|
.TP
|
||||||
.SH SEE ALSO
|
\fI\-m\fP midi\-channel
|
||||||
|
Use MIDI controller values to control the Faders in the mixer view.
|
||||||
|
The application will react to controllers on channel midi\-channel and
|
||||||
|
send controllers on this channel when the user moves the GUI sliders.
|
||||||
|
.SH "SEE ALSO"
|
||||||
\fB
|
\fB
|
||||||
alsamixer(1),
|
alsamixer(1),
|
||||||
amixer(1),
|
amixer(1),
|
||||||
gamix(1)
|
gamix(1)
|
||||||
\fP
|
\fP
|
||||||
|
|
||||||
.SH AUTHOR
|
.SH "AUTHOR"
|
||||||
\fBenvy24control\fP is by Jaroslav Kysela <perex@suse.cz>
|
\fBenvy24control\fP is by Jaroslav Kysela <perex@suse.cz>
|
||||||
This document is by James Tappin <james@xena.uklinux.net>.
|
This document is by James Tappin <james@xena.uklinux.net>.
|
||||||
Last updated by Dirk Kalis <dirk.kalis@t\-online.de>.
|
Last updated by Dirk Kalis <dirk.kalis@t\-online.de>.
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "envy24control.h"
|
#include "envy24control.h"
|
||||||
|
#include "midi.h"
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
|
|
@ -1926,7 +1927,7 @@ static void create_profiles(GtkWidget *main, GtkWidget *notebook, int page)
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: envy24control [-c card#] [-D control-name] [-o num-outputs] [-i num-inputs] [-p num-pcm-outputs] [-s num-spdif-in/outs] [-v] [-f profiles-file] [profile name|profile id]\n");
|
fprintf(stderr, "usage: envy24control [-c card#] [-D control-name] [-o num-outputs] [-i num-inputs] [-p num-pcm-outputs] [-s num-spdif-in/outs] [-v] [-f profiles-file] [profile name|profile id] [-m channel-num]\n");
|
||||||
fprintf(stderr, "\t-c, --card\tAlsa card number to control\n");
|
fprintf(stderr, "\t-c, --card\tAlsa card number to control\n");
|
||||||
fprintf(stderr, "\t-D, --device\tcontrol-name\n");
|
fprintf(stderr, "\t-D, --device\tcontrol-name\n");
|
||||||
fprintf(stderr, "\t-o, --outputs\tLimit number of analog line outputs to display\n");
|
fprintf(stderr, "\t-o, --outputs\tLimit number of analog line outputs to display\n");
|
||||||
|
|
@ -1935,6 +1936,7 @@ static void usage(void)
|
||||||
fprintf(stderr, "\t-s, --spdif\tLimit number of spdif inputs/outputs to display\n");
|
fprintf(stderr, "\t-s, --spdif\tLimit number of spdif inputs/outputs to display\n");
|
||||||
fprintf(stderr, "\t-v, --view_spdif_playback\tshows the spdif playback channels in the mixer\n");
|
fprintf(stderr, "\t-v, --view_spdif_playback\tshows the spdif playback channels in the mixer\n");
|
||||||
fprintf(stderr, "\t-f, --profiles_file\tuse file as profiles file\n");
|
fprintf(stderr, "\t-f, --profiles_file\tuse file as profiles file\n");
|
||||||
|
fprintf(stderr, "\t-m, --midichannel\tmidi channel number for controller control\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
|
@ -1946,17 +1948,19 @@ int main(int argc, char **argv)
|
||||||
snd_ctl_elem_value_t *val;
|
snd_ctl_elem_value_t *val;
|
||||||
int npfds;
|
int npfds;
|
||||||
struct pollfd *pfds;
|
struct pollfd *pfds;
|
||||||
|
int midi_fd, midi_channel = -1;
|
||||||
int page;
|
int page;
|
||||||
int input_channels_set = 0;
|
int input_channels_set = 0;
|
||||||
int output_channels_set = 0;
|
int output_channels_set = 0;
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"device", 1, 0, 'D'},
|
{"device", 1, 0, 'D'},
|
||||||
{"card", 1, 0, 'c'},
|
{"card", 1, 0, 'c'},
|
||||||
|
{"profiles_file", 1, 0, 'f'},
|
||||||
{"inputs", 1, 0, 'i'},
|
{"inputs", 1, 0, 'i'},
|
||||||
|
{"midichannel", 1, 0, 'm'},
|
||||||
{"outputs", 1, 0, 'o'},
|
{"outputs", 1, 0, 'o'},
|
||||||
{"pcm_outputs", 1, 0, 'p'},
|
{"pcm_outputs", 1, 0, 'p'},
|
||||||
{"spdif", 1, 0, 's'},
|
{"spdif", 1, 0, 's'},
|
||||||
{"profiles_file", 1, 0, 'f'},
|
|
||||||
{"view_spdif_playback", 0, 0, 'v'},
|
{"view_spdif_playback", 0, 0, 'v'},
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
@ -1977,8 +1981,16 @@ int main(int argc, char **argv)
|
||||||
view_spdif_playback = 0;
|
view_spdif_playback = 0;
|
||||||
profiles_file_name = DEFAULT_PROFILERC;
|
profiles_file_name = DEFAULT_PROFILERC;
|
||||||
default_profile = NULL;
|
default_profile = NULL;
|
||||||
while ((c = getopt_long(argc, argv, "D:c:i:o:p:s:f:v", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "D:c:f:i:m:o:p:s:v", long_options, NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case 'D':
|
||||||
|
name = optarg;
|
||||||
|
card_number = atoi(strchr(name, ':') + sizeof(char));
|
||||||
|
if (card_number < 0 || card_number >= MAX_CARD_NUMBERS) {
|
||||||
|
fprintf(stderr, "envy24control: invalid card number %d\n", card_number);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
i = atoi(optarg);
|
i = atoi(optarg);
|
||||||
if (i < 0 || i >= MAX_CARD_NUMBERS) {
|
if (i < 0 || i >= MAX_CARD_NUMBERS) {
|
||||||
|
|
@ -1989,13 +2001,8 @@ int main(int argc, char **argv)
|
||||||
sprintf(tmpname, "hw:%d", i);
|
sprintf(tmpname, "hw:%d", i);
|
||||||
name = tmpname;
|
name = tmpname;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'f':
|
||||||
name = optarg;
|
profiles_file_name = optarg;
|
||||||
card_number = atoi(strchr(name, ':') + sizeof(char));
|
|
||||||
if (card_number < 0 || card_number >= MAX_CARD_NUMBERS) {
|
|
||||||
fprintf(stderr, "envy24control: invalid card number %d\n", card_number);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
input_channels = atoi(optarg);
|
input_channels = atoi(optarg);
|
||||||
|
|
@ -2005,6 +2012,14 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
input_channels_set = 1;
|
input_channels_set = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'm':
|
||||||
|
midi_channel = atoi(optarg);
|
||||||
|
if (midi_channel < 1 || midi_channel > 16) {
|
||||||
|
fprintf(stderr, "envy24control: invalid midi channel number %i\n", midi_channel);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
--midi_channel;
|
||||||
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
output_channels = atoi(optarg);
|
output_channels = atoi(optarg);
|
||||||
if (output_channels < 0 || output_channels > MAX_OUTPUT_CHANNELS) {
|
if (output_channels < 0 || output_channels > MAX_OUTPUT_CHANNELS) {
|
||||||
|
|
@ -2027,9 +2042,6 @@ int main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'f':
|
|
||||||
profiles_file_name = optarg;
|
|
||||||
break;
|
|
||||||
case 'v':
|
case 'v':
|
||||||
view_spdif_playback = 1;
|
view_spdif_playback = 1;
|
||||||
break;
|
break;
|
||||||
|
|
@ -2083,6 +2095,8 @@ int main(int argc, char **argv)
|
||||||
patchbay_init();
|
patchbay_init();
|
||||||
hardware_init();
|
hardware_init();
|
||||||
analog_volume_init();
|
analog_volume_init();
|
||||||
|
if (midi_channel >= 0)
|
||||||
|
midi_fd = midi_init(argv[0], midi_channel);
|
||||||
|
|
||||||
fprintf(stderr, "using\t --- input_channels: %i\n\t --- output_channels: %i\n\t --- pcm_output_channels: %i\n\t --- spdif in/out channels: %i\n", \
|
fprintf(stderr, "using\t --- input_channels: %i\n\t --- output_channels: %i\n\t --- pcm_output_channels: %i\n\t --- spdif in/out channels: %i\n", \
|
||||||
input_channels, output_channels, pcm_output_channels, spdif_channels);
|
input_channels, output_channels, pcm_output_channels, spdif_channels);
|
||||||
|
|
@ -2123,6 +2137,9 @@ int main(int argc, char **argv)
|
||||||
ctl);
|
ctl);
|
||||||
snd_ctl_subscribe_events(ctl, 1);
|
snd_ctl_subscribe_events(ctl, 1);
|
||||||
}
|
}
|
||||||
|
if (midi_fd >= 0) {
|
||||||
|
gdk_input_add(midi_fd, GDK_INPUT_READ, midi_process, NULL);
|
||||||
|
}
|
||||||
gtk_timeout_add(40, level_meters_timeout_callback, NULL);
|
gtk_timeout_add(40, level_meters_timeout_callback, NULL);
|
||||||
gtk_timeout_add(100, master_clock_status_timeout_callback, NULL);
|
gtk_timeout_add(100, master_clock_status_timeout_callback, NULL);
|
||||||
gtk_timeout_add(100, internal_clock_status_timeout_callback, NULL);
|
gtk_timeout_add(100, internal_clock_status_timeout_callback, NULL);
|
||||||
|
|
@ -2141,6 +2158,7 @@ int main(int argc, char **argv)
|
||||||
gtk_main();
|
gtk_main();
|
||||||
|
|
||||||
snd_ctl_close(ctl);
|
snd_ctl_close(ctl);
|
||||||
|
midi_close();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
188
envy24control/midi.c
Normal file
188
envy24control/midi.c
Normal file
|
|
@ -0,0 +1,188 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
envy24control.c - Env24 chipset (ICE1712) control utility
|
||||||
|
midi controller code
|
||||||
|
(c) 2004 by Dirk Jagdmann <doj@cubic.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <alsa/asoundlib.h>
|
||||||
|
#include "midi.h"
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static snd_seq_t *seq=0;
|
||||||
|
static int client, clientId, port, ch;
|
||||||
|
static char *portname=0, *appname=0;
|
||||||
|
static int nofeedback=-1;
|
||||||
|
static int maxstreams=0;
|
||||||
|
static uint8_t currentvalues[128];
|
||||||
|
|
||||||
|
void midi_maxstreams(int m)
|
||||||
|
{
|
||||||
|
maxstreams=(m-1)*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int midi_close()
|
||||||
|
{
|
||||||
|
int i=0;
|
||||||
|
if(seq)
|
||||||
|
i=snd_seq_close(seq);
|
||||||
|
|
||||||
|
seq=0;
|
||||||
|
client=port=0;
|
||||||
|
if(portname)
|
||||||
|
free(portname), portname=0;
|
||||||
|
if(appname)
|
||||||
|
free(appname), appname=0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_controller(int c, int v)
|
||||||
|
{
|
||||||
|
snd_seq_event_t ev;
|
||||||
|
snd_seq_ev_clear(&ev);
|
||||||
|
snd_seq_ev_set_source(&ev, port);
|
||||||
|
snd_seq_ev_set_subs(&ev);
|
||||||
|
snd_seq_ev_set_direct(&ev);
|
||||||
|
snd_seq_ev_set_controller(&ev,ch,c,v);
|
||||||
|
snd_seq_event_output(seq, &ev);
|
||||||
|
snd_seq_drain_output(seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
int midi_controller(int c, int v)
|
||||||
|
{
|
||||||
|
if(c==nofeedback) return 0;
|
||||||
|
if(c<0 || c>127) return 0;
|
||||||
|
|
||||||
|
v*=127; v/=96;
|
||||||
|
if(v<0) v=0;
|
||||||
|
if(v>127) v=127;
|
||||||
|
currentvalues[c]=v;
|
||||||
|
do_controller(c,v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int midi_init(char *appname, int channel)
|
||||||
|
{
|
||||||
|
snd_seq_client_info_t *clientinfo;
|
||||||
|
int npfd;
|
||||||
|
struct pollfd *pfd;
|
||||||
|
|
||||||
|
if(seq)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ch=channel;
|
||||||
|
|
||||||
|
if(snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0)
|
||||||
|
{
|
||||||
|
g_warning("could not init ALSA sequencer\n");
|
||||||
|
seq=0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_seq_set_client_name(seq, appname);
|
||||||
|
snd_seq_client_info_alloca(&clientinfo);
|
||||||
|
snd_seq_get_client_info (seq, clientinfo);
|
||||||
|
client=snd_seq_client_info_get_client(clientinfo);
|
||||||
|
clientId = snd_seq_client_id(seq);
|
||||||
|
|
||||||
|
portname=g_strdup_printf("%s Mixer Control", appname);
|
||||||
|
port=snd_seq_create_simple_port(seq, portname,
|
||||||
|
SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE|SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
|
||||||
|
SND_SEQ_PORT_TYPE_APPLICATION);
|
||||||
|
if(port < 0)
|
||||||
|
{
|
||||||
|
g_warning("could not create ALSA sequencer port\n");
|
||||||
|
midi_close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
npfd=snd_seq_poll_descriptors_count(seq, POLLIN);
|
||||||
|
if(npfd<=0)
|
||||||
|
{
|
||||||
|
g_warning("could not get number of ALSA sequencer poll descriptors\n");
|
||||||
|
midi_close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfd=(struct pollfd*)alloca(npfd * sizeof(struct pollfd));
|
||||||
|
if(pfd==0)
|
||||||
|
{
|
||||||
|
g_warning("could not alloc memory for ALSA sequencer poll descriptors\n");
|
||||||
|
midi_close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(snd_seq_poll_descriptors(seq, pfd, npfd, POLLIN) != npfd)
|
||||||
|
{
|
||||||
|
g_warning("number of returned poll desc is not equal of request poll desc\n");
|
||||||
|
midi_close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pfd[0].fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mixer_adjust(GtkAdjustment *adj, gpointer data);
|
||||||
|
|
||||||
|
void midi_process(gpointer data, gint source, GdkInputCondition condition)
|
||||||
|
{
|
||||||
|
snd_seq_event_t *ev;
|
||||||
|
static GtkAdjustment *adj=0;
|
||||||
|
if(!adj)
|
||||||
|
adj=(GtkAdjustment*) gtk_adjustment_new(0, 0, 96, 1, 1, 10);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
snd_seq_event_input(seq, &ev);
|
||||||
|
if(!ev) continue;
|
||||||
|
switch(ev->type)
|
||||||
|
{
|
||||||
|
case SND_SEQ_EVENT_CONTROLLER:
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "Channel %02d: Controller %03d: Value:%d\n",
|
||||||
|
ev->data.control.channel, ev->data.control.param, ev->data.control.value);
|
||||||
|
#endif
|
||||||
|
if(ev->data.control.channel == ch && ev->data.control.param < maxstreams)
|
||||||
|
{
|
||||||
|
int stream=ev->data.control.param+1;
|
||||||
|
long data=((stream/2)<<16)|(stream&1);
|
||||||
|
int v=ev->data.control.value; v*=96; v/=127;
|
||||||
|
gtk_adjustment_set_value(adj, 96-v);
|
||||||
|
nofeedback=ev->data.control.param;
|
||||||
|
mixer_adjust(adj, (gpointer)data);
|
||||||
|
nofeedback=-1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SND_SEQ_EVENT_PORT_SUBSCRIBED:
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "event subscribed send.client:%i dest.client:%i clientId:%i\n",
|
||||||
|
(int)ev->data.connect.sender.client, (int)ev->data.connect.dest.client, clientId);
|
||||||
|
#endif
|
||||||
|
if(ev->data.connect.dest.client!=clientId)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i=0; i<sizeof(currentvalues); ++i)
|
||||||
|
do_controller(i, currentvalues[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
snd_seq_free_event(ev);
|
||||||
|
}
|
||||||
|
while (snd_seq_event_input_pending(seq, 0) > 0);
|
||||||
|
}
|
||||||
12
envy24control/midi.h
Normal file
12
envy24control/midi.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef MIDI__H
|
||||||
|
#define MIDI__H
|
||||||
|
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
|
||||||
|
int midi_init(char *appname, int channel);
|
||||||
|
int midi_close();
|
||||||
|
void midi_maxstreams(int);
|
||||||
|
int midi_controller(int c, int v);
|
||||||
|
void midi_process(gpointer data, gint source, GdkInputCondition condition);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "envy24control.h"
|
#include "envy24control.h"
|
||||||
|
#include "midi.h"
|
||||||
|
|
||||||
#define MULTI_PLAYBACK_SWITCH "Multi Playback Switch"
|
#define MULTI_PLAYBACK_SWITCH "Multi Playback Switch"
|
||||||
#define MULTI_PLAYBACK_VOLUME "Multi Playback Volume"
|
#define MULTI_PLAYBACK_VOLUME "Multi Playback Volume"
|
||||||
|
|
@ -62,6 +63,8 @@ void mixer_update_stream(int stream, int vol_flag, int sw_flag)
|
||||||
toggle_set(mixer_stereo_toggle[stream-1], FALSE);
|
toggle_set(mixer_stereo_toggle[stream-1], FALSE);
|
||||||
gtk_adjustment_set_value(GTK_ADJUSTMENT(mixer_adj[stream-1][0]), 96 - v[0]);
|
gtk_adjustment_set_value(GTK_ADJUSTMENT(mixer_adj[stream-1][0]), 96 - v[0]);
|
||||||
gtk_adjustment_set_value(GTK_ADJUSTMENT(mixer_adj[stream-1][1]), 96 - v[1]);
|
gtk_adjustment_set_value(GTK_ADJUSTMENT(mixer_adj[stream-1][1]), 96 - v[1]);
|
||||||
|
midi_controller(stream*2-1, v[0]);
|
||||||
|
midi_controller(stream*2, v[1]);
|
||||||
}
|
}
|
||||||
if (sw_flag) {
|
if (sw_flag) {
|
||||||
snd_ctl_elem_value_t *sw;
|
snd_ctl_elem_value_t *sw;
|
||||||
|
|
@ -139,10 +142,12 @@ static void set_volume1(int stream, int left, int right)
|
||||||
if (left >= 0) {
|
if (left >= 0) {
|
||||||
change |= (snd_ctl_elem_value_get_integer(vol, 0) != left);
|
change |= (snd_ctl_elem_value_get_integer(vol, 0) != left);
|
||||||
snd_ctl_elem_value_set_integer(vol, 0, left);
|
snd_ctl_elem_value_set_integer(vol, 0, left);
|
||||||
|
midi_controller(stream*2-1, left);
|
||||||
}
|
}
|
||||||
if (right >= 0) {
|
if (right >= 0) {
|
||||||
change |= (snd_ctl_elem_value_get_integer(vol, 1) != right);
|
change |= (snd_ctl_elem_value_get_integer(vol, 1) != right);
|
||||||
snd_ctl_elem_value_set_integer(vol, 1, right);
|
snd_ctl_elem_value_set_integer(vol, 1, right);
|
||||||
|
midi_controller(stream*2, right);
|
||||||
}
|
}
|
||||||
if (change) {
|
if (change) {
|
||||||
if ((err = snd_ctl_elem_write(ctl, vol)) < 0 && err != -EBUSY)
|
if ((err = snd_ctl_elem_write(ctl, vol)) < 0 && err != -EBUSY)
|
||||||
|
|
@ -176,6 +181,8 @@ void mixer_init(void)
|
||||||
int nb_active_channels;
|
int nb_active_channels;
|
||||||
snd_ctl_elem_value_t *val;
|
snd_ctl_elem_value_t *val;
|
||||||
|
|
||||||
|
midi_maxstreams(sizeof(stream_is_active)/sizeof(stream_is_active[0]));
|
||||||
|
|
||||||
snd_ctl_elem_value_alloca(&val);
|
snd_ctl_elem_value_alloca(&val);
|
||||||
snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER);
|
snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER);
|
||||||
memset (stream_is_active, 0, (MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS + MAX_INPUT_CHANNELS + MAX_SPDIF_CHANNELS) * sizeof(int));
|
memset (stream_is_active, 0, (MAX_PCM_OUTPUT_CHANNELS + MAX_SPDIF_CHANNELS + MAX_INPUT_CHANNELS + MAX_SPDIF_CHANNELS) * sizeof(int));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue