Mercurial > mplayer.hg
comparison libao2/ao_alsa1x.c @ 7077:a24f91c247cd
iec958-init completly rewritten
some debug printfs cleaned
author | joyping |
---|---|
date | Fri, 23 Aug 2002 13:03:00 +0000 |
parents | a5b2b377ab50 |
children | dda97c5190d7 |
comparison
equal
deleted
inserted
replaced
7076:3275af5787e0 | 7077:a24f91c247cd |
---|---|
1 /* | 1 /* |
2 ao_alsa9 - ALSA-0.9.x output plugin for MPlayer | 2 ao_alsa9 - ALSA-0.9.x output plugin for MPlayer |
3 | 3 |
4 (C) Alex Beregszaszi <alex@naxine.org> | 4 (C) Alex Beregszaszi <alex@naxine.org> |
5 | 5 |
6 modified for better alsa-0.9.0beta12(rc1)-support by Joy Winter <joy@pingfm.org> | 6 modified for real alsa-0.9.0-support by Joy Winter <joy@pingfm.org> |
7 additional AC3 passthrough support by Andy Lo A Foe <andy@alsaplayer.org> | 7 additional AC3 passthrough support by Andy Lo A Foe <andy@alsaplayer.org> |
8 08/22/2002 iec958-init rewritten and merged with common init, joy | |
8 | 9 |
9 Any bugreports regarding to this driver are welcome either to the mplayer-user-mailinglist or directly to the authors. | 10 Any bugreports regarding to this driver are welcome. |
10 */ | 11 */ |
11 | 12 |
12 #include <errno.h> | 13 #include <errno.h> |
13 #include <sys/time.h> | 14 #include <sys/time.h> |
14 #include <stdlib.h> | 15 #include <stdlib.h> |
45 | 46 |
46 static snd_pcm_t *alsa_handler; | 47 static snd_pcm_t *alsa_handler; |
47 static snd_pcm_format_t alsa_format; | 48 static snd_pcm_format_t alsa_format; |
48 static snd_pcm_hw_params_t *alsa_hwparams; | 49 static snd_pcm_hw_params_t *alsa_hwparams; |
49 static snd_pcm_sw_params_t *alsa_swparams; | 50 static snd_pcm_sw_params_t *alsa_swparams; |
50 static char *alsa_device; | 51 const char *alsa_device; |
51 | 52 |
52 /* possible 4096, original 8192 | 53 /* possible 4096, original 8192 |
53 * was only needed for calculating chunksize? */ | 54 * was only needed for calculating chunksize? */ |
54 static int alsa_fragsize = 4096; | 55 static int alsa_fragsize = 4096; |
55 /* 16 sets buffersize to 16 * chunksize is as default 1024 | 56 /* 16 sets buffersize to 16 * chunksize is as default 1024 |
71 #define ALSA_DEVICE_SIZE 48 | 72 #define ALSA_DEVICE_SIZE 48 |
72 | 73 |
73 #undef BUFFERTIME | 74 #undef BUFFERTIME |
74 #define SET_CHUNKSIZE | 75 #define SET_CHUNKSIZE |
75 #undef USE_POLL | 76 #undef USE_POLL |
76 | |
77 snd_pcm_t *spdif_init(char *pcm_name) | |
78 { | |
79 //char *pcm_name = "hw:0,2"; /* first card second device */ | |
80 static snd_aes_iec958_t spdif; | |
81 static snd_aes_iec958_t spdif_test; | |
82 snd_pcm_info_t *info; | |
83 snd_pcm_t *handler; | |
84 snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; | |
85 unsigned int channels = 2; | |
86 unsigned int rate = 48000; | |
87 int err, c; | |
88 | |
89 if ((err = snd_pcm_open(&handler, pcm_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) | |
90 { | |
91 fprintf(stderr, "open: %s\n", snd_strerror(err)); | |
92 return NULL; | |
93 } | |
94 | |
95 snd_pcm_info_alloca(&info); | |
96 | |
97 if ((err = snd_pcm_info(handler, info)) < 0) { | |
98 fprintf(stderr, "info: %s\n", snd_strerror(err)); | |
99 snd_pcm_close(handler); | |
100 return NULL; | |
101 } | |
102 printf("device: %d, subdevice: %d\n", snd_pcm_info_get_device(info), | |
103 snd_pcm_info_get_subdevice(info)); | |
104 { | |
105 | |
106 snd_ctl_elem_value_t *ctl; | |
107 snd_ctl_t *ctl_handler; | |
108 snd_ctl_elem_id_t *elem_id; | |
109 unsigned int elem_device; | |
110 const char *elem_name; | |
111 char ctl_name[12]; | |
112 int ctl_card; | |
113 //elem_id = 36; | |
114 | |
115 spdif.status[0] = IEC958_AES0_NONAUDIO | | |
116 IEC958_AES0_CON_EMPHASIS_NONE; | |
117 spdif.status[1] = IEC958_AES1_CON_ORIGINAL | | |
118 IEC958_AES1_CON_PCM_CODER; | |
119 spdif.status[2] = 0; | |
120 spdif.status[3] = IEC958_AES3_CON_FS_48000; | |
121 | |
122 snd_ctl_elem_value_alloca(&ctl); | |
123 snd_ctl_elem_id_alloca(&elem_id); | |
124 snd_ctl_elem_value_set_interface(ctl, SND_CTL_ELEM_IFACE_PCM); //SND_CTL_ELEM_IFACE_MIXER | |
125 snd_ctl_elem_value_set_device(ctl, snd_pcm_info_get_device(info)); | |
126 snd_ctl_elem_value_set_subdevice(ctl, snd_pcm_info_get_subdevice(info)); | |
127 snd_ctl_elem_value_set_name(ctl,SND_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM)); //SWITCH | |
128 snd_ctl_elem_value_set_iec958(ctl, &spdif); | |
129 ctl_card = snd_pcm_info_get_card(info); | |
130 if (ctl_card < 0) { | |
131 fprintf(stderr, "Unable to setup the IEC958 (S/PDIF) interface - PCM has no assigned card"); | |
132 goto __diga_end; | |
133 } | |
134 | |
135 sprintf(ctl_name, "hw:%d", ctl_card); | |
136 printf("hw:%d\n", ctl_card); | |
137 if ((err = snd_ctl_open(&ctl_handler, ctl_name, 0)) < 0) { | |
138 fprintf(stderr, "Unable to open the control interface '%s': %s\n", ctl_name, snd_strerror(err)); | |
139 goto __diga_end; | |
140 } | |
141 if ((err = snd_ctl_elem_write(ctl_handler, ctl)) < 0) { | |
142 //fprintf(stderr, "Unable to update the IEC958 control: %s\n", snd_strerror(err)); | |
143 printf("alsa-spdif-init: cant set spdif-through automatically\n"); | |
144 goto __diga_end; | |
145 } | |
146 | |
147 snd_ctl_close(ctl_handler); | |
148 __diga_end: | |
149 | |
150 } | |
151 | |
152 { | |
153 snd_pcm_hw_params_t *params; | |
154 snd_pcm_sw_params_t *swparams; | |
155 | |
156 snd_pcm_hw_params_alloca(¶ms); | |
157 snd_pcm_sw_params_alloca(&swparams); | |
158 | |
159 err = snd_pcm_hw_params_any(handler, params); | |
160 if (err < 0) { | |
161 fprintf(stderr, "Broken configuration for this PCM: no configurations available"); | |
162 return NULL; | |
163 } | |
164 | |
165 err = snd_pcm_hw_params_set_access(handler, params,SND_PCM_ACCESS_RW_INTERLEAVED); | |
166 if (err < 0) { | |
167 fprintf(stderr, "Access tyep not available"); | |
168 return NULL; | |
169 } | |
170 err = snd_pcm_hw_params_set_format(handler, params, format); | |
171 | |
172 if (err < 0) { | |
173 fprintf(stderr, "Sample format non available"); | |
174 return NULL; | |
175 } | |
176 | |
177 err = snd_pcm_hw_params_set_channels(handler, params, channels); | |
178 | |
179 if (err < 0) { | |
180 fprintf(stderr, "Channels count non avaible"); | |
181 return NULL; | |
182 } | |
183 | |
184 err = snd_pcm_hw_params_set_rate_near(handler, params, rate, 0); assert(err >= 0); | |
185 | |
186 err = snd_pcm_hw_params(handler, params); | |
187 | |
188 if (err < 0) { | |
189 fprintf(stderr, "Cannot set buffer size\n"); | |
190 return NULL; | |
191 } | |
192 snd_pcm_sw_params_current(handler, swparams); | |
193 } | |
194 return handler; | |
195 } | |
196 | 77 |
197 | 78 |
198 /* to set/get/query special features/parameters */ | 79 /* to set/get/query special features/parameters */ |
199 static int control(int cmd, int arg) | 80 static int control(int cmd, int arg) |
200 { | 81 { |
411 char *sub_str; | 292 char *sub_str; |
412 | 293 |
413 char *token_str[3]; | 294 char *token_str[3]; |
414 char* test_str = strdup(ao_subdevice); | 295 char* test_str = strdup(ao_subdevice); |
415 | 296 |
416 //printf("subd=%s, test=%s\n", ao_subdevice,test_str); | |
417 | 297 |
418 if ((strcspn(ao_subdevice, ":")) > 0) { | 298 if ((strcspn(ao_subdevice, ":")) > 0) { |
419 | 299 |
420 sub_str = strtok(test_str, ":"); | 300 sub_str = strtok(test_str, ":"); |
421 *(token_str) = sub_str; | 301 *(token_str) = sub_str; |
422 | 302 |
423 while (((sub_str = strtok(NULL, ":")) != NULL) && (i2 <= 3)) { | 303 while (((sub_str = strtok(NULL, ":")) != NULL) && (i2 <= 3)) { |
424 *(token_str+i2) = sub_str; | 304 *(token_str+i2) = sub_str; |
425 //printf("token %i: %s\n", i2, *(token_str+i2)); | |
426 i2 += 1; | 305 i2 += 1; |
427 } | 306 } |
428 | 307 |
429 for (i3=0; i3 <= i2-1; i3++) { | 308 for (i3=0; i3 <= i2-1; i3++) { |
430 //printf("test %i, %s\n", i3, *(token_str+i3)); | |
431 if (strcmp(*(token_str + i3), "mmap") == 0) { | 309 if (strcmp(*(token_str + i3), "mmap") == 0) { |
432 ao_mmap = 1; | 310 ao_mmap = 1; |
433 } | 311 } |
434 else if (strcmp(*(token_str+i3), "noblock") == 0) { | 312 else if (strcmp(*(token_str+i3), "noblock") == 0) { |
435 ao_noblock = 1; | 313 ao_noblock = 1; |
436 } | 314 } |
437 else if (strcmp(*(token_str+i3), "hw") == 0) { | 315 else if (strcmp(*(token_str+i3), "hw") == 0) { |
438 if ((i3 < i2-1) && (strcmp(*(token_str+i3+1), "noblock") != 0) && (strcmp(*(token_str+i3+1), "mmap") != 0)) { | 316 if ((i3 < i2-1) && (strcmp(*(token_str+i3+1), "noblock") != 0) && (strcmp(*(token_str+i3+1), "mmap") != 0)) { |
439 //printf("next tok = %s\n", *(token_str+(i3+1))); | |
440 alsa_device = alloca(ALSA_DEVICE_SIZE); | 317 alsa_device = alloca(ALSA_DEVICE_SIZE); |
441 snprintf(alsa_device, ALSA_DEVICE_SIZE, "hw:%s", *(token_str+(i3+1))); | 318 snprintf(alsa_device, ALSA_DEVICE_SIZE, "hw:%s", *(token_str+(i3+1))); |
442 device_set = 1; | 319 device_set = 1; |
443 } | 320 } |
444 else { | 321 else { |
445 //printf("setting hw\n"); | |
446 alsa_device = *(token_str+i3); | 322 alsa_device = *(token_str+i3); |
447 device_set = 1; | 323 device_set = 1; |
448 } | 324 } |
449 } | 325 } |
450 else if (device_set == 0 && (!ao_mmap || !ao_noblock)) { | 326 else if (device_set == 0 && (!ao_mmap || !ao_noblock)) { |
451 //printf("setting common, %s\n", *(token_str+i3)); | |
452 alsa_device = *(token_str+i3); | 327 alsa_device = *(token_str+i3); |
453 device_set = 1; | 328 device_set = 1; |
454 } | 329 } |
455 } | 330 } |
456 } | 331 } |
457 } //end parsing ao_subdevice | 332 } //end parsing ao_subdevice |
333 | |
334 /* switch for spdif | |
335 * sets opening sequence for SPDIF | |
336 * sets also the playback and other switches 'on the fly' | |
337 * while opening the abstract alias for the spdif subdevice | |
338 * 'iec958' | |
339 */ | |
340 if (format == AFMT_AC3) { | |
341 char devstr[128]; | |
342 unsigned char s[4]; | |
343 int err, c; | |
344 | |
345 switch (channels) { | |
346 case 1: | |
347 case 2: | |
348 | |
349 s[0] = IEC958_AES0_NONAUDIO | | |
350 IEC958_AES0_CON_EMPHASIS_NONE; | |
351 s[1] = IEC958_AES1_CON_ORIGINAL | | |
352 IEC958_AES1_CON_PCM_CODER; | |
353 s[2] = 0; | |
354 s[3] = IEC958_AES3_CON_FS_48000; | |
355 | |
356 sprintf(devstr, "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x", | |
357 s[0], s[1], s[2], s[3]); | |
358 | |
359 if (verbose) | |
360 printf("alsa-spdif-init: playing AC3, %i channels\n", channels); | |
361 break; | |
362 case 4: | |
363 strcpy(devstr, "surround40"); | |
364 break; | |
365 | |
366 case 6: | |
367 strcpy(devstr, "surround51"); | |
368 break; | |
369 | |
370 default: | |
371 fprintf(stderr, "%d channels are not supported\n", channels); | |
372 exit (0); | |
373 } | |
374 | |
375 alsa_device = devstr; | |
376 } | |
458 | 377 |
459 if (alsa_device == NULL) | 378 if (alsa_device == NULL) |
460 { | 379 { |
461 int tmp_device, tmp_subdevice, err; | 380 int tmp_device, tmp_subdevice, err; |
462 | 381 |
504 printf(" mmap-mode and the device-name as first card third device\n"); | 423 printf(" mmap-mode and the device-name as first card third device\n"); |
505 return(0); | 424 return(0); |
506 } else { | 425 } else { |
507 printf("alsa-init: soundcard set to %s\n", alsa_device); | 426 printf("alsa-init: soundcard set to %s\n", alsa_device); |
508 } | 427 } |
509 | |
510 // switch for spdif | |
511 // Try to initialize the SPDIF interface | |
512 if (format == AFMT_AC3) { | |
513 if (device_set) | |
514 alsa_handler = spdif_init(alsa_device); | |
515 else | |
516 alsa_handler = spdif_init("iec958"); | |
517 } | |
518 | 428 |
519 //setting modes for block or nonblock-mode | 429 //setting modes for block or nonblock-mode |
520 if (ao_noblock) { | 430 if (ao_noblock) { |
521 open_mode = SND_PCM_NONBLOCK; | 431 open_mode = SND_PCM_NONBLOCK; |
522 set_block_mode = 1; | 432 set_block_mode = 1; |