├── AUTHORS ├── perl ├── MANIFEST ├── Changes ├── t │ └── 00use.t ├── Build.PL ├── jmm_lsc.pl ├── README └── lib │ └── Audio │ └── JackMiniMix.pm ├── Makefile.am ├── src ├── Makefile.am ├── db.h └── minimix.c ├── ChangeLog ├── .travis.yml ├── .gitignore ├── configure.ac ├── README.md ├── autogen.sh ├── INSTALL └── COPYING /AUTHORS: -------------------------------------------------------------------------------- 1 | Nicholas J Humfrey 2 | -------------------------------------------------------------------------------- /perl/MANIFEST: -------------------------------------------------------------------------------- 1 | Build.PL 2 | Makefile.PL 3 | Changes 4 | lib/Audio/JackMiniMix.pm 5 | MANIFEST 6 | META.yml 7 | README 8 | t/00use.t 9 | -------------------------------------------------------------------------------- /perl/Changes: -------------------------------------------------------------------------------- 1 | Revision history for JackMiniMix perl interface 2 | 3 | 0.02 Fri Apr 21 22:49:36 BST 2006 4 | Added Makefile.PL 5 | 6 | 0.01 Wed Dec 21 09:25:09 GMT 2005 7 | First release 8 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | 3 | SUBDIRS = src . 4 | 5 | # Copy README.md to README when building distribution 6 | dist-hook: 7 | [ -f README.md ] && cat README.md > README || true 8 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CFLAGS = $(JACK_CFLAGS) $(LIBLO_CFLAGS) $(WARNING_CFLAGS) 2 | 3 | bin_PROGRAMS = jackminimix 4 | 5 | jackminimix_SOURCES = minimix.c db.h 6 | jackminimix_LDADD = $(JACK_LIBS) $(LIBLO_LIBS) 7 | -------------------------------------------------------------------------------- /perl/t/00use.t: -------------------------------------------------------------------------------- 1 | 2 | use strict; 3 | use Test; 4 | 5 | 6 | # use a BEGIN block so we print our plan before loading modules 7 | BEGIN { plan tests => 1 } 8 | 9 | 10 | # Check Audio::JackMiniMix loads ok 11 | use Audio::JackMiniMix; 12 | ok(1); 13 | 14 | 15 | 16 | exit; 17 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2 | 2007-03-19 Nicholas Humfrey 3 | 4 | * Minor bug fix for setting the client name 5 | * Released version 0.02 6 | 7 | 8 | 2005-06-20 Nicholas Humfrey 9 | 10 | * created project in Subversion 11 | * Released version 0.01 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: 4 | - gcc 5 | 6 | before_install: 7 | - sudo apt-get -qq update 8 | - sudo apt-get install -y build-essential pkg-config automake autoconf 9 | - sudo apt-get install -y liblo-dev libjack-jackd2-dev 10 | 11 | script: 12 | - ./autogen.sh 13 | - make 14 | - make distcheck 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | .libs 3 | *.a 4 | *.gz 5 | *.la 6 | *.lo 7 | *.o 8 | *.log 9 | *.trs 10 | 11 | Makefile 12 | Makefile.in 13 | stamp-h1 14 | 15 | /aclocal.m4 16 | /autom4te.cache/* 17 | /build-scripts/* 18 | /config.cache 19 | /config.log 20 | /config.status 21 | /configure 22 | 23 | /README 24 | /NEWS 25 | /INSTALL 26 | 27 | /src/config.h 28 | /src/config.h.in 29 | /src/jackminimix 30 | -------------------------------------------------------------------------------- /perl/Build.PL: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | 4 | use Module::Build; 5 | use strict; 6 | 7 | 8 | # Create the Build script 9 | my $build = Module::Build->new 10 | ( 11 | module_name => 'Audio::JackMiniMix', 12 | license => 'gpl', 13 | build_requires => { 14 | 'Module::Build' => '0.20' 15 | }, 16 | 17 | create_makefile_pl => 'passthrough', 18 | 19 | requires => { 20 | 'Test' => '1.00', 21 | 'Net::LibLO' => '0.03', 22 | }, 23 | ); 24 | 25 | $build->create_build_script; 26 | -------------------------------------------------------------------------------- /perl/jmm_lsc.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -I lib 2 | # 3 | # jmm_lsc.pl 4 | # JackMiniMix channel list 5 | # 6 | # Nicholas J. Humfrey 7 | # 8 | 9 | use Audio::JackMiniMix; 10 | use strict; 11 | 12 | # Create MadJACK object for talking to the deck 13 | my $minimix = new Audio::JackMiniMix(@ARGV); 14 | exit(-1) unless (defined $minimix); 15 | 16 | # Display the URL of the MadJACK deck we connected to 17 | print "URL of JackMiniMix server: ".$minimix->get_url()."\n"; 18 | 19 | 20 | 21 | # Get the gain of each of the channels 22 | foreach my $channel (1..$minimix->channel_count()) { 23 | my $gain = $minimix->get_channel_gain( $channel ); 24 | my $label = $minimix->get_channel_label( $channel ); 25 | print "[$channel] $label: $gain dB\n"; 26 | } 27 | -------------------------------------------------------------------------------- /perl/README: -------------------------------------------------------------------------------- 1 | JackMiniMix perl interface 2 | ========================== 3 | 4 | Perl module to make it easily to control a JackMiniMix server from a perl script. 5 | 6 | 7 | INSTALLATION 8 | ------------ 9 | 10 | I use Module::Build to build and install the module. 11 | To install this module type the following: 12 | 13 | perl Build.PL 14 | ./Build 15 | ./Build test 16 | 17 | And then as root: 18 | 19 | ./Build install 20 | 21 | 22 | API Overview 23 | ------------ 24 | 25 | Audio::JackMiniMix 26 | - new( url ) 27 | - new( host, port ) 28 | - channel_count() 29 | - set_channel_gain( channel, gain ) 30 | - get_channel_gain( channel ) 31 | - set_channel_label( channel, label ) 32 | - get_channel_label( channel ) 33 | - get_url(); 34 | - ping() 35 | 36 | 37 | AUTHOR 38 | ------ 39 | 40 | Nicholas J. Humfrey, njh@aelius.com 41 | 42 | 43 | COPYRIGHT 44 | --------- 45 | 46 | Copyright (C) 2005 Nicholas J. Humfrey 47 | 48 | -------------------------------------------------------------------------------- /src/db.h: -------------------------------------------------------------------------------- 1 | /* 2 | * db.h 3 | * 4 | * Copyright (C) 2003,2005 Steve Harris, Nicholas Humfrey 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * Originally Stolen from JAMIN 17 | */ 18 | 19 | #ifndef DB_H 20 | #define DB_H 21 | 22 | static inline float 23 | db2lin( float db ) 24 | { 25 | if (db <= -90.0f) return 0.0f; 26 | else { 27 | return powf(10.0f, db * 0.05f); 28 | } 29 | } 30 | 31 | static inline float 32 | lin2db( float lin ) 33 | { 34 | if (lin == 0.0f) return -90.0f; 35 | else return (20.0f * log10f(lin)); 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | 2 | dnl Require autoconf version >= 2.57 3 | AC_PREREQ(2.57) 4 | 5 | 6 | dnl ############# Initialization 7 | 8 | AC_INIT([jackminimix], [0.2.1], [njh@aelius.com]) 9 | 10 | AC_CONFIG_SRCDIR([src/minimix.c]) 11 | AC_CONFIG_AUX_DIR(build-scripts) 12 | AC_CANONICAL_SYSTEM 13 | 14 | dnl Version 1.7 of automake is recommended 15 | AM_INIT_AUTOMAKE([1.7]) 16 | AM_CONFIG_HEADER([src/config.h]) 17 | 18 | 19 | 20 | dnl ############# Compiler and tools Checks 21 | 22 | AC_PROG_CC 23 | AC_PROG_INSTALL 24 | AC_PROG_LN_S 25 | AC_C_INLINE 26 | 27 | 28 | 29 | dnl ############## Library Checks 30 | 31 | AC_CHECK_LIB([m], [sqrt], , [AC_MSG_ERROR(Can't find libm)]) 32 | AC_CHECK_LIB([mx], [powf]) 33 | 34 | # Check for JACK (need 0.100.0 for jack_client_open) 35 | PKG_CHECK_MODULES(JACK, jack >= 0.100.0) 36 | 37 | # Check for LibLO 38 | PKG_CHECK_MODULES(LIBLO, liblo >= 0.23) 39 | 40 | 41 | 42 | dnl ############## Header Checks 43 | 44 | AC_HEADER_STDC 45 | AC_CHECK_HEADERS([stdlib.h string.h unistd.h]) 46 | 47 | 48 | dnl ############## Function Checks 49 | AC_CHECK_FUNCS( atexit usleep ) 50 | 51 | 52 | 53 | dnl ############## Final Output 54 | 55 | AC_CONFIG_FILES([Makefile src/Makefile]) 56 | 57 | AC_OUTPUT 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/njh/jackminimix.svg?branch=master)](https://travis-ci.org/njh/jackminimix) 2 | 3 | JackMiniMix 4 | =========== 5 | 6 | JackMiniMix is a simple mixer for the Jack Audio Connection Kit with an OSC 7 | based control interface. It is released under the GPL licence. 8 | 9 | For the latest version of JackMiniMix, please see: 10 | http://www.aelius.com/njh/jackminimix/ 11 | 12 | 13 | OSC Interface 14 | ------------- 15 | 16 | Channels numbers range from 1 to the total number of channels. Gains are in floating point decibels in the range -90 to 90 dB, where -90 dB is treated as infinite. 17 | 18 | /mixer/get_channel_count - Get the number of channels 19 | replies with: 20 | /mixer/channel_count (i) 21 | 22 | /mixer/channel/set_gain (if) - Set the gain of channel i to f dB 23 | replies with: 24 | /mixer/channel/gain (if) 25 | 26 | /mixer/channel/set_label (is) - Set the label of channel i to s 27 | replies with: 28 | /mixer/channel/label (is) 29 | 30 | /mixer/channel/get_gain (i) - Get gain of channel i 31 | replies with: 32 | /mixer/channel/gain (if) 33 | 34 | /mixer/channel/get_label (i) - Get the label of channel i 35 | replies with: 36 | /mixer/channel/label (is) 37 | 38 | /ping - Check mixer is still there 39 | replies with: 40 | /pong 41 | 42 | Replies are send back to the port/socket that they were sent from. 43 | 44 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this to set up the build system: configure, makefiles, etc. 3 | 4 | package="JackMiniMix" 5 | 6 | 7 | srcdir=`dirname $0` 8 | test -z "$srcdir" && srcdir=. 9 | 10 | cd "$srcdir" 11 | DIE=0 12 | 13 | (autoheader --version) < /dev/null > /dev/null 2>&1 || { 14 | echo 15 | echo "You must have autoconf installed to compile $package." 16 | echo "Download the appropriate package for your distribution," 17 | echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" 18 | DIE=1 19 | } 20 | 21 | (autoconf --version) < /dev/null > /dev/null 2>&1 || { 22 | echo 23 | echo "You must have autoconf installed to compile $package." 24 | echo "Download the appropriate package for your distribution," 25 | echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" 26 | DIE=1 27 | } 28 | 29 | (automake --version) < /dev/null > /dev/null 2>&1 || { 30 | echo 31 | echo "You must have automake installed to compile $package." 32 | echo "Download the appropriate package for your system," 33 | echo "or get the source from one of the GNU ftp sites" 34 | echo "listed in http://www.gnu.org/order/ftp.html" 35 | DIE=1 36 | } 37 | 38 | (pkg-config --version) < /dev/null > /dev/null 2>&1 || { 39 | echo 40 | echo "You must have pkg-config installed to compile $package." 41 | echo "Download the appropriate package for your system," 42 | echo "or get the source from http://pkgconfig.freedesktop.org/" 43 | DIE=1 44 | } 45 | 46 | 47 | if test "$DIE" -eq 1; then 48 | exit 1 49 | fi 50 | 51 | 52 | 53 | echo "Generating configuration files for $package, please wait...." 54 | 55 | run_cmd() { 56 | echo " running $* ..." 57 | if ! $*; then 58 | echo failed! 59 | exit 1 60 | fi 61 | } 62 | 63 | 64 | # Because git doesn't support empty directories 65 | if [ ! -d "$srcdir/build-scripts" ]; then 66 | mkdir "$srcdir/build-scripts" 67 | fi 68 | 69 | run_cmd aclocal 70 | run_cmd autoheader 71 | run_cmd automake --add-missing --copy 72 | run_cmd autoconf 73 | 74 | 75 | $srcdir/configure && echo 76 | -------------------------------------------------------------------------------- /perl/lib/Audio/JackMiniMix.pm: -------------------------------------------------------------------------------- 1 | package Audio::JackMiniMix; 2 | 3 | ################ 4 | # 5 | # JackMiniMix: perl control interface 6 | # 7 | # Copyright 2005 Nicholas J. Humfrey 8 | # 9 | 10 | use Carp; 11 | 12 | use Net::LibLO; 13 | use strict; 14 | 15 | use vars qw/$VERSION $ATTEMPTS/; 16 | 17 | $VERSION="0.02"; 18 | $ATTEMPTS=5; 19 | 20 | 21 | sub new { 22 | my $class = shift; 23 | 24 | croak( "Missing JackMiniMix server port or URL" ) if (scalar(@_)<1); 25 | 26 | # Bless the hash into an object 27 | my $self = { 28 | channel_count => 0, 29 | channels => {}, 30 | pong => 0 31 | }; 32 | bless $self, $class; 33 | 34 | # Create address of JackMiniMix server 35 | $self->{addr} = new Net::LibLO::Address( @_ ); 36 | if (!defined $self->{addr}) { 37 | carp("Error creating Net::LibLO::Address"); 38 | return undef; 39 | } 40 | 41 | # Create new LibLO instance 42 | $self->{lo} = new Net::LibLO(); 43 | if (!defined $self->{lo}) { 44 | carp("Error creating Net::LibLO"); 45 | return undef; 46 | } 47 | 48 | # Add reply handlers 49 | $self->{lo}->add_method( '/mixer/channel/gain', 'if', \&_channel_gain_handler, $self ); 50 | $self->{lo}->add_method( '/mixer/channel/label', 'is', \&_channel_label_handler, $self ); 51 | $self->{lo}->add_method( '/mixer/channel_count', 'i', \&_channel_count_handler, $self ); 52 | $self->{lo}->add_method( '/pong', '', \&_pong_handler, $self ); 53 | 54 | # Get the number of channels 55 | if (!$self->channel_count()) { 56 | carp("JackMiniMix server is not responding"); 57 | return undef; 58 | } 59 | 60 | return $self; 61 | } 62 | 63 | sub channel_count { 64 | my $self=shift; 65 | $self->{channel_count} = 0; 66 | $self->_wait_reply( '/mixer/get_channel_count' ); 67 | return $self->{channel_count}; 68 | } 69 | 70 | sub _channel_count_handler { 71 | my ($serv, $mesg, $path, $typespec, $userdata, @params) = @_; 72 | $userdata->{channel_count}=$params[0]; 73 | return 0; # Success 74 | } 75 | 76 | sub get_channel_gain { 77 | my $self=shift; 78 | my ($channel) = @_; 79 | croak "Total number of channels is unknown" unless ($self->{channel_count}); 80 | $self->{channels}->{$channel}->{gain} = undef; 81 | $self->_wait_reply( '/mixer/channel/get_gain', 'i', $channel ); 82 | return $self->{channels}->{$channel}->{gain}; 83 | } 84 | 85 | sub set_channel_gain { 86 | my $self=shift; 87 | my ($channel,$gain) = @_; 88 | croak "Total number of channels is unknown" unless ($self->{channel_count}); 89 | $self->_wait_reply( '/mixer/channel/set_gain', 'if', $channel, $gain ); 90 | return 1 if ($self->{channels}->{$channel}->{gain} == $gain); 91 | return 0; # Failed 92 | } 93 | 94 | sub _channel_gain_handler { 95 | my ($serv, $mesg, $path, $typespec, $userdata, @params) = @_; 96 | my ($channel, $gain) = @params; 97 | 98 | # Check channel exists 99 | if (!exists $userdata->{channels}->{$channel}) { 100 | $userdata->{channels}->{$channel} = {}; 101 | } 102 | 103 | # Store the gain 104 | $userdata->{channels}->{$channel}->{gain} = $gain; 105 | 106 | return 0; # Success 107 | } 108 | 109 | 110 | sub get_channel_label { 111 | my $self=shift; 112 | my ($channel) = @_; 113 | croak "Total number of channels is unknown" unless ($self->{channel_count}); 114 | $self->{channels}->{$channel}->{label} = undef; 115 | $self->_wait_reply( '/mixer/channel/get_label', 'i', $channel ); 116 | return $self->{channels}->{$channel}->{label}; 117 | } 118 | 119 | sub set_channel_label { 120 | my $self=shift; 121 | my ($channel,$label) = @_; 122 | croak "Total number of channels is unknown" unless ($self->{channel_count}); 123 | $self->_wait_reply( '/mixer/channel/set_label', 'is', $channel, $label ); 124 | return 1 if ($self->{channels}->{$channel}->{label} == $label); 125 | return 0; # Failed 126 | } 127 | 128 | sub _channel_label_handler { 129 | my ($serv, $mesg, $path, $typespec, $userdata, @params) = @_; 130 | my ($channel, $label) = @params; 131 | 132 | # Check channel exists 133 | if (!exists $userdata->{channels}->{$channel}) { 134 | $userdata->{channels}->{$channel} = {}; 135 | } 136 | 137 | # Store the label 138 | $userdata->{channels}->{$channel}->{label} = $label; 139 | 140 | return 0; # Success 141 | } 142 | 143 | sub ping { 144 | my $self=shift; 145 | $self->{pong} = 0; 146 | $self->_wait_reply( '/ping' ); 147 | return $self->{pong}; 148 | } 149 | 150 | sub _pong_handler { 151 | my ($serv, $mesg, $path, $typespec, $userdata, @params) = @_; 152 | $userdata->{pong}++; 153 | return 0; # Success 154 | } 155 | 156 | sub get_url { 157 | my $self=shift; 158 | return $self->{addr}->get_url(); 159 | } 160 | 161 | 162 | sub _wait_reply { 163 | my $self=shift; 164 | my (@args) = @_; 165 | my $bytes = 0; 166 | 167 | # Throw away any old incoming messages 168 | for(1..$ATTEMPTS) { $self->{lo}->recv_noblock( 0 ); } 169 | 170 | # Try a few times 171 | for(1..$ATTEMPTS) { 172 | 173 | # Send Query 174 | my $result = $self->{lo}->send( $self->{addr}, @args ); 175 | if ($result<1) { 176 | warn "Failed to send message (".join(',',@args)."): ".$self->{addr}->errstr()."\n"; 177 | sleep(1); 178 | next; 179 | } 180 | 181 | # Wait for reply within one second 182 | $bytes = $self->{lo}->recv_noblock( 1000 ); 183 | if ($bytes<1) { 184 | warn "Timed out waiting for reply after one second.\n"; 185 | } else { last; } 186 | } 187 | 188 | # Failed to get reply ? 189 | if ($bytes<1) { 190 | warn "Failed to get reply from JackMiniMix server after $ATTEMPTS attempts.\n"; 191 | } 192 | 193 | return $bytes; 194 | } 195 | 196 | 197 | 1; 198 | 199 | __END__ 200 | 201 | =pod 202 | 203 | =head1 NAME 204 | 205 | Audio::JackMiniMix - Talk to JACK Mini Mixer using OSC 206 | 207 | =head1 SYNOPSIS 208 | 209 | use Audio::JackMiniMix; 210 | 211 | my $mix = new Audio::JackMiniMix('osc.udp://host.example.net:3450/'); 212 | $mix->set_channel_gain( 1, -50 ); 213 | $mix->set_channel_gain( 2, -90 ); 214 | 215 | 216 | =head1 DESCRIPTION 217 | 218 | The Audio::JackMiniMix module uses Net::LibLO to talk to a JackMiniMix server. 219 | It can be used to get and set the gains and labels for the channels of the mixer. 220 | 221 | =over 4 222 | 223 | =item B 224 | 225 | Connect to JackMiniMix process specified by C. 226 | A channel_count() query is sent to the mixer, if the mixer does not 227 | respond, then undef is returned. 228 | 229 | 230 | =item B 231 | 232 | Returns the number of stereo input channels that the mixer has. 233 | 234 | 235 | =item B 236 | 237 | Returns the gain (in decibels) of channel. 238 | 239 | C is the number of the channel (in range 1 to total number of channels). 240 | 241 | 242 | =item B 243 | 244 | Sets the gain of channel C to C dB. 245 | 246 | C is the number of the channel (in range 1 to total number of channels). 247 | 248 | C is the gain (in decibels) to set the channel to (in range -90 to 90 dB). 249 | 250 | 251 | =item B 252 | 253 | Returns the label (string) of channel number C. 254 | 255 | C is the number of the channel (in range 1 to total number of channels). 256 | 257 | 258 | =item B 259 | 260 | Sets the label (string) of channel number C to C