217 lines
6.7 KiB
C++
217 lines
6.7 KiB
C++
|
/*
|
||
|
* Audio Library for Linux and Windows
|
||
|
* ===================================
|
||
|
* Author: DJ0ABR
|
||
|
*
|
||
|
* Author: Kurt Moraw, Ham radio: DJ0ABR, github: dj0abr
|
||
|
* License: GPL-3
|
||
|
*
|
||
|
* compilation:
|
||
|
* Windows ... Visual Studio
|
||
|
* Linux ... make
|
||
|
*
|
||
|
* Documentation see: libkmaudio.h
|
||
|
*
|
||
|
* 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
|
||
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
|
*
|
||
|
* libkmaudio_getDevices_linux.cpp
|
||
|
* like libkmaudio_getDevices.cpp, but uses libsoundio under Linux
|
||
|
* to get the device list. Portaudio does not work under Linux because
|
||
|
* it does not support pulseaudio. Therefore the linux functions
|
||
|
* use libsoundio
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#ifndef WIN32 // Linux
|
||
|
|
||
|
#include "libkmaudio.h"
|
||
|
|
||
|
int scan_devices();
|
||
|
|
||
|
int kmaudio_getDeviceList()
|
||
|
{
|
||
|
if (soundio == NULL)
|
||
|
{
|
||
|
printf("kmaudio_getDeviceList: soundio not initialized\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
soundio_flush_events(soundio); // to get actual data
|
||
|
|
||
|
if (scan_devices() == -1) // read devices
|
||
|
{
|
||
|
printf("cannot read audio devices\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
io_buildAudioDevString();
|
||
|
|
||
|
// close stream if a device does not exist any more
|
||
|
for (int i = 0; i < devanz; i++)
|
||
|
{
|
||
|
if (devlist[i].active == 0)
|
||
|
{
|
||
|
if (devlist[i].instream != NULL)
|
||
|
{
|
||
|
printf("capture device %s disconnected, stop stream\n", devlist[i].name);
|
||
|
soundio_instream_destroy(devlist[i].instream);
|
||
|
devlist[i].instream = NULL;
|
||
|
devlist[i].working = 0;
|
||
|
}
|
||
|
|
||
|
if(devlist[i].outstream != NULL)
|
||
|
{
|
||
|
printf("playback device %s disconnected, stop stream\n", devlist[i].name);
|
||
|
soundio_outstream_destroy(devlist[i].outstream);
|
||
|
devlist[i].outstream = NULL;
|
||
|
devlist[i].working = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int csum = 0;
|
||
|
int sum = 0;
|
||
|
uint8_t* p = (uint8_t*)&(devlist[0].index);
|
||
|
for (int i = 0; i < (int)sizeof(devlist); i++)
|
||
|
sum += *p++;
|
||
|
|
||
|
if (csum != sum)
|
||
|
{
|
||
|
csum = sum;
|
||
|
|
||
|
printf("====== Linux Devices found: ======\n");
|
||
|
for (int i = 0; i < devanz; i++)
|
||
|
{
|
||
|
printf("Index: %d\n", devlist[i].index);
|
||
|
printf("Name: %s\n", devlist[i].name);
|
||
|
printf("ID: %s\n", devlist[i].id);
|
||
|
printf("Cap/PB: %d\n", devlist[i].in_out);
|
||
|
printf("Channels: %d\n", devlist[i].stereo_mono);
|
||
|
printf("SR 44100: %d\n", devlist[i].supports_44100);
|
||
|
printf("SR 48000: %d\n", devlist[i].supports_48000);
|
||
|
printf("is active: %s\n", devlist[i].active ? "yes" : "no");
|
||
|
printf("--------------------------------------\n");
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void get_channel_layout(const struct SoundIoChannelLayout* layout)
|
||
|
{
|
||
|
if (layout->name)
|
||
|
{
|
||
|
if (strstr(layout->name, "ereo"))
|
||
|
devlist[devanz].stereo_mono = 2;
|
||
|
if (strstr(layout->name, "ono"))
|
||
|
devlist[devanz].stereo_mono = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int getDeviceParameters(int idx, struct SoundIoDevice* device)
|
||
|
{
|
||
|
strncpy(devlist[idx].id, device->id, sizeof(devlist[0].id) - 1);
|
||
|
devlist[idx].id[sizeof(devlist[0].id) - 1] = 0;
|
||
|
strncpy(devlist[idx].name, device->name, sizeof(devlist[0].name) - 1);
|
||
|
devlist[idx].name[sizeof(devlist[0].name) - 1] = 0;
|
||
|
|
||
|
for (int i = 0; i < device->layout_count; i++)
|
||
|
get_channel_layout(&device->layouts[i]);
|
||
|
|
||
|
int min = 999999, max = 0;
|
||
|
for (int i = 0; i < device->sample_rate_count; i++)
|
||
|
{
|
||
|
struct SoundIoSampleRateRange* range = &device->sample_rates[i];
|
||
|
if (range->min < min)
|
||
|
min = range->min;
|
||
|
|
||
|
if (range->max > max)
|
||
|
max = range->max;
|
||
|
}
|
||
|
if (min <= 44100) devlist[idx].supports_44100 = 1;
|
||
|
if (max >= 48000) devlist[idx].supports_48000 = 1;
|
||
|
if (devlist[idx].supports_44100 == 0 && devlist[idx].supports_48000 == 0) return 0;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int getDevlistIndex(char* name, char* id)
|
||
|
{
|
||
|
for (int i = 0; i < devanz; i++)
|
||
|
{
|
||
|
// check if already exists
|
||
|
if (!strcmp(devlist[i].id, id) && !strcmp(devlist[i].name, name))
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
int newidx = devanz;
|
||
|
devanz++;
|
||
|
//printf("New Dev:%s Idx:%d\n", name, newidx);
|
||
|
return newidx;
|
||
|
}
|
||
|
|
||
|
int scan_devices()
|
||
|
{
|
||
|
for (int i = 0; i < devanz; i++)
|
||
|
devlist[i].active = 0;
|
||
|
|
||
|
int didx;
|
||
|
for (int i = 0; i < soundio_input_device_count(soundio); i++)
|
||
|
{
|
||
|
struct SoundIoDevice* device = soundio_get_input_device(soundio, i);
|
||
|
if (device == NULL) continue;
|
||
|
if (strstr(device->name, "onitor")) continue;
|
||
|
if (device->probe_error) continue;
|
||
|
|
||
|
didx = getDevlistIndex(device->name, device->id);
|
||
|
if (getDeviceParameters(didx, device) == 1)
|
||
|
{
|
||
|
//printf("%d %d ====CAP:\nid:<%s>\nname:<%s>\n", i,devanz,device->id, device->name);
|
||
|
devlist[didx].in_out = 0;
|
||
|
devlist[didx].index = didx;
|
||
|
devlist[didx].active = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*devlist[didx].name = 0;
|
||
|
*devlist[didx].id = 0;
|
||
|
}
|
||
|
soundio_device_unref(device);
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < soundio_output_device_count(soundio); i++)
|
||
|
{
|
||
|
struct SoundIoDevice* device = soundio_get_output_device(soundio, i);
|
||
|
if (device == NULL) continue;
|
||
|
if (strstr(device->name, "onitor")) continue;
|
||
|
if (device->probe_error) continue;
|
||
|
|
||
|
didx = getDevlistIndex(device->name, device->id);
|
||
|
if (getDeviceParameters(didx, device) == 1)
|
||
|
{
|
||
|
//printf("====PB :\nid:<%s>\nname:<%s>\n", device->id, device->name);
|
||
|
devlist[didx].in_out = 1;
|
||
|
devlist[didx].index = didx;
|
||
|
devlist[didx].active = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*devlist[didx].name = 0;
|
||
|
*devlist[didx].id = 0;
|
||
|
}
|
||
|
soundio_device_unref(device);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif // ifndef WIN32
|