⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alsaseq_c.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    TiMidity++ -- MIDI to WAVE converter and player    Copyright (C) 1999-2004 Masanao Izumo <iz@onicos.co.jp>    Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>    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    alsaseq_c.c - ALSA sequencer server interface        Copyright (c) 2000  Takashi Iwai <tiwai@suse.de>    This interface provides an ALSA sequencer client which receives    events and plays it in real-time.  On this mode, TiMidity works    as a software (quasi-)real-time MIDI synth engine.    See doc/C/README.alsaseq for more details.*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <unistd.h>#include <sched.h>#include <sys/types.h>#include <sys/time.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include <math.h>#include <signal.h>#if HAVE_ALSA_ASOUNDLIB_H#include <alsa/asoundlib.h>#else#include <sys/asoundlib.h>#endif#include "timidity.h"#include "common.h"#include "controls.h"#include "instrum.h"#include "playmidi.h"#include "readmidi.h"#include "recache.h"#include "output.h"#include "aq.h"#include "timer.h"void readmidi_read_init(void);#define MAX_PORTS	16#define TICKTIME_HZ	100struct seq_context {	snd_seq_t *handle;	/* The snd_seq handle to /dev/snd/seq */	int client;		/* The client associated with this context */	int num_ports;		/* number of ports */	int port[MAX_PORTS];	/* created sequencer ports */	int fd;			/* The file descriptor */	int used;		/* number of current connection */	int active;		/* */	int queue;	snd_seq_queue_status_t *q_status;};static struct seq_context alsactx;#if SND_LIB_MAJOR > 0 || SND_LIB_MINOR >= 6/* !! this is a dirty hack.  not sure to work in future !! */static int snd_seq_file_descriptor(snd_seq_t *handle){	int pfds = snd_seq_poll_descriptors_count(handle, POLLIN);	if (pfds > 0) {		struct pollfd pfd;		if (snd_seq_poll_descriptors(handle, &pfd, 1, POLLIN) >= 0)			return pfd.fd;	}	return -ENXIO;}static int alsa_seq_open(snd_seq_t **seqp){	return snd_seq_open(seqp, "hw", SND_SEQ_OPEN_DUPLEX, 0);}static int alsa_create_port(snd_seq_t *seq, int index){	char name[32];	int port;	sprintf(name, "TiMidity port %d", index);	port = snd_seq_create_simple_port(seq, name,					  SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,					  SND_SEQ_PORT_TYPE_MIDI_GENERIC);	if (port < 0) {		fprintf(stderr, "error in snd_seq_create_simple_port\n");		return -1;	}	return port;}#elsestatic int alsa_seq_open(snd_seq_t **seqp){	return snd_seq_open(seqp, SND_SEQ_OPEN_IN);}static int alsa_create_port(snd_seq_t *seq, int index){	snd_seq_port_info_t pinfo;	memset(&pinfo, 0, sizeof(pinfo));	sprintf(pinfo.name, "TiMidity port %d", index);	pinfo.capability = SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE;	pinfo.type = SND_SEQ_PORT_TYPE_MIDI_GENERIC;	strcpy(pinfo.group, SND_SEQ_GROUP_DEVICE);	if (snd_seq_create_port(alsactx.handle, &pinfo) < 0) {		fprintf(stderr, "error in snd_seq_create_simple_port\n");		return -1;	}	return pinfo.port;}#endifstatic void alsa_set_timestamping(struct seq_context *ctxp, int port){#if HAVE_SND_SEQ_PORT_INFO_SET_TIMESTAMPING	int q = 0;	snd_seq_port_info_t *pinfo;	if (ctxp->queue < 0) {		q = snd_seq_alloc_queue(ctxp->handle);		ctxp->queue = q;		if (q < 0)			return;		if (snd_seq_queue_status_malloc(&ctxp->q_status) < 0) {			fprintf(stderr, "no memory!\n");			exit(1);		}	}	snd_seq_port_info_alloca(&pinfo);	if (snd_seq_get_port_info(ctxp->handle, port, pinfo) < 0)		return;	snd_seq_port_info_set_timestamping(pinfo, 1);	snd_seq_port_info_set_timestamp_real(pinfo, 1);	snd_seq_port_info_set_timestamp_queue(pinfo, q);	if (snd_seq_set_port_info(ctxp->handle, port, pinfo) < 0)		return;#endif}static int ctl_open(int using_stdin, int using_stdout);static void ctl_close(void);static int ctl_read(int32 *valp);static int cmsg(int type, int verbosity_level, char *fmt, ...);static void ctl_event(CtlEvent *e);static void ctl_pass_playing_list(int n, char *args[]);/**********************************//* export the interface functions */#define ctl alsaseq_control_modeControlMode ctl={    "ALSA sequencer interface", 'A',    1,0,0,    0,    ctl_open,    ctl_close,    ctl_pass_playing_list,    ctl_read,    cmsg,    ctl_event};/* options */int opt_realtime_priority = 0;int opt_sequencer_ports = 4;static int buffer_time_advance;static long buffer_time_offset;static long start_time_base;static long cur_time_offset;static long last_queue_offset;static double rate_frac, rate_frac_nsec;static FILE *outfp;/*ARGSUSED*/static int ctl_open(int using_stdin, int using_stdout){	ctl.opened = 1;	ctl.flags &= ~(CTLF_LIST_RANDOM|CTLF_LIST_SORT);	if (using_stdout)		outfp = stderr;	else		outfp = stdout;	return 0;}static void ctl_close(void){	if (!ctl.opened)		return;}static int ctl_read(int32 *valp){    return RC_NONE;}static int cmsg(int type, int verbosity_level, char *fmt, ...){    va_list ap;    if((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&       ctl.verbosity < verbosity_level)	return 0;    if(outfp == NULL)	outfp = stderr;    va_start(ap, fmt);    vfprintf(outfp, fmt, ap);    fputs(NLS, outfp);    fflush(outfp);    va_end(ap);    return 0;}static void ctl_event(CtlEvent *e){}static RETSIGTYPE sig_timeout(int sig){    signal(SIGALRM, sig_timeout); /* For SysV base */    /* Expect EINTR */}static void doit(struct seq_context *ctxp);static int do_sequencer(struct seq_context *ctxp);static int start_sequencer(struct seq_context *ctxp);static void stop_sequencer(struct seq_context *ctxp);static void server_reset(void);/* reset all when SIGHUP is received */static RETSIGTYPE sig_reset(int sig){	if (alsactx.active) {		stop_sequencer(&alsactx);		server_reset();	}	signal(SIGHUP, sig_reset);}/* * set the process to realtime privs */static int set_realtime_priority(void){	struct sched_param schp;	int max_prio;	if (opt_realtime_priority <= 0)		return 0;        memset(&schp, 0, sizeof(schp));	max_prio = sched_get_priority_max(SCHED_FIFO);	if (max_prio < opt_realtime_priority)		opt_realtime_priority = max_prio;	schp.sched_priority = opt_realtime_priority;        if (sched_setscheduler(0, SCHED_FIFO, &schp) != 0) {		printf("can't set sched_setscheduler - using normal priority\n");                return -1;        }	/* drop root priv. */	if (! geteuid() && getuid() != geteuid()) {		if (setuid(getuid()))			perror("dropping root priv");	}	printf("set SCHED_FIFO(%d)\n", opt_realtime_priority);        return 0;}static void ctl_pass_playing_list(int n, char *args[]){	double btime;	int i, j;#ifdef SIGPIPE	signal(SIGPIPE, SIG_IGN);    /* Handle broken pipe */#endif /* SIGPIPE */	printf("TiMidity starting in ALSA server mode\n");	set_realtime_priority();	if (alsa_seq_open(&alsactx.handle) < 0) {		fprintf(stderr, "error in snd_seq_open\n");		return;	}	alsactx.queue = -1;	alsactx.client = snd_seq_client_id(alsactx.handle);	alsactx.fd = snd_seq_file_descriptor(alsactx.handle);	snd_seq_set_client_name(alsactx.handle, "TiMidity");	snd_seq_set_client_pool_input(alsactx.handle, 1000); /* enough? */	if (opt_sequencer_ports < 1)		alsactx.num_ports = 1;	else if (opt_sequencer_ports > MAX_PORTS)		alsactx.num_ports = MAX_PORTS;	else		alsactx.num_ports = opt_sequencer_ports;	printf("Opening sequencer port:");	for (i = 0; i < alsactx.num_ports; i++) {		int port;		port = alsa_create_port(alsactx.handle, i);		if (port < 0)			return;		alsactx.port[i] = port;		alsa_set_timestamping(&alsactx, port);		printf(" %d:%d", alsactx.client, alsactx.port[i]);	}	printf("\n");	alsactx.used = 0;	alsactx.active = 0;	opt_realtime_playing = 1; /* Enable loading patch while playing */	allocate_cache_size = 0; /* Don't use pre-calclated samples */	current_keysig = (opt_init_keysig == 8) ? 0 : opt_init_keysig;	note_key_offset = key_adjust;	if (IS_STREAM_TRACE) {		/* set the audio queue size as minimum as possible, since		 * we don't have to use audio queue..		 */		play_mode->acntl(PM_REQ_GETFRAGSIZ, &buffer_time_advance);		if (!(play_mode->encoding & PE_MONO))			buffer_time_advance >>= 1;		if (play_mode->encoding & PE_16BIT)			buffer_time_advance >>= 1;		btime = (double)buffer_time_advance / play_mode->rate;		btime *= 1.01; /* to be sure */		aq_set_soft_queue(btime, 0.0);	} else {		buffer_time_advance = 0;	}	rate_frac = (double)play_mode->rate / 1000000.0;	rate_frac_nsec = (double)play_mode->rate / 1000000000.0;	alarm(0);	signal(SIGALRM, sig_timeout);	signal(SIGINT, safe_exit);	signal(SIGTERM, safe_exit);	signal(SIGHUP, sig_reset);	i = current_keysig + ((current_keysig < 8) ? 7 : -9), j = 0;	while (i != 7)		i += (i < 7) ? 5 : -7, j++;	j += note_key_offset, j -= floor(j / 12.0) * 12;	current_freq_table = j;	play_mode->close_output();	if (ctl.flags & CTLF_DAEMONIZE)	{		int pid = fork();		FILE *pidf;		switch (pid)		{			case 0:			// child is the daemon				break;			case -1:		// error status return				exit(7);			default:		// no error, doing well				if ((pidf = fopen( "/var/run/timidity.pid", "w" )) != NULL )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -