comparison src/alsa/audio.c @ 2760:35ac6cb80680

Use glib types.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 02 Jul 2008 08:03:42 +0300
parents e99d3e8653df
children 58c63fbbd3ce
comparison
equal deleted inserted replaced
2759:fd550b4fc79f 2760:35ac6cb80680
44 /* Number of bytes that we have sent to the sound card */ 44 /* Number of bytes that we have sent to the sound card */
45 static guint64 alsa_hw_written; 45 static guint64 alsa_hw_written;
46 static guint64 output_time_offset; 46 static guint64 output_time_offset;
47 47
48 /* device buffer/period sizes in bytes */ 48 /* device buffer/period sizes in bytes */
49 static int hw_buffer_size, hw_period_size; /* in output bytes */ 49 static gint hw_buffer_size, hw_period_size; /* in output bytes */
50 static int hw_buffer_size_in, hw_period_size_in; /* in input bytes */ 50 static gint hw_buffer_size_in, hw_period_size_in; /* in input bytes */
51 51
52 /* Set/Get volume */ 52 /* Set/Get volume */
53 static snd_mixer_elem_t *pcm_element; 53 static snd_mixer_elem_t *pcm_element;
54 static snd_mixer_t *mixer; 54 static snd_mixer_t *mixer;
55 55
58 58
59 static gboolean alsa_can_pause; 59 static gboolean alsa_can_pause;
60 60
61 /* for audio thread */ 61 /* for audio thread */
62 static GThread *audio_thread; /* audio loop thread */ 62 static GThread *audio_thread; /* audio loop thread */
63 static int thread_buffer_size; /* size of intermediate buffer in bytes */ 63 static gint thread_buffer_size; /* size of intermediate buffer in bytes */
64 static char *thread_buffer; /* audio intermediate buffer */ 64 static gchar *thread_buffer; /* audio intermediate buffer */
65 static int rd_index, wr_index; /* current read/write position in int-buffer */ 65 static gint rd_index, wr_index; /* current read/write position in int-buffer */
66 static gboolean pause_request; /* pause status currently requested */ 66 static gboolean pause_request; /* pause status currently requested */
67 static int flush_request; /* flush status (time) currently requested */ 67 static gint flush_request; /* flush status (time) currently requested */
68 static int prebuffer_size; 68 static gint prebuffer_size;
69 GStaticMutex alsa_mutex = G_STATIC_MUTEX_INIT; 69 GStaticMutex alsa_mutex = G_STATIC_MUTEX_INIT;
70 70
71 struct snd_format { 71 struct snd_format {
72 unsigned int rate; 72 guint rate;
73 unsigned int channels; 73 guint channels;
74 snd_pcm_format_t format; 74 snd_pcm_format_t format;
75 AFormat xmms_format; 75 AFormat xmms_format;
76 int sample_bits; 76 gint sample_bits;
77 int bps; 77 gint bps;
78 }; 78 };
79 79
80 static struct snd_format *inputf = NULL; 80 static struct snd_format *inputf = NULL;
81 static struct snd_format *outputf = NULL; 81 static struct snd_format *outputf = NULL;
82 82
83 static int alsa_setup(struct snd_format *f); 83 static gint alsa_setup(struct snd_format *f);
84 static void alsa_write_audio(char *data, int length); 84 static void alsa_write_audio(gchar *data, gint length);
85 static void alsa_cleanup_mixer(void); 85 static void alsa_cleanup_mixer(void);
86 static int get_thread_buffer_filled(void); 86 static gint get_thread_buffer_filled(void);
87 87
88 static struct snd_format * snd_format_from_xmms(AFormat fmt, int rate, int channels); 88 static struct snd_format * snd_format_from_xmms(AFormat fmt, gint rate, gint channels);
89 89
90 static const struct { 90 static const struct {
91 AFormat xmms; 91 AFormat xmms;
92 snd_pcm_format_t alsa; 92 snd_pcm_format_t alsa;
93 } format_table[] = 93 } format_table[] =
113 {FMT_U8, SND_PCM_FORMAT_U8}, 113 {FMT_U8, SND_PCM_FORMAT_U8},
114 {FMT_S8, SND_PCM_FORMAT_S8}, 114 {FMT_S8, SND_PCM_FORMAT_S8},
115 }; 115 };
116 116
117 117
118 static void debug(char *str, ...) G_GNUC_PRINTF(1, 2); 118 static void debug(gchar *str, ...) G_GNUC_PRINTF(1, 2);
119 119
120 static void debug(char *str, ...) 120 static void debug(gchar *str, ...)
121 { 121 {
122 va_list args; 122 va_list args;
123 123
124 if (alsa_cfg.debug) 124 if (alsa_cfg.debug)
125 { 125 {
138 !paused && 138 !paused &&
139 !prebuffer && 139 !prebuffer &&
140 get_thread_buffer_filled() > hw_period_size_in; 140 get_thread_buffer_filled() > hw_period_size_in;
141 } 141 }
142 142
143 static int 143 static gint
144 alsa_recovery(int err) 144 alsa_recovery(gint err)
145 { 145 {
146 int err2; 146 gint err2;
147 147
148 /* if debug mode is enabled, dump ALSA state to console */ 148 /* if debug mode is enabled, dump ALSA state to console */
149 if (alsa_cfg.debug) 149 if (alsa_cfg.debug)
150 { 150 {
151 snd_pcm_status_t *alsa_status = NULL; 151 snd_pcm_status_t *alsa_status = NULL;
296 g_static_mutex_unlock(&alsa_mutex); 296 g_static_mutex_unlock(&alsa_mutex);
297 } 297 }
298 298
299 /* reopen ALSA PCM */ 299 /* reopen ALSA PCM */
300 #if 0 300 #if 0
301 static int alsa_reopen(struct snd_format *f) 301 static gint alsa_reopen(struct snd_format *f)
302 { 302 {
303 /* remember the current position */ 303 /* remember the current position */
304 output_time_offset += (alsa_hw_written * 1000) / outputf->bps; 304 output_time_offset += (alsa_hw_written * 1000) / outputf->bps;
305 alsa_hw_written = 0; 305 alsa_hw_written = 0;
306 306
309 return alsa_setup(f); 309 return alsa_setup(f);
310 } 310 }
311 #endif 311 #endif
312 312
313 /* do flush (drop) operation */ 313 /* do flush (drop) operation */
314 static void alsa_do_flush(int time) 314 static void alsa_do_flush(gint time)
315 { 315 {
316 if (alsa_pcm) 316 if (alsa_pcm)
317 { 317 {
318 snd_pcm_drop(alsa_pcm); 318 snd_pcm_drop(alsa_pcm);
319 snd_pcm_prepare(alsa_pcm); 319 snd_pcm_prepare(alsa_pcm);
322 output_time_offset = time; 322 output_time_offset = time;
323 alsa_total_written = (guint64) time * inputf->bps / 1000; 323 alsa_total_written = (guint64) time * inputf->bps / 1000;
324 rd_index = wr_index = alsa_hw_written = 0; 324 rd_index = wr_index = alsa_hw_written = 0;
325 } 325 }
326 326
327 void alsa_flush(int time) 327 void alsa_flush(gint time)
328 { 328 {
329 flush_request = time; 329 flush_request = time;
330 while ((flush_request != -1) && (going)) 330 while ((flush_request != -1) && (going))
331 g_usleep(10000); 331 g_usleep(10000);
332 } 332 }
333 333
334 static void parse_mixer_name(char *str, char **name, int *index) 334 static void parse_mixer_name(gchar *str, gchar **name, gint *index)
335 { 335 {
336 char *end; 336 gchar *end;
337 337
338 while (isspace(*str)) 338 while (isspace(*str))
339 str++; 339 str++;
340 340
341 if ((end = strchr(str, ',')) != NULL) 341 if ((end = strchr(str, ',')) != NULL)
349 *name = g_strdup(str); 349 *name = g_strdup(str);
350 *index = 0; 350 *index = 0;
351 } 351 }
352 } 352 }
353 353
354 int alsa_get_mixer(snd_mixer_t **mixer, int card) 354 gint alsa_get_mixer(snd_mixer_t **mixer, gint card)
355 { 355 {
356 char *dev; 356 gchar *dev;
357 int err; 357 gint err;
358 358
359 debug("alsa_get_mixer"); 359 debug("alsa_get_mixer");
360 360
361 if ((err = snd_mixer_open(mixer, 0)) < 0) 361 if ((err = snd_mixer_open(mixer, 0)) < 0)
362 { 362 {
391 391
392 return (*mixer != NULL); 392 return (*mixer != NULL);
393 } 393 }
394 394
395 395
396 static snd_mixer_elem_t* alsa_get_mixer_elem(snd_mixer_t *mixer, char *name, int index) 396 static snd_mixer_elem_t* alsa_get_mixer_elem(snd_mixer_t *mixer, gchar *name, gint index)
397 { 397 {
398 snd_mixer_selem_id_t *selem_id; 398 snd_mixer_selem_id_t *selem_id;
399 snd_mixer_elem_t* elem; 399 snd_mixer_elem_t* elem;
400 snd_mixer_selem_id_alloca(&selem_id); 400 snd_mixer_selem_id_alloca(&selem_id);
401 401
409 return elem; 409 return elem;
410 } 410 }
411 411
412 static int alsa_setup_mixer(void) 412 static int alsa_setup_mixer(void)
413 { 413 {
414 char *name; 414 gchar *name;
415 long int a, b; 415 glong a, b;
416 long alsa_min_vol, alsa_max_vol; 416 glong alsa_min_vol, alsa_max_vol;
417 int err, index; 417 gint err, index;
418 418
419 debug("alsa_setup_mixer"); 419 debug("alsa_setup_mixer");
420 420
421 if ((err = alsa_get_mixer(&mixer, alsa_cfg.mixer_card)) < 0) 421 if ((err = alsa_get_mixer(&mixer, alsa_cfg.mixer_card)) < 0)
422 return err; 422 return err;
469 snd_mixer_close(mixer); 469 snd_mixer_close(mixer);
470 mixer = NULL; 470 mixer = NULL;
471 } 471 }
472 } 472 }
473 473
474 void alsa_get_volume(int *l, int *r) 474 void alsa_get_volume(gint *l, gint *r)
475 { 475 {
476 long ll = *l, lr = *r; 476 glong ll = *l, lr = *r;
477 477
478 if (mixer_start) 478 if (mixer_start)
479 { 479 {
480 alsa_setup_mixer(); 480 alsa_setup_mixer();
481 mixer_start = FALSE; 481 mixer_start = FALSE;
495 *l = ll; 495 *l = ll;
496 *r = lr; 496 *r = lr;
497 } 497 }
498 498
499 499
500 void alsa_set_volume(int l, int r) 500 void alsa_set_volume(gint l, gint r)
501 { 501 {
502 if (!pcm_element) 502 if (!pcm_element)
503 return; 503 return;
504 504
505 if (snd_mixer_selem_is_playback_mono(pcm_element)) 505 if (snd_mixer_selem_is_playback_mono(pcm_element))
539 if (wr_index >= rd_index) 539 if (wr_index >= rd_index)
540 return wr_index - rd_index; 540 return wr_index - rd_index;
541 return thread_buffer_size - (rd_index - wr_index); 541 return thread_buffer_size - (rd_index - wr_index);
542 } 542 }
543 543
544 int alsa_get_output_time(void) 544 gint alsa_get_output_time(void)
545 { 545 {
546 snd_pcm_sframes_t delay; 546 snd_pcm_sframes_t delay;
547 guint64 bytes = alsa_hw_written; 547 guint64 bytes = alsa_hw_written;
548 548
549 if (!going || alsa_pcm == NULL) 549 if (!going || alsa_pcm == NULL)
558 bytes -= d; 558 bytes -= d;
559 } 559 }
560 return output_time_offset + (bytes * 1000) / outputf->bps; 560 return output_time_offset + (bytes * 1000) / outputf->bps;
561 } 561 }
562 562
563 int alsa_get_written_time(void) 563 gint alsa_get_written_time(void)
564 { 564 {
565 if (!going) 565 if (!going)
566 return 0; 566 return 0;
567 return (alsa_total_written * 1000) / inputf->bps; 567 return (alsa_total_written * 1000) / inputf->bps;
568 } 568 }
579 579
580 alsa_write_audio(data, length); 580 alsa_write_audio(data, length);
581 } 581 }
582 582
583 /* write callback */ 583 /* write callback */
584 void alsa_write(gpointer data, int length) 584 void alsa_write(gpointer data, gint length)
585 { 585 {
586 int cnt; 586 gint cnt;
587 char *src = (char *)data; 587 gchar *src = (gchar *)data;
588 588
589 remove_prebuffer = FALSE; 589 remove_prebuffer = FALSE;
590 590
591 alsa_total_written += length; 591 alsa_total_written += length;
592 while (length > 0) 592 while (length > 0)
600 src += cnt; 600 src += cnt;
601 } 601 }
602 } 602 }
603 603
604 /* transfer data to audio h/w via normal write */ 604 /* transfer data to audio h/w via normal write */
605 static void alsa_write_audio(char *data, int length) 605 static void alsa_write_audio(gchar *data, gint length)
606 { 606 {
607 snd_pcm_sframes_t written_frames; 607 snd_pcm_sframes_t written_frames;
608 608
609 while (length > 0) 609 while (length > 0)
610 { 610 {
653 653
654 /* audio thread loop */ 654 /* audio thread loop */
655 /* FIXME: proper lock? */ 655 /* FIXME: proper lock? */
656 static void *alsa_loop(void *arg) 656 static void *alsa_loop(void *arg)
657 { 657 {
658 int npfds = snd_pcm_poll_descriptors_count(alsa_pcm); 658 gint npfds = snd_pcm_poll_descriptors_count(alsa_pcm);
659 int wr = 0; 659 gint wr = 0;
660 660
661 g_static_mutex_lock(&alsa_mutex); 661 g_static_mutex_lock(&alsa_mutex);
662 662
663 if (npfds <= 0) 663 if (npfds <= 0)
664 goto _error; 664 goto _error;
702 g_thread_exit(NULL); 702 g_thread_exit(NULL);
703 return(NULL); 703 return(NULL);
704 } 704 }
705 705
706 /* open callback */ 706 /* open callback */
707 int alsa_open(AFormat fmt, int rate, int nch) 707 gint alsa_open(AFormat fmt, gint rate, gint nch)
708 { 708 {
709 debug("Opening device"); 709 debug("Opening device");
710 if((inputf = snd_format_from_xmms(fmt, rate, nch)) == NULL) return 0; 710 if((inputf = snd_format_from_xmms(fmt, rate, nch)) == NULL) return 0;
711 711
712 if (alsa_cfg.debug) 712 if (alsa_cfg.debug)
749 749
750 audio_thread = g_thread_create((GThreadFunc)alsa_loop, NULL, TRUE, NULL); 750 audio_thread = g_thread_create((GThreadFunc)alsa_loop, NULL, TRUE, NULL);
751 return 1; 751 return 1;
752 } 752 }
753 753
754 static struct snd_format * snd_format_from_xmms(AFormat fmt, int rate, int channels) 754 static struct snd_format * snd_format_from_xmms(AFormat fmt, gint rate, gint channels)
755 { 755 {
756 struct snd_format *f = g_malloc(sizeof(struct snd_format)); 756 struct snd_format *f = g_malloc(sizeof(struct snd_format));
757 size_t i; 757 size_t i;
758 int found = 0; 758 gint found = 0;
759 759
760 f->xmms_format = fmt; 760 f->xmms_format = fmt;
761 f->format = SND_PCM_FORMAT_UNKNOWN; 761 f->format = SND_PCM_FORMAT_UNKNOWN;
762 762
763 for (i = 0; i < sizeof(format_table) / sizeof(format_table[0]); i++) 763 for (i = 0; i < sizeof(format_table) / sizeof(format_table[0]); i++)
788 f->bps = (rate * f->sample_bits * channels) >> 3; 788 f->bps = (rate * f->sample_bits * channels) >> 3;
789 789
790 return f; 790 return f;
791 } 791 }
792 792
793 static int alsa_setup(struct snd_format *f) 793 static gint alsa_setup(struct snd_format *f)
794 { 794 {
795 int err; 795 gint err;
796 snd_pcm_hw_params_t *hwparams = NULL; 796 snd_pcm_hw_params_t *hwparams = NULL;
797 snd_pcm_sw_params_t *swparams = NULL; 797 snd_pcm_sw_params_t *swparams = NULL;
798 unsigned int alsa_buffer_time, alsa_period_time; 798 guint alsa_buffer_time, alsa_period_time;
799 snd_pcm_uframes_t alsa_buffer_size, alsa_period_size; 799 snd_pcm_uframes_t alsa_buffer_size, alsa_period_size;
800 800
801 debug("alsa_setup"); 801 debug("alsa_setup");
802 802
803 g_free(outputf); 803 g_free(outputf);