From: bruceperens Date: Sun, 9 Mar 2014 06:53:02 +0000 (+0000) Subject: Enumerate devices, works for ALSA now. X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=1d509134038729be220c9802c5b41e265253d056;p=freetel-svn-tracking.git Enumerate devices, works for ALSA now. git-svn-id: https://svn.code.sf.net/p/freetel/code@1419 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/freedv-server/source/driver_manager.cpp b/freedv-server/source/driver_manager.cpp index b0cb1cf7..6dea58a1 100644 --- a/freedv-server/source/driver_manager.cpp +++ b/freedv-server/source/driver_manager.cpp @@ -14,13 +14,15 @@ namespace FreeDV { // embedded, it's worth some extra effort to avoid STL containers. static std::ostream & - enumerate(std::ostream & stream, const DriverList * list) + enumerate(std::ostream & stream, const char * name, const DriverList * list) { if ( list == 0 ) return stream; + stream << "# " << name << std::endl; + while ( list->key ) { - stream << list->key << ' '; + (*(list->enumerator))(stream); list++; } return stream; @@ -32,7 +34,7 @@ namespace FreeDV { while ( list->key ) { if ( strcmp(key, list->key) == 0 ) { try { - return (*(list->value))(parameters); + return (*(list->creator))(parameters); } catch(std::exception & e) { std::cerr << "Open " << type << " \"" << key << "\": " << e.what() << std::endl; @@ -46,7 +48,11 @@ namespace FreeDV { } static void - place(const char * const key, FreeDV::Base * (*value)(const char *), std::ostream & (*enumerator)(std::ostream &), DriverList * * const list) + place( + const char * const key, + FreeDV::Base * (*creator)(const char *), + std::ostream & (*enumerator)(std::ostream &), + DriverList * * const list) { DriverList * next; @@ -67,10 +73,12 @@ namespace FreeDV { *list = next = new DriverList[2]; next->key = strdup(key); - next->value = value; + next->creator = creator; + next->enumerator = enumerator; ++next; next->key = 0; - next->value = 0; + next->creator = 0; + next->enumerator = 0; } // Global instance of the driver manager used to register @@ -86,32 +94,15 @@ namespace FreeDV { std::ostream & DriverManager::print(std::ostream & s) const { - s << "Audio Input: "; - enumerate(s, audio_input_drivers) << std::endl; - - s << "Audio Output: "; - enumerate(s, audio_output_drivers) << std::endl; - - s << "Codec: "; - enumerate(s, codecs) << std::endl; - - s << "Framer: "; - enumerate(s, framers) << std::endl; - - s << "Keying Output: "; - enumerate(s, keying_output_drivers) << std::endl; - - s << "Modem: "; - enumerate(s, modems) << std::endl; - - s << "PTT Input: "; - enumerate(s, ptt_input_drivers) << std::endl; - - s << "Text Input: "; - enumerate(s, text_input_drivers) << std::endl; - - s << "User Interface: "; - enumerate(s, user_interface_drivers) << std::endl; + enumerate(s, "Audio Input", audio_input_drivers) << std::endl; + enumerate(s, "Audio Output", audio_output_drivers) << std::endl; + enumerate(s, "Codec", codecs) << std::endl; + enumerate(s, "Protocol Framer", framers) << std::endl; + enumerate(s, "Keying Output", keying_output_drivers) << std::endl; + enumerate(s, "Modem", modems) << std::endl; + enumerate(s, "PTT Input", ptt_input_drivers) << std::endl; + enumerate(s, "Text Input", text_input_drivers) << std::endl; + enumerate(s, "User Interface", user_interface_drivers) << std::endl; return s; } diff --git a/freedv-server/source/drivers.h b/freedv-server/source/drivers.h index 13fae2d4..fc3e37d3 100644 --- a/freedv-server/source/drivers.h +++ b/freedv-server/source/drivers.h @@ -703,6 +703,7 @@ namespace FreeDV { namespace Driver { AudioInput * Tone(const char * parameter); AudioOutput * AudioSink(const char * parameter); + AudioOutput * AudioOutALSA(const char * parameter); Codec * CodecNoOp(const char * parameter); Framer * FramerNoOp(const char * parameter); KeyingOutput * KeyingSink(const char * parameter); @@ -716,6 +717,7 @@ namespace FreeDV { namespace Enumerator { std::ostream & Tone(std::ostream &); std::ostream & AudioSink(std::ostream &); + std::ostream & AudioOutALSA(std::ostream &); std::ostream & CodecNoOp(std::ostream &); std::ostream & FramerNoOp(std::ostream &); std::ostream & KeyingSink(std::ostream &); @@ -740,7 +742,8 @@ namespace FreeDV { struct DriverList { const char * key; - FreeDV::Base * (*value)(const char *); + FreeDV::Base * (*creator)(const char *); + std::ostream & (*enumerator)(std::ostream &); }; /// Device driver manager. Allows for registration and enumeration of device diff --git a/freedv-server/source/platform/linux/alsa.cpp b/freedv-server/source/platform/linux/alsa.cpp new file mode 100644 index 00000000..792c3d4e --- /dev/null +++ b/freedv-server/source/platform/linux/alsa.cpp @@ -0,0 +1,73 @@ +#include +#include +#include + +namespace FreeDV { + static std::ostream & + error_message(std::ostream & stream, int error) { + switch ( error ) { + case 0: + break; + case -ENOENT: + stream << " (Not connected)"; + break; + case -EBUSY: + stream << " (In use by another program)"; + break; + case -EACCES: + stream << " (Access denied)"; + break; + default: + stream << " (" << snd_strerror(error) << ')'; + } + return stream; + } + + std::ostream & + ALSAEnumerate(std::ostream & stream, snd_pcm_stream_t mode) + { + int card_index = -1; + snd_pcm_t * pcm_handle; + snd_ctl_card_info_t * info = 0; + + const int error = snd_pcm_open( + &pcm_handle, + "default", + SND_PCM_STREAM_PLAYBACK, + 0); + + stream << "\"alsa:default\""; + error_message(stream, error); + stream << std::endl; + + while ( snd_card_next(&card_index) == 0 && card_index >= 0 ) { + char device_name[20]; + snd_ctl_t * ctl_handle = 0; + int pcm_error = 0; + char * longname = 0; + + if ( snd_card_get_longname(card_index, &longname) == 0 ) { + sprintf(device_name, "hw:%d", card_index); + + const int ctl_error = snd_ctl_open(&ctl_handle, device_name, 0); + if ( ctl_error == 0 ) { + pcm_error = snd_pcm_open(&pcm_handle, device_name, mode, 0); + } + + const int error = ctl_error ? ctl_error : pcm_error; + + stream << "\"alsa:" << longname << '"'; + error_message(stream, error); + stream << std::endl; + + if ( ctl_error == 0 ) { + snd_ctl_close(ctl_handle); + if ( pcm_error == 0 ) + snd_pcm_close(pcm_handle); + } + } + } + + return stream; + } +}; diff --git a/freedv-server/source/platform/linux/audio_out_alsa.cpp b/freedv-server/source/platform/linux/audio_out_alsa.cpp index 345b4ef3..af12e0c0 100644 --- a/freedv-server/source/platform/linux/audio_out_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_out_alsa.cpp @@ -6,6 +6,8 @@ #include namespace FreeDV { + std::ostream & ALSAEnumerate(std::ostream & stream, snd_pcm_stream_t mode); + /// Audio output "sink", discards the audio, for testing. class AudioOutALSA : public AudioOutput { private: @@ -61,10 +63,10 @@ namespace FreeDV { return new ::FreeDV::AudioOutALSA(parameter); } - ostream & - Enumerator::AudioOutALSA(ostream & stream) + std::ostream & + Enumerator::AudioOutALSA(std::ostream & stream) { - return stream; + return ALSAEnumerate(stream, SND_PCM_STREAM_PLAYBACK); } std::size_t