1#include <unistd.h> 2#include <sys/time.h> 3#include <alsa/asoundlib.h> 4#include <alsa/seq.h> 5 6void normalize(struct timeval *tv) 7{ 8 if (tv->tv_sec == 0) { 9 while (tv->tv_usec <= -1000000) { tv->tv_usec += 1000000; --tv->tv_sec; } 10 while (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; ++tv->tv_sec; } 11 } else if (tv->tv_sec < 0) { 12 while (tv->tv_usec <= -1000000) { tv->tv_usec += 1000000; --tv->tv_sec; } 13 while (tv->tv_usec > 0) { tv->tv_usec -= 1000000; ++tv->tv_sec; } 14 } else { 15 while (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; ++tv->tv_sec; } 16 while (tv->tv_usec < 0) { tv->tv_usec += 1000000; --tv->tv_sec; } 17 } 18} 19 20int 21main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) 22{ 23 snd_seq_t *handle; 24 int portid; 25 /* int npfd; 26 struct pollfd *pfd; 27 */ 28 int queue; 29 /* int i; 30 int rval;' 31 */ 32 struct timeval starttv, prevdiff; 33 int countdown = -1; 34 /* snd_seq_queue_timer_t *timer; 35 snd_timer_id_t *timerid; 36 */ 37 38 if (snd_seq_open(&handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) { 39 fprintf(stderr, "failed to open ALSA sequencer interface\n"); 40 return 1; 41 } 42 43 snd_seq_set_client_name(handle, "generator"); 44 45 if ((portid = snd_seq_create_simple_port 46 (handle, "generator", 47 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, 0)) < 0) { 48 fprintf(stderr, "failed to create ALSA sequencer port\n"); 49 return 1; 50 } 51 52 if ((queue = snd_seq_alloc_queue(handle)) < 0) { 53 fprintf(stderr, "failed to create ALSA sequencer queue\n"); 54 return 1; 55 } 56/* 57 snd_seq_queue_timer_alloca(&timer); 58 snd_seq_get_queue_timer(handle, queue, timer); 59 snd_timer_id_alloca(&timerid); 60 snd_timer_id_set_class(timerid, SND_TIMER_CLASS_PCM); 61 snd_timer_id_set_sclass(timerid, SND_TIMER_SCLASS_NONE); 62 snd_timer_id_set_card(timerid, 0); 63 snd_timer_id_set_device(timerid, 0); 64 snd_timer_id_set_subdevice(timerid, 0); 65 snd_seq_queue_timer_set_id(timer, timerid); 66 snd_seq_set_queue_timer(handle, queue, timer); 67*/ 68 snd_seq_start_queue(handle, queue, 0); 69 snd_seq_drain_output(handle); 70 71 gettimeofday(&starttv, 0); 72 prevdiff.tv_sec = 0; 73 prevdiff.tv_usec = 0; 74 75 while (countdown != 0) { 76 77 snd_seq_queue_status_t *status; 78 const snd_seq_real_time_t *rtime; 79 struct timeval tv, diff, diffdiff; 80 struct timespec ts; 81 82 snd_seq_queue_status_alloca(&status); 83 84 snd_seq_get_queue_status(handle, queue, status); 85 rtime = snd_seq_queue_status_get_real_time(status); 86 87 gettimeofday(&tv, 0); 88 89 tv.tv_sec -= starttv.tv_sec; 90 tv.tv_usec -= starttv.tv_usec; 91 normalize(&tv); 92 93 diff.tv_sec = tv.tv_sec - rtime->tv_sec; 94 diff.tv_usec = tv.tv_usec - rtime->tv_nsec / 1000; 95 normalize(&diff); 96 97 diffdiff.tv_sec = diff.tv_sec - prevdiff.tv_sec; 98 diffdiff.tv_usec = diff.tv_usec - prevdiff.tv_usec; 99 normalize(&diffdiff); 100 prevdiff = diff; 101 102 fprintf(stderr, " real time: %12ld sec %8ld usec\nqueue time: %12ld sec %8ld usec\n diff: %12ld sec %8ld usec\n diffdiff: %12ld sec %8ld usec\n", 103 tv.tv_sec, tv.tv_usec, 104 (long)rtime->tv_sec, (long)rtime->tv_nsec / 1000, 105 diff.tv_sec, diff.tv_usec, 106 (long)diffdiff.tv_sec, (long)diffdiff.tv_usec); 107 108 if (diffdiff.tv_usec > 5000 || 109 diffdiff.tv_usec < -5000) { 110 fprintf(stderr, "oops! queue slipped\n"); 111 if (tv.tv_sec < 5) { 112 fprintf(stderr, "(ignoring in first few seconds)\n"); 113 } else { 114 countdown = 2; 115 } 116 } else { 117 if (countdown > 0) --countdown; 118 } 119 120 fprintf(stderr, "\n"); 121// sleep(1); 122 ts.tv_sec = 0; 123 ts.tv_nsec = 500000000; 124 nanosleep(&ts, 0); 125 } 126 return EXIT_SUCCESS; 127} 128 129