Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / audioalsa.C
index 7a8d712c3b8f2687280dd33a9bccfa0925872c12..21fe8b1e1fd2520982a6556f3714b512c82d8657 100644 (file)
@@ -2,6 +2,7 @@
 /*
  * CINELERRA
  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2003-2016 Cinelerra CV contributors
  *
  * 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
@@ -67,7 +68,7 @@ public:
        ~alsa_leaks() { snd_config_update_free_global(); }
 } alsa_leak;
 
-void AudioALSA::list_devices(ArrayList<char*> *devices, int pcm_title, int mode)
+void AudioALSA::list_devices(ArrayList<char*> *names, ArrayList<char*> *pcm_names, int mode)
 {
        snd_ctl_t *handle;
        int card, err, dev;
@@ -92,24 +93,22 @@ void AudioALSA::list_devices(ArrayList<char*> *devices, int pcm_title, int mode)
 
        card = -1;
 #define DEFAULT_DEVICE "default"
-       char *result = new char[strlen(DEFAULT_DEVICE) + 1];
-       devices->append(result);
-       strcpy(result, DEFAULT_DEVICE);
+       if( names )
+               names->append(cstrdup(DEFAULT_DEVICE));
+       if( pcm_names )
+               pcm_names->append(cstrdup(DEFAULT_DEVICE));
 
-       while(snd_card_next(&card) >= 0)
-       {
+       while(snd_card_next(&card) >= 0) {
                char name[BCTEXTLEN];
                if(card < 0) break;
                sprintf(name, "hw:%i", card);
 
-               if((err = snd_ctl_open(&handle, name, 0)) < 0)
-               {
+               if((err = snd_ctl_open(&handle, name, 0)) < 0) {
                        printf("AudioALSA::list_devices card=%i: %s\n", card, snd_strerror(err));
                        continue;
                }
 
-               if((err = snd_ctl_card_info(handle, info)) < 0)
-               {
+               if((err = snd_ctl_card_info(handle, info)) < 0) {
                        printf("AudioALSA::list_devices card=%i: %s\n", card, snd_strerror(err));
                        snd_ctl_close(handle);
                        continue;
@@ -117,103 +116,36 @@ void AudioALSA::list_devices(ArrayList<char*> *devices, int pcm_title, int mode)
 
                dev = -1;
 
-               while(1)
-               {
+               while(1) {
                        if(snd_ctl_pcm_next_device(handle, &dev) < 0)
                                printf("AudioALSA::list_devices: snd_ctl_pcm_next_device\n");
 
-                       if (dev < 0)
-                               break;
+                       if (dev < 0) break;
 
                        snd_pcm_info_set_device(pcminfo, dev);
                        snd_pcm_info_set_subdevice(pcminfo, 0);
                        snd_pcm_info_set_stream(pcminfo, stream);
 
-                       if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0)
-                       {
+                       if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
                                if(err != -ENOENT)
                                        printf("AudioALSA::list_devices card=%i: %s\n", card, snd_strerror(err));
                                continue;
                        }
 
-                       if(pcm_title)
-                       {
+                       if( pcm_names ) {
                                sprintf(string, "plughw:%d,%d", card, dev);
 //                             strcpy(string, "cards.pcm.front");
+                               pcm_names->append(cstrdup(string));
                        }
-                       else
-                       {
+                       if( names ) {
                                sprintf(string, "%s #%d",
-                                       snd_ctl_card_info_get_name(info),
-                                       dev);
+                                       snd_ctl_card_info_get_name(info), dev);
+                               names->append(cstrdup(string));
                        }
-
-                       char *result = devices->append(new char[strlen(string) + 1]);
-                       strcpy(result, string);
                }
 
-
-
                snd_ctl_close(handle);
        }
-
-#ifdef HAVE_PACTL
-// attempt to add pulseaudio "monitor" devices
-//  run: pactl list <sources>|<sinks>
-//   scan output for <Source/Sink> #n,  Name: <device>
-//   build alsa device config and add to alsa snd_config
-
-       const char *arg = 0;
-       switch( mode ) {
-               case MODERECORD:
-                       arg = "source";
-                       break;
-               case MODEPLAY:
-                       arg = "sink";
-                       break;
-       }
-       FILE *pactl = 0;
-       char line[BCTEXTLEN];
-       if( arg ) {
-               sprintf(line, "pactl list %ss", arg);
-               pactl = popen(line,"r");
-       }
-       if( pactl ) {
-               if( pcm_title ) snd_config_update();
-               char name[BCTEXTLEN], pa_name[BCTEXTLEN], device[BCTEXTLEN];
-               name[0] = pa_name[0] = device[0] = 0;
-               int arg_len = strlen(arg);
-               while( fgets(line, sizeof(line), pactl) ) {
-                       if( !strncasecmp(line, arg, arg_len) ) {
-                               char *sp = name, *id = pa_name;
-                               for( char *cp=line; *cp && *cp!='\n'; *sp++=*cp++ )
-                                       *id++ = (*cp>='A' && *cp<='Z') ||
-                                               (*cp>='a' && *cp<='z') ||
-                                               (*cp>='0' && *cp<='9') ? *cp : '_';
-                               *sp++ = 0;  *id = 0;
-                               if( !pcm_title )
-                                       devices->append(strcpy(new char[sp-name], name));
-                               continue;
-                       }
-                       if( !pcm_title ) continue;
-                       if( sscanf(line, " Name: %s", device) != 1 ) continue;
-                       int len = strlen(pa_name);
-                       devices->append(strcpy(new char[len+1], pa_name));
-                       char alsa_config[BCTEXTLEN];
-                       len = snprintf(alsa_config, sizeof(alsa_config),
-                               "pcm.!%s {\n type pulse\n device %s\n}\n"
-                               "ctl.!%s {\n type pulse\n device %s\n}\n",
-                               pa_name, device, pa_name, device);
-                       FILE *fp = fmemopen(alsa_config,len,"r");
-                       snd_input_t *inp;
-                       snd_input_stdio_attach(&inp, fp, 1);
-                       snd_config_load(snd_config, inp);
-                       name[0] = pa_name[0] = device[0] = 0;
-                       snd_input_close(inp);
-               }
-               pclose(pactl);
-       }
-#endif
 }
 
 void AudioALSA::translate_name(char *output, char *input, int mode)
@@ -224,8 +156,10 @@ void AudioALSA::translate_name(char *output, char *input, int mode)
        ArrayList<char*> pcm_titles;
        pcm_titles.set_array_delete();
 
-       list_devices(&titles, 0, mode);
-       list_devices(&pcm_titles, 1, mode);
+       list_devices(&titles, &pcm_titles, mode);
+
+// attempt to add pulseaudio "monitor" devices
+       add_pulse_devices(mode, &titles, &pcm_titles);
 
        sprintf(output, "default");
        for(int i = 0; i < titles.total; i++)
@@ -246,18 +180,10 @@ snd_pcm_format_t AudioALSA::translate_format(int format)
 {
        switch(format)
        {
-       case 8:
-               return SND_PCM_FORMAT_S8;
-               break;
-       case 16:
-               return SND_PCM_FORMAT_S16_LE;
-               break;
-       case 24:
-               return SND_PCM_FORMAT_S24_LE;
-               break;
-       case 32:
-               return SND_PCM_FORMAT_S32_LE;
-               break;
+       case  8: return SND_PCM_FORMAT_S8;
+       case 16: return SND_PCM_FORMAT_S16_LE;
+       case 24: return SND_PCM_FORMAT_S24_LE;
+       case 32: return SND_PCM_FORMAT_S32_LE;
        }
        return SND_PCM_FORMAT_UNKNOWN;
 }
@@ -599,7 +525,7 @@ int AudioALSA::write_buffer(char *buffer, int size)
                                done = 1;
                }
                else {
-                       printf("AudioALSA::write_buffer err %d(%s) at sample %jd\n",
+                       printf(_("AudioALSA::write_buffer err %d(%s) at sample %jd\n"),
                                ret, snd_strerror(ret), device->current_position());
                        Timer::delay(50);
 //                     snd_pcm_resume(get_output());
@@ -696,4 +622,64 @@ snd_pcm_t* AudioALSA::get_input()
        return dsp_in;
 }
 
+void AudioALSA::add_pulse_devices(int mode,
+               ArrayList<char*> *names, ArrayList<char*> *pcm_names)
+{
+#ifdef HAVE_PACTL
+//  run: pactl list <sources>|<sinks>
+//   scan output for <Source/Sink> #n,  Name: <device>
+//   build alsa device config and add to alsa snd_config
+       const char *arg = 0;
+       switch( mode ) {
+       case MODERECORD:
+               arg = "source";
+               break;
+       case MODEPLAY:
+               arg = "sink";
+               break;
+       }
+       FILE *pactl = 0;
+       char line[BCTEXTLEN];
+       if( arg ) {
+               sprintf(line, "LANGUAGE=en_US.UTF-8 pactl list %ss", arg);
+               pactl = popen(line,"r");
+       }
+       if( pactl ) {
+               snd_config_update();
+               char name[BCTEXTLEN], pa_name[BCTEXTLEN], device[BCTEXTLEN];
+               name[0] = pa_name[0] = device[0] = 0;
+               int arg_len = strlen(arg);
+               while( fgets(line, sizeof(line), pactl) ) {
+                       if( !strncasecmp(line, arg, arg_len) ) {
+                               char *sp = name, *id = pa_name;
+                               for( char *cp=line; *cp && *cp!='\n'; *sp++=*cp++ )
+                                       *id++ = (*cp>='A' && *cp<='Z') ||
+                                               (*cp>='a' && *cp<='z') ||
+                                               (*cp>='0' && *cp<='9') ? *cp : '_';
+                               *sp++ = 0;  *id = 0;
+                               if( names )
+                                       names->append(cstrdup(name));
+                               continue;
+                       }
+                       if( sscanf(line, " Name: %s", device) != 1 ) continue;
+                       int len = strlen(pa_name);
+                       if( pcm_names )
+                               pcm_names->append(cstrdup(pa_name));
+                       char alsa_config[BCTEXTLEN];
+                       len = snprintf(alsa_config, sizeof(alsa_config),
+                               "pcm.!%s {\n type pulse\n device %s\n}\n"
+                               "ctl.!%s {\n type pulse\n device %s\n}\n",
+                               pa_name, device, pa_name, device);
+                       FILE *fp = fmemopen(alsa_config,len,"r");
+                       snd_input_t *inp;
+                       snd_input_stdio_attach(&inp, fp, 1);
+                       snd_config_load(snd_config, inp);
+                       name[0] = pa_name[0] = device[0] = 0;
+                       snd_input_close(inp);
+               }
+               pclose(pactl);
+       }
+#endif
+}
+
 #endif