|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* ALSA hwdep SBI FM instrument loader
|
|
Packit Service |
b98cfc |
* Copyright (c) 2000 Uros Bizjak <uros@kss-loka.si>
|
|
Packit Service |
b98cfc |
*
|
|
Packit Service |
b98cfc |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
b98cfc |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
b98cfc |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit Service |
b98cfc |
* (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 |
* Oct. 2007 - Takashi Iwai <tiwai@suse.de>
|
|
Packit Service |
b98cfc |
* Changed to use hwdep instead of obsoleted seq-instr interface
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
#include <errno.h>
|
|
Packit Service |
b98cfc |
#include <getopt.h>
|
|
Packit Service |
b98cfc |
#include <stdio.h>
|
|
Packit Service |
b98cfc |
#include <stdlib.h>
|
|
Packit Service |
b98cfc |
#include <string.h>
|
|
Packit Service |
b98cfc |
#include <assert.h>
|
|
Packit Service |
b98cfc |
#include <unistd.h>
|
|
Packit Service |
b98cfc |
#include <fcntl.h>
|
|
Packit Service |
b98cfc |
#include <errno.h>
|
|
Packit Service |
b98cfc |
#include <alsa/asoundlib.h>
|
|
Packit Service |
b98cfc |
#include <alsa/sound/asound_fm.h>
|
|
Packit Service |
b98cfc |
#include <sys/time.h>
|
|
Packit Service |
b98cfc |
#include <sys/ioctl.h>
|
|
Packit Service |
b98cfc |
#include <unistd.h>
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
#define DATA_LEN_2OP 16
|
|
Packit Service |
b98cfc |
#define DATA_LEN_4OP 24
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* offsets for SBI params */
|
|
Packit Service |
b98cfc |
#define AM_VIB 0
|
|
Packit Service |
b98cfc |
#define KSL_LEVEL 2
|
|
Packit Service |
b98cfc |
#define ATTACK_DECAY 4
|
|
Packit Service |
b98cfc |
#define SUSTAIN_RELEASE 6
|
|
Packit Service |
b98cfc |
#define WAVE_SELECT 8
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* offset for SBI instrument */
|
|
Packit Service |
b98cfc |
#define CONNECTION 10
|
|
Packit Service |
b98cfc |
#define OFFSET_4OP 11
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* offsets for SBI extensions */
|
|
Packit Service |
b98cfc |
#define ECHO_DELAY 0
|
|
Packit Service |
b98cfc |
#define ECHO_ATTEN 1
|
|
Packit Service |
b98cfc |
#define CHORUS_SPREAD 2
|
|
Packit Service |
b98cfc |
#define TRNSPS 3
|
|
Packit Service |
b98cfc |
#define FIX_DUR 4
|
|
Packit Service |
b98cfc |
#define MODES 5
|
|
Packit Service |
b98cfc |
#define FIX_KEY 6
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* Options for the command */
|
|
Packit Service |
b98cfc |
#define HAS_ARG 1
|
|
Packit Service |
b98cfc |
static struct option long_opts[] = {
|
|
Packit Service |
b98cfc |
{"device", HAS_ARG, NULL, 'D'},
|
|
Packit Service |
b98cfc |
{"opl2", 0, NULL, '2'},
|
|
Packit Service |
b98cfc |
{"opl3", 0, NULL, '4'},
|
|
Packit Service |
b98cfc |
{"clear", 0, NULL, 'c'},
|
|
Packit Service |
b98cfc |
{"path", HAS_ARG, NULL, 'P'},
|
|
Packit Service |
b98cfc |
{"verbose", HAS_ARG, NULL, 'v'},
|
|
Packit Service |
b98cfc |
{"quiet", 0, NULL, 'q'},
|
|
Packit Service |
b98cfc |
{"version", 0, NULL, 'V'},
|
|
Packit Service |
b98cfc |
{0, 0, 0, 0},
|
|
Packit Service |
b98cfc |
};
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* Number of elements in an array */
|
|
Packit Service |
b98cfc |
#define NELEM(a) ( sizeof(a)/sizeof((a)[0]) )
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
enum {
|
|
Packit Service |
b98cfc |
FM_PATCH_UNKNOWN,
|
|
Packit Service |
b98cfc |
FM_PATCH_OPL2,
|
|
Packit Service |
b98cfc |
FM_PATCH_OPL3
|
|
Packit Service |
b98cfc |
};
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* Default file type */
|
|
Packit Service |
b98cfc |
static int file_type = FM_PATCH_UNKNOWN;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* Default verbose level */
|
|
Packit Service |
b98cfc |
static int quiet;
|
|
Packit Service |
b98cfc |
static int verbose = 0;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* Global declarations */
|
|
Packit Service |
b98cfc |
static snd_hwdep_t *handle;
|
|
Packit Service |
b98cfc |
static int iface;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
#ifndef PATCHDIR
|
|
Packit Service |
b98cfc |
#define PATCHDIR "/usr/share/sounds/opl3"
|
|
Packit Service |
b98cfc |
#endif
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
static char *patchdir = PATCHDIR;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* Function prototypes */
|
|
Packit Service |
b98cfc |
static void show_usage (void);
|
|
Packit Service |
b98cfc |
static void show_op (struct sbi_patch * instr, int type);
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
static int load_patch (struct sbi_patch * instr);
|
|
Packit Service |
b98cfc |
static int load_file (int bank, char *filename);
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
static int init_hwdep (const char *name);
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* Show usage message
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
static void
|
|
Packit Service |
b98cfc |
show_usage () {
|
|
Packit Service |
b98cfc |
char **cpp;
|
|
Packit Service |
b98cfc |
static char *msg[] = {
|
|
Packit Service |
b98cfc |
"Usage: sbiload [options] [instfile [drumfile]]",
|
|
Packit Service |
b98cfc |
" sbiload [options] -c",
|
|
Packit Service |
b98cfc |
"",
|
|
Packit Service |
b98cfc |
" -D, --device=name - hwdep device string",
|
|
Packit Service |
b98cfc |
" -c, --clear - Clear patches and exit",
|
|
Packit Service |
b98cfc |
" -2, --opl2 - two operators file type (OPL2)",
|
|
Packit Service |
b98cfc |
" -4, --opl3 - four operators file type (OPL3)",
|
|
Packit Service |
b98cfc |
" -P, --path=path - Specify the patch path",
|
|
Packit Service |
b98cfc |
" (default path: " PATCHDIR ")",
|
|
Packit Service |
b98cfc |
" -v, --verbose=level - Verbose level (default = 0)",
|
|
Packit Service |
b98cfc |
" -q, --quiet - Be quiet, no error/warning messages",
|
|
Packit Service |
b98cfc |
" -V, --version - Show version",
|
|
Packit Service |
b98cfc |
};
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
for (cpp = msg; cpp < msg + NELEM (msg); cpp++) {
|
|
Packit Service |
b98cfc |
printf ("%s\n", *cpp);
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* Show version
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
static void
|
|
Packit Service |
b98cfc |
show_version () {
|
|
Packit Service |
b98cfc |
printf("Version: " VERSION "\n");
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* Show instrument FM operators
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
static void
|
|
Packit Service |
b98cfc |
show_op (struct sbi_patch * inst, int type) {
|
|
Packit Service |
b98cfc |
int i = 0;
|
|
Packit Service |
b98cfc |
int ofs = 0;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
do {
|
|
Packit Service |
b98cfc |
unsigned char val;
|
|
Packit Service |
b98cfc |
val = inst->data[AM_VIB + ofs];
|
|
Packit Service |
b98cfc |
printf (" OP%i: flags: %s %s %s %s", i,
|
|
Packit Service |
b98cfc |
val & (1 << 7) ? "AM" : " ",
|
|
Packit Service |
b98cfc |
val & (1 << 6) ? "VIB" : " ",
|
|
Packit Service |
b98cfc |
val & (1 << 5) ? "EGT" : " ",
|
|
Packit Service |
b98cfc |
val & (1 << 4) ? "KSR" : " ");
|
|
Packit Service |
b98cfc |
val = inst->data[AM_VIB + ofs + 1];
|
|
Packit Service |
b98cfc |
printf ("\011OP%i: flags: %s %s %s %s\n", i + 1,
|
|
Packit Service |
b98cfc |
val & (1 << 7) ? "AM" : " ",
|
|
Packit Service |
b98cfc |
val & (1 << 6) ? "VIB" : " ",
|
|
Packit Service |
b98cfc |
val & (1 << 5) ? "EGT" : " ",
|
|
Packit Service |
b98cfc |
val & (1 << 4) ? "KSR" : "");
|
|
Packit Service |
b98cfc |
val = inst->data[AM_VIB + ofs];
|
|
Packit Service |
b98cfc |
printf (" OP%i: MULT = 0x%x", i, val & 0x0f);
|
|
Packit Service |
b98cfc |
val = inst->data[AM_VIB + ofs + 1];
|
|
Packit Service |
b98cfc |
printf ("\011\011OP%i: MULT = 0x%x\n", i + 1, val & 0x0f);
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
val = inst->data[KSL_LEVEL + ofs];
|
|
Packit Service |
b98cfc |
printf (" OP%i: KSL = 0x%x TL = 0x%.2x", i,
|
|
Packit Service |
b98cfc |
(val >> 6) & 0x03, val & 0x3f);
|
|
Packit Service |
b98cfc |
val = inst->data[KSL_LEVEL + ofs + 1];
|
|
Packit Service |
b98cfc |
printf ("\011OP%i: KSL = 0x%x TL = 0x%.2x\n", i + 1,
|
|
Packit Service |
b98cfc |
(val >> 6) & 0x03, val & 0x3f);
|
|
Packit Service |
b98cfc |
val = inst->data[ATTACK_DECAY + ofs];
|
|
Packit Service |
b98cfc |
printf (" OP%i: AR = 0x%x DL = 0x%x", i,
|
|
Packit Service |
b98cfc |
(val >> 4) & 0x0f, val & 0x0f);
|
|
Packit Service |
b98cfc |
val = inst->data[ATTACK_DECAY + ofs + 1];
|
|
Packit Service |
b98cfc |
printf ("\011OP%i: AR = 0x%x DL = 0x%x\n", i + 1,
|
|
Packit Service |
b98cfc |
(val >> 4) & 0x0f, val & 0x0f);
|
|
Packit Service |
b98cfc |
val = inst->data[SUSTAIN_RELEASE + ofs];
|
|
Packit Service |
b98cfc |
printf (" OP%i: SL = 0x%x RR = 0x%x", i,
|
|
Packit Service |
b98cfc |
(val >> 4) & 0x0f, val & 0x0f);
|
|
Packit Service |
b98cfc |
val = inst->data[SUSTAIN_RELEASE + ofs + 1];
|
|
Packit Service |
b98cfc |
printf ("\011OP%i: SL = 0x%x RR = 0x%x\n", i + 1,
|
|
Packit Service |
b98cfc |
(val >> 4) & 0x0f, val & 0x0f);
|
|
Packit Service |
b98cfc |
val = inst->data[WAVE_SELECT + ofs];
|
|
Packit Service |
b98cfc |
printf (" OP%i: WS = 0x%x", i, val & 0x07);
|
|
Packit Service |
b98cfc |
val = inst->data[WAVE_SELECT + ofs + 1];
|
|
Packit Service |
b98cfc |
printf ("\011\011OP%i: WS = 0x%x\n", i + 1, val & 0x07);
|
|
Packit Service |
b98cfc |
val = inst->data[CONNECTION + ofs];
|
|
Packit Service |
b98cfc |
printf (" FB = 0x%x, %s\n", (val >> 1) & 0x07,
|
|
Packit Service |
b98cfc |
val & (1 << 0) ? "parallel" : "serial");
|
|
Packit Service |
b98cfc |
i += 2;
|
|
Packit Service |
b98cfc |
ofs += OFFSET_4OP;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
while (i == (type == FM_PATCH_OPL3) << 1);
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
printf (" Extended data:\n"
|
|
Packit Service |
b98cfc |
" ED = %.3i EA = %.3i CS = %.3i TR = %.3i\n"
|
|
Packit Service |
b98cfc |
" FD = %.3i MO = %.3i FK = %.3i\n",
|
|
Packit Service |
b98cfc |
inst->extension[ECHO_DELAY], inst->extension[ECHO_ATTEN],
|
|
Packit Service |
b98cfc |
inst->extension[CHORUS_SPREAD], inst->extension[TRNSPS],
|
|
Packit Service |
b98cfc |
inst->extension[FIX_DUR], inst->extension[MODES],
|
|
Packit Service |
b98cfc |
inst->extension[FIX_KEY]);
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* Send patch to destination port
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
static int
|
|
Packit Service |
b98cfc |
load_patch (struct sbi_patch * inst) {
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
ssize_t ret;
|
|
Packit Service |
b98cfc |
ret = snd_hwdep_write(handle, inst, sizeof(*inst));
|
|
Packit Service |
b98cfc |
if (ret != sizeof(*inst)) {
|
|
Packit Service |
b98cfc |
if (!quiet)
|
|
Packit Service |
b98cfc |
fprintf (stderr, "Unable to write an instrument %.3i put event: %s\n",
|
|
Packit Service |
b98cfc |
inst->prog, snd_strerror (ret));
|
|
Packit Service |
b98cfc |
return -1;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (verbose)
|
|
Packit Service |
b98cfc |
printf ("Loaded instrument %.3i, bank %.3i: %s\n",
|
|
Packit Service |
b98cfc |
inst->prog, inst->bank, inst->name);
|
|
Packit Service |
b98cfc |
return 0;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* Parse standard .sb or .o3 file
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
static void
|
|
Packit Service |
b98cfc |
load_sb (int bank, int fd) {
|
|
Packit Service |
b98cfc |
int len;
|
|
Packit Service |
b98cfc |
int prg;
|
|
Packit Service |
b98cfc |
struct sbi_patch inst;
|
|
Packit Service |
b98cfc |
int fm_instr_type;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
len = (file_type == FM_PATCH_OPL3) ? DATA_LEN_4OP : DATA_LEN_2OP;
|
|
Packit Service |
b98cfc |
for (prg = 0;; prg++) {
|
|
Packit Service |
b98cfc |
inst.prog = prg;
|
|
Packit Service |
b98cfc |
inst.bank = bank;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (read (fd, inst.key, 4) != 4)
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (!memcmp (inst.key, "SBI\032", 4) || !memcmp (inst.key, "2OP\032", 4)) {
|
|
Packit Service |
b98cfc |
fm_instr_type = FM_PATCH_OPL2;
|
|
Packit Service |
b98cfc |
} else if (!strncmp (inst.key, "4OP\032", 4)) {
|
|
Packit Service |
b98cfc |
fm_instr_type = FM_PATCH_OPL3;
|
|
Packit Service |
b98cfc |
} else {
|
|
Packit Service |
b98cfc |
if (verbose)
|
|
Packit Service |
b98cfc |
printf ("%.3i: wrong instrument key!\n", prg);
|
|
Packit Service |
b98cfc |
fm_instr_type = FM_PATCH_UNKNOWN;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (read (fd, &inst.name, sizeof(inst.name)) != sizeof(inst.name) ||
|
|
Packit Service |
b98cfc |
read (fd, &inst.extension, sizeof(inst.extension)) != sizeof(inst.extension) ||
|
|
Packit Service |
b98cfc |
read (fd, &inst.data, len) != len)
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (fm_instr_type == FM_PATCH_UNKNOWN)
|
|
Packit Service |
b98cfc |
continue;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (verbose > 1) {
|
|
Packit Service |
b98cfc |
printf ("%.3i: [%s] %s\n", inst.prog,
|
|
Packit Service |
b98cfc |
fm_instr_type == FM_PATCH_OPL2 ? "OPL2" : "OPL3",
|
|
Packit Service |
b98cfc |
inst.name);
|
|
Packit Service |
b98cfc |
show_op (&inst, fm_instr_type);
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (load_patch (&inst) < 0)
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
return;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* Load file
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
static int
|
|
Packit Service |
b98cfc |
load_file (int bank, char *filename) {
|
|
Packit Service |
b98cfc |
int fd;
|
|
Packit Service |
b98cfc |
char path[1024];
|
|
Packit Service |
b98cfc |
char *name;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (*filename != '/') {
|
|
Packit Service |
b98cfc |
snprintf(path, sizeof(path), "%s/%s", patchdir, filename);
|
|
Packit Service |
b98cfc |
name = path;
|
|
Packit Service |
b98cfc |
} else {
|
|
Packit Service |
b98cfc |
name = filename;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
fd = open (name, O_RDONLY);
|
|
Packit Service |
b98cfc |
if (fd < 0) {
|
|
Packit Service |
b98cfc |
/* try to guess from the interface name */
|
|
Packit Service |
b98cfc |
const char *ext = iface == SND_HWDEP_IFACE_OPL2 ? "sb" : "o3";
|
|
Packit Service |
b98cfc |
if (*filename != '/')
|
|
Packit Service |
b98cfc |
snprintf(path, sizeof(path), "%s/%s.%s", patchdir, filename, ext);
|
|
Packit Service |
b98cfc |
else
|
|
Packit Service |
b98cfc |
snprintf(path, sizeof(path), "%s.%s", filename, ext);
|
|
Packit Service |
b98cfc |
name = path;
|
|
Packit Service |
b98cfc |
fd = open (name, O_RDONLY);
|
|
Packit Service |
b98cfc |
if (fd < 0) {
|
|
Packit Service |
b98cfc |
if (!quiet)
|
|
Packit Service |
b98cfc |
perror (filename);
|
|
Packit Service |
b98cfc |
return -1;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* correct file type if not set explicitly */
|
|
Packit Service |
b98cfc |
if (file_type == FM_PATCH_UNKNOWN)
|
|
Packit Service |
b98cfc |
file_type = iface == SND_HWDEP_IFACE_OPL2 ? FM_PATCH_OPL2 : FM_PATCH_OPL3;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (verbose)
|
|
Packit Service |
b98cfc |
fprintf (stderr, "Loading from %s\n", name);
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
load_sb(bank, fd);
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
close (fd);
|
|
Packit Service |
b98cfc |
return 0;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
static void
|
|
Packit Service |
b98cfc |
clear_patches (void)
|
|
Packit Service |
b98cfc |
{
|
|
Packit Service |
b98cfc |
snd_hwdep_ioctl(handle, SNDRV_DM_FM_IOCTL_CLEAR_PATCHES, 0);
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* Open a hwdep device
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
static int open_hwdep (const char *name)
|
|
Packit Service |
b98cfc |
{
|
|
Packit Service |
b98cfc |
int err;
|
|
Packit Service |
b98cfc |
snd_hwdep_info_t *info;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if ((err = snd_hwdep_open (&handle, name, SND_HWDEP_OPEN_WRITE)) < 0)
|
|
Packit Service |
b98cfc |
return err;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
snd_hwdep_info_alloca(&info;;
|
|
Packit Service |
b98cfc |
if (!snd_hwdep_info (handle, info)) {
|
|
Packit Service |
b98cfc |
iface = snd_hwdep_info_get_iface(info);
|
|
Packit Service |
b98cfc |
if (iface == SND_HWDEP_IFACE_OPL2 ||
|
|
Packit Service |
b98cfc |
iface == SND_HWDEP_IFACE_OPL3 ||
|
|
Packit Service |
b98cfc |
iface == SND_HWDEP_IFACE_OPL4)
|
|
Packit Service |
b98cfc |
return 0;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
snd_hwdep_close(handle);
|
|
Packit Service |
b98cfc |
handle = NULL;
|
|
Packit Service |
b98cfc |
return -EINVAL;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
static int
|
|
Packit Service |
b98cfc |
init_hwdep (const char *name) {
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
int err;
|
|
Packit Service |
b98cfc |
char tmpname[16];
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (!name || !*name) {
|
|
Packit Service |
b98cfc |
/* auto probe */
|
|
Packit Service |
b98cfc |
int card = -1;
|
|
Packit Service |
b98cfc |
snd_ctl_t *ctl;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
while (!snd_card_next(&card) && card >= 0) {
|
|
Packit Service |
b98cfc |
int dev;
|
|
Packit Service |
b98cfc |
sprintf(tmpname, "hw:%d", card);
|
|
Packit Service |
b98cfc |
if (snd_ctl_open(&ctl, tmpname, 0) < 0)
|
|
Packit Service |
b98cfc |
continue;
|
|
Packit Service |
b98cfc |
dev = -1;
|
|
Packit Service |
b98cfc |
while (!snd_ctl_hwdep_next_device(ctl, &dev) && dev >= 0) {
|
|
Packit Service |
b98cfc |
sprintf(tmpname, "hw:%d,%d", card, dev);
|
|
Packit Service |
b98cfc |
if (!open_hwdep(tmpname)) {
|
|
Packit Service |
b98cfc |
snd_ctl_close(ctl);
|
|
Packit Service |
b98cfc |
return 0;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
snd_ctl_close(ctl);
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
if (!quiet)
|
|
Packit Service |
b98cfc |
fprintf (stderr, "Can't find any OPL3 hwdep device\n");
|
|
Packit Service |
b98cfc |
return -1;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (*name == '/') {
|
|
Packit Service |
b98cfc |
/* guess card and device numbers - for convenience to user
|
|
Packit Service |
b98cfc |
* from udev rules
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
int card, device;
|
|
Packit Service |
b98cfc |
if (sscanf(name, "/dev/snd/hwC%dD%d", &card, &device) == 2) {
|
|
Packit Service |
b98cfc |
if (card >= 0 && card <= 32 && device >= 0 && device <= 32) {
|
|
Packit Service |
b98cfc |
sprintf(tmpname, "hw:%d,%d", card, device);
|
|
Packit Service |
b98cfc |
name = tmpname; /* override */
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if ((err = open_hwdep (name)) < 0) {
|
|
Packit Service |
b98cfc |
if (!quiet)
|
|
Packit Service |
b98cfc |
fprintf (stderr, "Could not open hwdep %s: %s\n",
|
|
Packit Service |
b98cfc |
name, snd_strerror (err));
|
|
Packit Service |
b98cfc |
return -1;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
return 0;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* Unsubscribe client from destination port
|
|
Packit Service |
b98cfc |
* and close sequencer
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
static void
|
|
Packit Service |
b98cfc |
finish_hwdep ()
|
|
Packit Service |
b98cfc |
{
|
|
Packit Service |
b98cfc |
snd_hwdep_close(handle);
|
|
Packit Service |
b98cfc |
handle = NULL;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/*
|
|
Packit Service |
b98cfc |
* Load a .SBI FM instrument patch
|
|
Packit Service |
b98cfc |
* sbiload [-p client:port] [-l] [-P path] [-v level] instfile drumfile
|
|
Packit Service |
b98cfc |
*
|
|
Packit Service |
b98cfc |
* -D, --device=name - An ALSA hwdep name to use
|
|
Packit Service |
b98cfc |
* -2 --opl2 - two operators file type (*.sb)
|
|
Packit Service |
b98cfc |
* -4 --opl3 - four operators file type (*.o3)
|
|
Packit Service |
b98cfc |
* -P, --path=path - Specify the patch path
|
|
Packit Service |
b98cfc |
* -v, --verbose=level - Verbose level
|
|
Packit Service |
b98cfc |
* -q, --quiet - Be quiet, no error/warning messages
|
|
Packit Service |
b98cfc |
*/
|
|
Packit Service |
b98cfc |
int
|
|
Packit Service |
b98cfc |
main (int argc, char **argv) {
|
|
Packit Service |
b98cfc |
char opts[NELEM (long_opts) * 2 + 1];
|
|
Packit Service |
b98cfc |
char *name;
|
|
Packit Service |
b98cfc |
char *cp;
|
|
Packit Service |
b98cfc |
int c;
|
|
Packit Service |
b98cfc |
int clear = 0;
|
|
Packit Service |
b98cfc |
struct option *op;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* Build up the short option string */
|
|
Packit Service |
b98cfc |
cp = opts;
|
|
Packit Service |
b98cfc |
for (op = long_opts; op < &long_opts[NELEM (long_opts)]; op++) {
|
|
Packit Service |
b98cfc |
*cp++ = op->val;
|
|
Packit Service |
b98cfc |
if (op->has_arg)
|
|
Packit Service |
b98cfc |
*cp++ = ':';
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
name = NULL;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* Deal with the options */
|
|
Packit Service |
b98cfc |
for (;;) {
|
|
Packit Service |
b98cfc |
c = getopt_long (argc, argv, opts, long_opts, NULL);
|
|
Packit Service |
b98cfc |
if (c == -1)
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
switch (c) {
|
|
Packit Service |
b98cfc |
case 'D':
|
|
Packit Service |
b98cfc |
name = optarg;
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
case 'c':
|
|
Packit Service |
b98cfc |
clear = 1;
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
case '2':
|
|
Packit Service |
b98cfc |
file_type = FM_PATCH_OPL2;
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
case '4':
|
|
Packit Service |
b98cfc |
file_type = FM_PATCH_OPL3;
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
case 'q':
|
|
Packit Service |
b98cfc |
quiet = 1;
|
|
Packit Service |
b98cfc |
verbose = 0;
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
case 'v':
|
|
Packit Service |
b98cfc |
quiet = 0;
|
|
Packit Service |
b98cfc |
verbose = atoi (optarg);
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
case 'V':
|
|
Packit Service |
b98cfc |
show_version();
|
|
Packit Service |
b98cfc |
exit (1);
|
|
Packit Service |
b98cfc |
case 'P':
|
|
Packit Service |
b98cfc |
patchdir = optarg;
|
|
Packit Service |
b98cfc |
break;
|
|
Packit Service |
b98cfc |
case '?':
|
|
Packit Service |
b98cfc |
show_usage ();
|
|
Packit Service |
b98cfc |
exit (1);
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
if (init_hwdep (name) < 0) {
|
|
Packit Service |
b98cfc |
return 1;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
clear_patches ();
|
|
Packit Service |
b98cfc |
if (clear)
|
|
Packit Service |
b98cfc |
goto done;
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
/* Process instrument and drum file */
|
|
Packit Service |
b98cfc |
if (optind < argc)
|
|
Packit Service |
b98cfc |
name = argv[optind++];
|
|
Packit Service |
b98cfc |
else
|
|
Packit Service |
b98cfc |
name = "std";
|
|
Packit Service |
b98cfc |
if (load_file (0, name) < 0) {
|
|
Packit Service |
b98cfc |
finish_hwdep();
|
|
Packit Service |
b98cfc |
return 1;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
if (optind < argc)
|
|
Packit Service |
b98cfc |
name = argv[optind];
|
|
Packit Service |
b98cfc |
else
|
|
Packit Service |
b98cfc |
name = "drums";
|
|
Packit Service |
b98cfc |
if (load_file (128, name) < 0) {
|
|
Packit Service |
b98cfc |
finish_hwdep();
|
|
Packit Service |
b98cfc |
return 1;
|
|
Packit Service |
b98cfc |
}
|
|
Packit Service |
b98cfc |
|
|
Packit Service |
b98cfc |
done:
|
|
Packit Service |
b98cfc |
finish_hwdep();
|
|
Packit Service |
b98cfc |
return 0;
|
|
Packit Service |
b98cfc |
}
|