Browse Source

Merge branch 'develop'

master kmxtool-0.3.0
Damien Goutte-Gattat 5 years ago
parent
commit
343dc3698a
  1. 21
      Makefile.am
  2. 8
      NEWS
  3. 49
      README
  4. 117
      README.md
  5. 7
      configure.ac
  6. 8
      lib/Makefile.am
  7. 20
      lib/hexio.c
  8. 79
      lib/xmem.c
  9. 52
      lib/xmem.h
  10. 1
      man/Makefile.am
  11. 6
      man/kmxtool.1.in
  12. 9
      src/Makefile.am
  13. 11
      src/asysex.c
  14. 39
      src/kmxtool.c
  15. 35
      src/microx.c
  16. 14
      src/microx.h
  17. 73
      src/midi.c
  18. 7
      src/sysex.c
  19. 5
      src/sysex.h

21
Makefile.am

@ -1,7 +1,22 @@
SUBDIRS = lib src man
ACLOCAL_AMFLAGS = -I m4 --install
dist_doc_DATA = AUTHORS COPYING NEWS README
dist_doc_DATA = AUTHORS COPYING NEWS README.md
EXTRA_DIST = Doxyfile
convlib_sources = lib/err.compat.h lib/compat.h lib/hexio.c lib/hexio.h
common_sources = src/midi.c src/midi.h src/sysex.c src/sysex.h \
$(convlib_sources)
bin_PROGRAMS = asysex kmxtool
asysex_SOURCES = src/asysex.c src/manufacturers.h $(common_sources)
kmxtool_SOURCES = src/kmxtool.c src/microx.c src/microx.h $(common_sources)
DEFS = -DEXIT_ON_ENOMEM @DEFS@
AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/src
LDADD = $(LIBOBJS)
dist_man_MANS = man/asysex.1 man/kmxtool.1

8
NEWS

@ -1,3 +1,11 @@
Chanes in kmxtools 0.3.0
* Fix crash in the absence of MIDI ports.
* Fix crash in the presence of multiple raw MIDI devices.
* Fix detection of GLOBAL mode.
* Detect the correct global MIDI channel to use.
Changes in kmxtools 0.2.0
* List programs on the microX.

49
README

@ -1,49 +0,0 @@
kmxtool - KORG microX utility
=============================
Description
-----------
Kmxtool is a program to interact with a KORG microX synthesizer. It
allows to dump/load data from/to the synth and to query its current
status.
Kmxtool comes bundled with the asysex program, from which it is derived.
Asysex is a generic (non KORG-specific) tool for emitting and receiving
System Exclusive (SysEx) MIDI messages. It reads a SysEx message from
its standard input and sends it to a MIDI device, then receives a single
SysEx message in response (if any) and prints it to standard output.
Copying
-------
Kmxtool is distributed under the terms of the GNU General Public
License, version 3 or higher. The full license is included in the
COPYING file of the source distribution.
Homepage and contact
--------------------
The project homepage, where release tarballs may be found, is located at
<http://www.incenp.org/dvlpt/kmxtool.html>. The repository containing
the latest source code is available at <git://git.incenp.org/kmxtool.git>.
To contact the author, use the following address:
Damien Goutte-Gattat <dgouttegattat@incenp.org>
MIDI backends
-------------
Kmxtool and asysex currently support ALSA and OSS MIDI backends. Please
note that as I only use ALSA, the OSS backend has only been tested
against the ALSA emulation layer for OSS; it *does* work against the
emulated OSS, so I expect it should also work against a real OSS, but I
cannot guarantee that.
MIDI backends available on the target system are enabled by default; if
support for a given backend is not wanted, use the corresponding
`--disable-{alsa,oss}' option at configure time.
When the `-p, --port` option is used, the name of the MIDI port
determines which backend is used. For example, `/dev/midi00` selects the
OSS backend, while `hw:1,0,0' selects the ALSA backend.

117
README.md

@ -0,0 +1,117 @@
kmxtool - KORG microX utility
=============================
Kmxtool is a command-line utility to interact with a KORG microX
synthesizer. It allows to dump and load data from and to the synth, to
query the synth’s status, and to list available Programs.
Kmxtool comes bundled with the asysex program, from which it is derived;
asysex is a generic (non KORG-specific) tool for emitting and receiving
System Exclusive (SysEx) MIDI messages. It reads a SysEx message from
its standard input and sends it to a MIDI device, then receives a single
SysEx message in response (if any) and prints it to standard output.
Usage
-----
Kmxtool uses either ALSA or OSS to access the hardware MIDI ports; it
runs at least on GNU/Linux and should run on most Unix-like systems with
an OSS-compatible interface.
If called without the `-p` option to explicitly specify a MIDI port to
use, kmxtool will scan all available ports until it finds a device
announcing itself as a microX synthesizer.
The default behavior of kmxtool is to print the current status of the
synthesizer:
$ kmxtool
KORG microX synthesizer, version 01.00.00.04
Global channel: 0
Active mode: MULTI
Status of Global mode:
Local Control: No
Clock Source: AUTO
Bank Map: GM
Memorize Mode on Power On: On
Rec. Ext.Realtime Command: Yes
Enable Program Change: Yes
[...]
### Dumping parameter data
With the `-d` option, you specify the memory slot that you want to dump
from the microX to your computer. Dumped data is written to standard
output in hexdump’s “canonical hex+ASCII” format.
$ kmxtool -d PC7
00000000 47 6f 73 70 65 6c 20 50 65 72 63 4f 72 67 61 6e |Gospel PercOrgan|
00000010 c4 32 65 34 65 32 31 32 64 11 1c 09 1b 9c 78 04 |.2e4e212d.....x.|
00000020 28 40 02 00 40 00 7f 7f 08 41 83 e7 01 8c f1 c5 |.@..@...0A......|
[...]
A memory slot is identified by:
- an uppercase letter indicating the type of slot (`P` for programs, `C`
for combinations, `M` for multis, `D` for drumkits, `A` for arpeggio
patterns, and `E` for external controllers sets);
- (only for programs and combinations) an uppercase letter indicating
the bank, or an asterisk to dump all programs or combinations in all
banks;
- up to three decimal digits indicating the slot number, or an asterisk
to dump all slots in the given bank (for programs and combinations) or
all slots of the given type (for multis, drumkits, arpeggio patterns
and external controllers sets).
The following table gives some examples of memory slot specifications:
| Argument of `-d` | Meaning |
| ---------------- | ----------------------------------------------------- |
| PA78 | dump parameter data for program #78 in bank A |
| PE\* | dump parameter data for all programs in bank E |
| CB50 | dump parameter for combination #50 in bank B |
| C\* | dump parameter data for all combinations in all banks |
| M108 | dump parameter data for multi #108 |
| D\* | dump parameter data for all drumkits |
### Loading parameter data
The `-l` option performs the opposite of `-d`, that is, loads parameter
data (read from standard input in the same “canonical hex+ASCII” format)
from your computer to a specified memory slot on the microX.
The target memory slot is specified in the same way as for the `-d`
option, except that asterisks are forbidden—you can only load a single
slot at a time, loading an entire bank is not supported.
MIDI backends
-------------
Kmxtool and asysex currently support ALSA and OSS MIDI backends. Please
note that as I only use ALSA, the OSS backend has only been tested
against the ALSA emulation layer for OSS; it *does* work against the
emulated OSS, so I expect it should also work against a real OSS, but I
cannot guarantee that.
MIDI backends available on the target system are enabled by default; if
support for a given backend is not wanted, use the corresponding
`--disable-{alsa,oss}' option at configure time.
When the `-p, --port` option is used, the name of the MIDI port
determines which backend is used. For example, `/dev/midi00` selects the
OSS backend, while `hw:1,0,0' selects the ALSA backend.
Copying
-------
Kmxtool is distributed under the terms of the GNU General Public
License, version 3 or higher. The full license is included in the
[COPYING file](COPYING) of the source distribution.
Homepage and contact
--------------------
The project homepage, where release tarballs may be found, is located at
<http://www.incenp.org/dvlpt/kmxtool.html>. The repository containing
the latest source code is available at <git://git.incenp.org/kmxtool.git>.
To contact the author, use the following address:
Damien Goutte-Gattat <dgouttegattat@incenp.org>

7
configure.ac

@ -1,6 +1,6 @@
dnl Configure template for the kmxtool package
AC_INIT([KORG microX utility], [0.2.0],
AC_INIT([KORG microX utility], [0.3.0],
[dgouttegattat@incenp.org], [kmxtool])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])
@ -8,7 +8,7 @@ AC_CONFIG_AUX_DIR([config])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_LIBOBJ_DIR([lib])
AC_USE_SYSTEM_EXTENSIONS
AM_INIT_AUTOMAKE([foreign])
AM_INIT_AUTOMAKE([foreign subdir-objects silent-rules])
dnl Check for development tools
AC_PROG_CC
@ -75,8 +75,7 @@ AC_DEFINE_UNQUOTED([DEFAULT_MIDI_PORT], ["$midi_default_port"],
AC_SUBST([DEFAULT_MIDI_PORT], [$midi_default_port])
dnl Output files
AC_CONFIG_FILES([Makefile lib/Makefile src/Makefile
man/Makefile man/asysex.1 man/kmxtool.1])
AC_CONFIG_FILES([Makefile man/asysex.1 man/kmxtool.1])
AC_OUTPUT
dnl Summary

8
lib/Makefile.am

@ -1,8 +0,0 @@
noinst_LIBRARIES = libcvasysex.a
libcvasysex_a_SOURCES = err.compat.h compat.h xmem.c xmem.h \
hexio.c hexio.h
libcvasysex_a_LIBADD = $(LIBOBJS)
DEFS = -DEXIT_ON_ENOMEM @DEFS@

20
lib/hexio.c

@ -26,16 +26,13 @@
#include <errno.h>
#include <ctype.h>
#ifdef EXIT_ON_ENOMEM
#include <xmem.h>
#endif
#define BLOCK_SIZE 512
int
fprinthd(FILE *f, unsigned char *buffer, size_t len, unsigned offset)
{
int i, j, n;
unsigned int i, j;
int n;
if ( ! f || ! buffer ) {
errno = EINVAL;
@ -70,7 +67,8 @@ fprinthd(FILE *f, unsigned char *buffer, size_t len, unsigned offset)
int
fprinth(FILE *f, unsigned char *buffer, size_t len)
{
int i, n;
unsigned int i;
int n;
if ( ! f || ! buffer ) {
errno = EINVAL;
@ -183,10 +181,6 @@ freadha(FILE *f, unsigned char **buffer, size_t *len)
while ( (n = freadh(f, buf, sizeof(buf))) > 0 ) {
if ( *len < m + n ) {
#ifdef EXIT_ENOMEM
*len += BLOCK_SIZE;
*buffer = xrealloc(*buffer, *len);
#else
unsigned char *p;
if ( ! (p = realloc(*buffer, *len + BLOCK_SIZE)) )
@ -194,7 +188,6 @@ freadha(FILE *f, unsigned char **buffer, size_t *len)
*buffer = p;
*len += BLOCK_SIZE;
#endif
}
memcpy(*buffer + m, buf, n);
m += n;
@ -279,10 +272,6 @@ freadhda(FILE *f, unsigned char **buffer, size_t *len)
while ( (n = freadhd(f, buf, sizeof(buf), &s)) > 0 ) {
if ( *len < m + n ) {
#ifdef EXIT_ENOMEM
*len += BLOCK_SIZE;
*buffer = xrealloc(*buffer, *len);
#else
unsigned char *p;
if ( ! (p = realloc(*buffer, *len + BLOCK_SIZE)) )
@ -290,7 +279,6 @@ freadhda(FILE *f, unsigned char **buffer, size_t *len)
*buffer = p;
*len += BLOCK_SIZE;
#endif
}
memcpy(*buffer + m, buf, n);
m += n;

79
lib/xmem.c

@ -1,79 +0,0 @@
/*
* xmem - Incenp.org Notch Library: die-on-error memory functions
* Copyright (C) 2011 Damien Goutte-Gattat
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <xmem.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
void (*xmem_error)(const char *, unsigned int) = NULL;
#define mem_error(f, l) \
do { \
if ( xmem_error ) \
(*xmem_error)((f), (l)); \
err(EXIT_FAILURE, "%s, %d", (f), (l)); \
} while ( 0 )
void *
do_malloc(size_t s, const char *file, unsigned int line)
{
void *p;
if ( ! (p = malloc(s)) && s )
mem_error(file, line);
return p;
}
void *
do_calloc(size_t n, size_t s, const char *file, unsigned int line)
{
void *p;
if ( ! (p = calloc(n, s)) && n && s )
mem_error(file, line);
return p;
}
void *
do_realloc(void *p, size_t s, const char *file, unsigned int line)
{
void *np;
if ( ! (np = realloc(p, s)) && s )
mem_error(file, line);
return np;
}
char *
do_strdup(const char *s, const char *file, unsigned int line)
{
char *dup;
if ( ! (dup = strdup(s)) && s )
mem_error(file, line);
return dup;
}

52
lib/xmem.h

@ -1,52 +0,0 @@
/*
* xmem - Incenp.org Notch Library: die-on-error memory functions
* Copyright (C) 2011 Damien Goutte-Gattat
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef ICP20110203_XMEM_H
#define ICP20110203_XMEM_H
#include <stdlib.h>
#include <stdarg.h>
#ifdef __cpluscplus
extern "C" {
#endif
extern void (*xmem_error)(const char *, unsigned int);
void *
do_malloc(size_t, const char *, unsigned int);
void *
do_calloc(size_t, size_t, const char *, unsigned int);
void *
do_realloc(void *, size_t, const char *, unsigned int);
char *
do_strdup(const char *, const char *, unsigned int);
#define xmalloc(s) do_malloc(s, __FILE__, __LINE__)
#define xcalloc(n,s) do_calloc(n, s, __FILE__, __LINE__)
#define xrealloc(p,s) do_realloc(p, s, __FILE__, __LINE__)
#define xstrdup(s) do_strdup(s, __FILE__, __LINE__)
#ifdef __cplusplus
}
#endif
#endif /* !ICP20110203_XMEM_H */

1
man/Makefile.am

@ -1 +0,0 @@
dist_man_MANS = asysex.1 kmxtool.1

6
man/kmxtool.1.in

@ -10,6 +10,7 @@ kmxtool - KORG microX Utility
.RB [ \-p | --port
.IR port ]
.RB [ \-s | --status ]
.RB [ \-L | --list-programs ]
.RB [ \-d | --dump-data
.IR id ]
.RB [ \-l | --load-data
@ -47,6 +48,9 @@ to all available MIDI ports to detect a microX synthesizer.
Print the current status of the synthesizer. This is
the default mode of operation.
.TP
.BR -L ", " --list-programs
Print a list of all programs in all banks.
.TP
.BR -d ", " --dump-data " " \fIid\fR
Dump the specified memory slot to standard output.
.TP
@ -100,7 +104,7 @@ Damien Goutte-Gattat
.SH COPYRIGHT
.ad l
.PP
Copyright \(co 2012,2013 Damien Goutte-Gattat
Copyright \(co 2012,2013,2016 Damien Goutte-Gattat
.PP
This program is released under the GNU General Public License.
See the COPYING file in the source distribution or

9
src/Makefile.am

@ -1,9 +0,0 @@
bin_PROGRAMS = asysex kmxtool
asysex_SOURCES = asysex.c midi.h midi.c sysex.h sysex.c manufacturers.h
kmxtool_SOURCES = kmxtool.c microx.c microx.h midi.c midi.h sysex.c sysex.h
AM_CPPFLAGS = -I$(top_srcdir)/lib
AM_LDFLAGS = -L$(top_builddir)/lib
LDADD = -lcvasysex

11
src/asysex.c

@ -1,6 +1,6 @@
/*
* asysex - A SysEx Utility
* Copyright (C) 2012 Damien Goutte-Gattat
* Copyright (C) 2012,2016 Damien Goutte-Gattat
*
* 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
@ -24,9 +24,9 @@
#include <stdlib.h>
#include <locale.h>
#include <getopt.h>
#include <err.h>
#include <sysex.h>
#include <xmem.h>
#include <hexio.h>
#define ASYSEX_MODE_QUERY 0x00
@ -75,7 +75,7 @@ info(void)
{
printf("\
asysex %s\n\
Copyright (C) 2012 Damien Goutte-Gattat\n\
Copyright (C) 2012,2016 Damien Goutte-Gattat\n\
\n\
This program is released under the GNU General Public License.\n\
See the COPYING file or <http://www.gnu.org/licenses/gpl.html>.\n\
@ -129,7 +129,7 @@ do_query(midi_io_t *midi, FILE *in, FILE *out, print_midi_fn_t print_midi)
n = freadha(in, &query, NULL);
if ( n < 2 || query[0] != 0xF0 || query[n-1] != 0xF7 )
errx(EXIT_FAILURE, "invalid SysEx input (%d)", n);
errx(EXIT_FAILURE, "invalid SysEx input (%lu)", n);
if ( (n = midi_write(midi, query, n)) < 0 )
errx(EXIT_FAILURE, "cannot send MIDI data");
@ -168,7 +168,8 @@ identify_device(midi_io_t *midi)
int
main(int argc, char **argv)
{
char c, *port;
char c;
const char *port;
int mode;
print_midi_fn_t print_midi;

39
src/kmxtool.c

@ -1,6 +1,6 @@
/*
* kmxtool - KORG microX utility
* Copyright (C) 2012,2013 Damien Goutte-Gattat
* Copyright (C) 2012,2013,2016 Damien Goutte-Gattat
*
* 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
@ -27,7 +27,6 @@
#include <err.h>
#include <hexio.h>
#include <xmem.h>
#include <microx.h>
@ -39,6 +38,7 @@
/* Globals. */
static midi_io_t *midi = NULL;
static unsigned channel = 0;
/* Help and informations about the program. */
@ -80,7 +80,7 @@ info(void)
{
printf("\
kmxtool %s\n\
Copyright (C) 2012,2013 Damien Goutte-Gattat\n\
Copyright (C) 2012,2013,2016 Damien Goutte-Gattat\n\
\n\
This program is released under the GNU General Public License.\n\
See the COPYING file or <http://www.gnu.org/licenses/gpl.html>.\n\
@ -104,12 +104,12 @@ cleanup(void)
static void
print_microx_status(struct kmx_microx_status *s)
{
static char *modes[] = { "COMBI PLAY", "COMBI EDIT", "PROG PLAY",
"PROG EDIT", "MULTI", "GLOBAL" };
static char *clock[] = { "Internal", "Ext-MIDI", "Ext-USB", "AUTO" };
static char *flter[] = { "All", "Odd", "Even" };
static char *yesno[] = { "No", "Yes" };
static char *bnkmp[] = { "KORG", "GM" };
static const char *modes[] = { "COMBI PLAY", "COMBI EDIT", "PROG PLAY",
"PROG EDIT", "MULTI", "", "GLOBAL" };
static const char *clock[] = { "Internal", "Ext-MIDI", "Ext-USB", "AUTO" };
static const char *flter[] = { "All", "Odd", "Even" };
static const char *yesno[] = { "No", "Yes" };
static const char *bnkmp[] = { "KORG", "GM" };
printf("Global channel: %d\n", s->global_channel);
printf("Active mode: %s\n",
@ -165,9 +165,10 @@ do_list_programs(midi_io_t *midi)
dump.bank = KMX_MICROX_DUMP_ALL;
len = kmx_microx_get_dump_size(&dump);
reply = xmalloc(len);
if ( ! (reply = malloc(len)) )
err(EXIT_FAILURE, "cannot dump data");
if ( (n = kmx_microx_dump(midi, &dump, reply, len)) < 0 )
if ( (n = kmx_microx_dump(midi, channel, &dump, reply, len)) < 0 )
errx(EXIT_FAILURE, "cannot dump data: %s", kmx_microx_error(midi, n));
for ( cursor = reply, bank = 'A'; bank < 'F'; bank++ ) {
@ -194,7 +195,7 @@ find_microx_on_port(const char *port,
ret = -1;
if ( (midi = midi_open(port)) != NULL ) {
if ( (e = kmx_microx_identify(midi, version)) == 0 )
if ( (e = kmx_microx_identify(midi, version, &channel)) == 0 )
ret = 0;
else {
midi_close(midi);
@ -237,7 +238,7 @@ main(int argc, char **argv)
setlocale(LC_ALL, "");
atexit(cleanup);
port = NULL;
port = param = NULL;
mode = MODE_STATUS;
while ( (c = getopt_long(argc, argv, "hvp:sd:l:L",
@ -287,6 +288,9 @@ main(int argc, char **argv)
ports = midi_get_ports();
if ( ! ports )
errx(EXIT_FAILURE, "no MIDI ports available");
for ( p = ports, found = 0; *p != NULL; p++ ) {
if ( ! found )
found = find_microx_on_port(*p, &version, 1) != -1;
@ -302,7 +306,7 @@ main(int argc, char **argv)
printf("KORG microX synthesizer, version %02d.%02d.%02d.%02d\n",
version.major, version.minor, version.release, version.build);
if ( (e = kmx_microx_query_status(midi, &status)) < 0 )
if ( (e = kmx_microx_query_status(midi, channel, &status)) < 0 )
errx(EXIT_FAILURE, "cannot query microX status: %s",
kmx_microx_error(midi, e));
@ -317,9 +321,10 @@ main(int argc, char **argv)
errx(EXIT_FAILURE, "invalid dump request: %s", param);
n = kmx_microx_get_dump_size(&dump);
data = xmalloc(n);
if ( ! (data = malloc(n)) )
err(EXIT_FAILURE, "cannot dump data");
if ( (n = kmx_microx_dump(midi, &dump, data, n)) < 0 )
if ( (n = kmx_microx_dump(midi, channel, &dump, data, n)) < 0 )
errx(EXIT_FAILURE, "cannot dump data: %s",
kmx_microx_error(midi, n));
@ -338,7 +343,7 @@ main(int argc, char **argv)
if ( n < 1 )
err(EXIT_FAILURE, "cannot read data");
if ( (n = kmx_microx_load(midi, &dump, data, n)) < 0 )
if ( (n = kmx_microx_load(midi, channel, &dump, data, n)) < 0 )
errx(EXIT_FAILURE, "cannot load data: %s",
kmx_microx_error(midi, n));
}

35
src/microx.c

@ -1,6 +1,6 @@
/*
* kmxtool - KORG microX utility
* Copyright (C) 2012,2013 Damien Goutte-Gattat
* Copyright (C) 2012,2013,2016 Damien Goutte-Gattat
*
* 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
@ -41,6 +41,9 @@
* @param[out] version A pointer to a kmx_microx_version structure
* to be filled in with informations from the
* device; may be @c NULL.
* @param[out] global A pointer to an integer to receive the
* global MIDI channel used by the microX;
* may be @c NULL.
*
* @return
* - @e KMX_OK if the port is connected to a device which
@ -54,7 +57,8 @@
*/
int
kmx_microx_identify(midi_io_t *midi,
struct kmx_microx_version *version)
struct kmx_microx_version *version,
unsigned int *global)
{
int n;
midi_device_id_t devid;
@ -77,6 +81,9 @@ kmx_microx_identify(midi_io_t *midi,
version->build = (devid.version >> 24) & 0xFF;
}
if ( global )
*global = devid.global_channel;
return KMX_OK;
}
@ -86,6 +93,7 @@ kmx_microx_identify(midi_io_t *midi,
* synthesizer.
*
* @param[in] midi The MIDI port.
* @param[int] chan The global MIDI channel.
* @param[out] status A pointer to a kmx_microx_status structure
* to be filled in with the status data
* received from the microX; may be @c NULL.
@ -98,6 +106,7 @@ kmx_microx_identify(midi_io_t *midi,
*/
int
kmx_microx_query_status(midi_io_t *midi,
unsigned int chan,
struct kmx_microx_status *s)
{
ssize_t n;
@ -109,6 +118,10 @@ kmx_microx_query_status(midi_io_t *midi,
0x12, /* Mode and state request */
0xF7 /* SysEx message end */ };
fprintf(stderr, "querying status on channel %d\n", chan);
query[2] |= chan & 0xF;
if ( (n = sysex_query(midi, query, sizeof(query),
reply, sizeof(reply))) == -1 )
return KMX_IO_ERROR;
@ -508,6 +521,10 @@ kmx_microx_get_dump_size(struct kmx_microx_dump *dump)
if ( dump->program == KMX_MICROX_DUMP_ALL )
s *= MICROX_N_EXTSET;
break;
default: /* Should never happen. */
s = 0;
break;
}
return s;
@ -633,8 +650,8 @@ kmx_microx_read_dump(midi_io_t *midi,
unsigned char *data,
size_t len)
{
size_t n;
int i, j, k, m;
ssize_t n;
unsigned i, j, k, m;
unsigned char reply[1024];
j = k = m = 0;
@ -694,6 +711,7 @@ kmx_microx_read_dump(midi_io_t *midi,
* in reply.
*
* @param[in] midi The MIDI port.
* @param[in] chan The global MIDI channel.
* @param[in] dump A kmx_microx_dump structure representing
* the dump request.
* @param[out] data The buffer where to store the dump.
@ -711,11 +729,12 @@ kmx_microx_read_dump(midi_io_t *midi,
*/
int
kmx_microx_dump(midi_io_t *midi,
unsigned int chan,
struct kmx_microx_dump *dump,
unsigned char *data,
size_t len)
{
size_t n;
ssize_t n;
unsigned char query[] = { 0xF0, /* SysEx message begin */
0x42, /* KORG manufacturer ID */
0x30, /* Global channel */
@ -726,6 +745,8 @@ kmx_microx_dump(midi_io_t *midi,
0x00, /* Dump parameter 3 */
0xF7 /* SysEx message end */ };
query[2] |= chan & 0xF;
if ( get_dump_parameters(dump, &(query[4])) == KMX_INVALID_QUERY )
return KMX_INVALID_QUERY;
@ -744,6 +765,7 @@ kmx_microx_dump(midi_io_t *midi,
* the microX synthesizer.
*
* @param[in] midi The MIDI port.
* @param[in] chan The global MIDI channel.
* @param[in] dump A kmx_microx_dump structure indicating the
* memory slot to load the data into.
* @param[in] data The data to load.
@ -767,6 +789,7 @@ kmx_microx_dump(midi_io_t *midi,
*/
int
kmx_microx_load(midi_io_t *midi,
unsigned int chan,
struct kmx_microx_dump *dump,
unsigned char *data,
size_t len)
@ -783,6 +806,8 @@ kmx_microx_load(midi_io_t *midi,
0x00, /* Dump parameter 3 */ };
unsigned char reply[7];
buffer[2] |= chan & 0xF;
if ( get_dump_parameters(dump, &(buffer[4])) == KMX_INVALID_QUERY )
return KMX_INVALID_QUERY;

14
src/microx.h

@ -1,6 +1,6 @@
/*
* kmxtool - KORG microX utility
* Copyright (C) 2012,2013 Damien Goutte-Gattat
* Copyright (C) 2012,2013,2016 Damien Goutte-Gattat
*
* 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
@ -94,7 +94,7 @@ enum kmx_microx_mode
PROG_PLAY,
PROG_EDIT,
MULTI,
GLOBAL,
GLOBAL = 0x06,
DEMO = 0x7F
};
@ -185,10 +185,14 @@ extern "C" {
#endif
int
kmx_microx_identify(midi_io_t *, struct kmx_microx_version *);
kmx_microx_identify(midi_io_t *,
struct kmx_microx_version *,
unsigned int *);
int
kmx_microx_query_status(midi_io_t *, struct kmx_microx_status *);
kmx_microx_query_status(midi_io_t *,
unsigned int,
struct kmx_microx_status *);
const char *
kmx_microx_error(midi_io_t *, int);
@ -208,12 +212,14 @@ kmx_microx_read_dump(midi_io_t *,
int
kmx_microx_dump(midi_io_t *,
unsigned int,
struct kmx_microx_dump *,
unsigned char *,
size_t);
int
kmx_microx_load(midi_io_t *,
unsigned int,
struct kmx_microx_dump *,
unsigned char *,
size_t );

73
src/midi.c

@ -1,6 +1,6 @@
/*
* asysex - A SysEx Utility
* Copyright (C) 2012,2013 Damien Goutte-Gattat
* Copyright (C) 2012,2013,2016 Damien Goutte-Gattat
*
* 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
@ -35,8 +35,6 @@
#include <stdlib.h>
#include <assert.h>
#include <xmem.h>
#ifdef HAVE_ALSA
#include <alsa/asoundlib.h>
#endif
@ -117,6 +115,16 @@ struct midi_io
#ifdef HAVE_ALSA
static int snd_config_updated = 0;
#define SND_CONFIG_UPDATE() \
do { \
if ( ! snd_config_updated ) { \
snd_config_update(); \
snd_config_updated = 1; \
} \
} while ( 0 )
static int
alsa_midi_close(midi_io_t *midi)
{
@ -136,7 +144,8 @@ alsa_midi_write(midi_io_t *midi, unsigned char *buffer, size_t len)
/* Flush reading buffer. */
midi->pos = midi->len = 0;
if ( (n = snd_rawmidi_write(midi->alsa.out, buffer, len)) != len ) {
if ( (n = snd_rawmidi_write(midi->alsa.out, buffer, len)) < 0 ||
(unsigned)n != len ) {
midi->error = n;
n = -1;
}
@ -175,7 +184,11 @@ alsa_midi_open(const char *name)
{
midi_io_t *midi;
midi = xmalloc(sizeof(*midi));
if ( ! (midi = malloc(sizeof(*midi))) )
return NULL;
SND_CONFIG_UPDATE();
midi->alsa.in = midi->alsa.out = NULL;
midi->error = midi->pos = midi->len = midi->status = 0;
@ -184,8 +197,8 @@ alsa_midi_open(const char *name)
midi->backend.read = alsa_midi_read;
midi->backend.error = alsa_midi_error;
if ( snd_rawmidi_open(&(midi->alsa.in), &(midi->alsa.out), name,
SND_RAWMIDI_NONBLOCK) < 0 ) {
if ( snd_rawmidi_open_lconf(&(midi->alsa.in), &(midi->alsa.out), name,
SND_RAWMIDI_NONBLOCK, snd_config) < 0 ) {
free(midi);
midi = NULL;
}
@ -203,25 +216,34 @@ alsa_midi_get_ports(char ***ports, size_t *n, size_t *max)
char name[32];
int card;
SND_CONFIG_UPDATE();
card = -1;
while ( snd_card_next(&card) >= 0 && card != -1 ) {
snd_ctl_t *ctl;
snprintf(name, sizeof(name), "hw:%d", card);
if ( snd_ctl_open(&ctl, name, 0) >= 0 ) {
if ( snd_ctl_open_lconf(&ctl, name, 0, snd_config) >= 0 ) {
int device;
device = -1;
while ( snd_ctl_rawmidi_next_device(ctl, &device) >= 0 && device >= 0 ) {
snprintf(name, sizeof(name), "hw:%d,%d", card, device);
if ( *n >= *max ) {
if ( *n + 1 >= *max ) {
char **tmp;
if ( ! (tmp = realloc(*ports, *max + 10)) )
goto err;
*ports = tmp;
*max += 10;
*ports = xrealloc(*ports, *max);
}
(*ports)[(*n)++] = xstrdup(name);
if ( ((*ports)[*n] = strdup(name)) )
*n += 1;
}
err:
snd_ctl_close(ctl);
}
}
@ -285,7 +307,9 @@ oss_midi_open(const char *name)
assert(name != NULL);
midi = xmalloc(sizeof(*midi));
if ( ! (midi = malloc(sizeof(*midi))) )
return NULL;
midi->oss.fd = -1;
midi->error = midi->pos = midi->len = midi->status = 0;
@ -312,7 +336,7 @@ static void
oss_midi_get_ports(char ***ports, size_t *n, size_t *max)
{
char name[32];
size_t k;
int k;
struct dirent **namelist;
if ( (k = scandir("/dev", &namelist, oss_midi_device, alphasort)) != -1 ) {
@ -320,11 +344,19 @@ oss_midi_get_ports(char ***ports, size_t *n, size_t *max)
snprintf(name, sizeof(name), "/dev/%s", namelist[k]->d_name);
free(namelist[k]);
if ( *n >= *max ) {
if ( *n + 1 >= *max ) {
char **tmp;
if ( ! (tmp = realloc(*ports, *max + 10)) )
goto err;
*max += 10;
*ports = xrealloc(*ports, *max);
*ports = tmp;
}
(*ports)[(*n)++] = xstrdup(name);
if ( ((*ports)[*n] = strdup(name)) )
*n += 1;
err:
;
}
}
}
@ -470,7 +502,7 @@ midi_error(midi_io_t *midi)
char **
midi_get_ports(void)
{
char **ports, name[32];
char **ports;
size_t n, max;
ports = NULL;
@ -483,11 +515,10 @@ midi_get_ports(void)
oss_midi_get_ports(&ports, &n, &max);
#endif
if ( n >= max ) {
max += 1;
ports = xrealloc(ports, max);
if ( ports ) {
assert (n < max);
ports[n] = NULL;
}
ports[n++] = NULL;
return ports;
}

7
src/sysex.c

@ -1,6 +1,6 @@
/*
* asysex - A SysEx Utility
* Copyright (C) 2012 Damien Goutte-Gattat
* Copyright (C) 2012,2016 Damien Goutte-Gattat
*
* 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
@ -56,7 +56,8 @@
ssize_t
sysex_read(midi_io_t *midi, unsigned char *data, size_t len)
{
int byte, loop, n, p;
int byte, loop;
unsigned n, p;
loop = 1;
n = p = 0;
@ -182,6 +183,8 @@ sysex_identify(midi_io_t *midi, midi_device_id_t *devid)
/* invalid reply */
return 0;
devid->global_channel = reply[2] & 0xF;
p = &reply[5];
devid->manufacturer = *p++;
if ( devid->manufacturer == 0x00 ) { /* extended manufacturer ID */

5
src/sysex.h

@ -1,6 +1,6 @@
/*
* asysex - A SysEx Utility
* Copyright (C) 2012 Damien Goutte-Gattat
* Copyright (C) 2012,2016 Damien Goutte-Gattat
*
* 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
@ -42,6 +42,9 @@ typedef struct midi_device_id
/** A version number for the device. */
unsigned int version;
/** The global MIDI channel used by this device. */
unsigned int global_channel;
} midi_device_id_t;
#ifdef __cpluscplus

Loading…
Cancel
Save