#include #include #include #include #define __TQSE_SEQNAME "TestQSchedEv" #define __TQSE_PORTNAME "OutputPort" #define __TQSE_QUEUENAME "TQSE_Queue" #define __TQSE_BPM 120 #define __TQSE_PPQ 192 #define __TQSE_ERR_CODE -3 snd_seq_t *seqh; int seqid, portid, queueid; void SetTempo(unsigned int bpm, unsigned int ppq) { snd_seq_queue_tempo_t *tempo; unsigned int beat_in_microsec = (unsigned int) (60000000 / bpm); int err; snd_seq_queue_tempo_alloca(&tempo); snd_seq_queue_tempo_set_tempo(tempo, beat_in_microsec); snd_seq_queue_tempo_set_ppq(tempo, ppq); err = snd_seq_set_queue_tempo(seqh, queueid, tempo); if (err < 0) { fprintf(stderr, "SetTempo: snd_seq_set_queue_tempo: %s\n", snd_strerror(err)); exit(__TQSE_ERR_CODE); } return; } void StartQueue(void) { int err; snd_seq_start_queue(seqh, queueid, 0); err = snd_seq_drain_output(seqh); if (err < 0) { fprintf(stderr, "StartQueue: snd_seq_drain_output: %s\n", snd_strerror(err)); exit(__TQSE_ERR_CODE); } return; } void StopQueue(void) { int err; snd_seq_stop_queue(seqh, queueid, 0); err = snd_seq_drain_output(seqh); if (err < 0) { fprintf(stderr, "StopQueue: snd_seq_drain_output: %s\n", snd_strerror(err)); exit(__TQSE_ERR_CODE); } return; } void SetNoteEv(unsigned char channel, unsigned char note, unsigned int duration, unsigned int ticktime) { /* Trying to set queued note ev scheduled with ticktime. */ snd_seq_event_t ev; int err; snd_seq_ev_clear(&ev); snd_seq_ev_schedule_tick(&ev, queueid, 0, ticktime); snd_seq_ev_set_source(&ev, portid); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_note(&ev, channel, note, 127, duration); err = snd_seq_event_output_direct(seqh, &ev); if (err < 0) { fprintf(stderr, "SetNoteEv: snd_seq_event_output_direct: %s\n", snd_strerror(err)); exit(__TQSE_ERR_CODE); } return; } void InitSeqPortQueue(void) { /* I try to init the alsa sequencer to just output event I don't touch the queue pool output, because it seems to have a default size in /proc/asound/seq/queue. */ int err; err = snd_seq_open(&seqh, "default", SND_SEQ_OPEN_OUTPUT, 0); if (err < 0) { fprintf(stderr, "snd_seq_open: %s\n", snd_strerror(err)); exit(__TQSE_ERR_CODE); } err = snd_seq_set_client_name(seqh, __TQSE_SEQNAME); if (err < 0) { fprintf(stderr, "snd_seq_set_client_name: %s\n", snd_strerror(err)); exit(__TQSE_ERR_CODE); } seqid = snd_seq_client_id(seqh); if (seqid < 0) { fprintf(stderr, "snd_seq_client_id: %s\n", snd_strerror(seqid)); exit(__TQSE_ERR_CODE); } portid = snd_seq_create_simple_port(seqh, __TQSE_PORTNAME, SND_SEQ_PORT_CAP_SUBS_READ \ |SND_SEQ_PORT_CAP_READ, 0); if (portid < 0) { fprintf(stderr, "_Init_GAlsaSeqPort: snd_seq_create_simple_port: %s\n", snd_strerror(portid)); exit(__TQSE_ERR_CODE); } queueid = snd_seq_alloc_named_queue(seqh, __TQSE_QUEUENAME); if (queueid < 0) { fprintf(stderr, "_Init_GAlsaSeqQueue: snd_seq_alloc_named_queue: %s\n", snd_strerror(queueid)); exit(__TQSE_ERR_CODE); } return; } void CloseSeqPortQueue(void) { int err; err = snd_seq_free_queue(seqh, queueid); if (err < 0) fprintf(stderr, "snd_seq_free_queue: %s\n", snd_strerror(err)); err = snd_seq_delete_simple_port(seqh, portid); if (err < 0) fprintf(stderr, "close client port : %s\n", snd_strerror(err)); err = snd_seq_close(seqh); if (err < 0) fprintf(stderr, "close seq client : %s\n", snd_strerror(err)); return; } int main(void) { unsigned int i; InitSeqPortQueue(); SetTempo((unsigned int) __TQSE_BPM, (unsigned int) __TQSE_PPQ); /* Preparing the queue to send an event every 4 beats */ for (i = 0; i < 16; i++) SetNoteEv(1, 60, (4 * __TQSE_PPQ), (i * 16 * __TQSE_PPQ)); printf("Press Enter to start the queue when all subscribtion are done.\n"); /* trying to set enough time for event transimission */ i = (17 * 60 / __TQSE_BPM) + 1; fgetc(stdin); printf("Starting the queue\n"); StartQueue(); sleep(i); printf("\nStopping the queue\n"); StopQueue(); CloseSeqPortQueue(); return 0; } /* I compiled it with : gcc -Wall -g -o TestQSchedEv TestQSchedEv.c -lasound */