ALSA - prefer stereo configuraton if available.
This commit is contained in:
+65
-2
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Robin E. R. Davies
|
||||
* Copyright (c) 2024 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
@@ -366,11 +366,38 @@ namespace pipedal
|
||||
{
|
||||
/*if not user-specified, try to find the maximum
|
||||
* number of channels */
|
||||
unsigned int channels_max;
|
||||
unsigned int channels_max = 0;
|
||||
unsigned int channels_min = 0;
|
||||
err = snd_pcm_hw_params_get_channels_max(hwParams,
|
||||
&channels_max);
|
||||
if (err < 0) {
|
||||
AlsaError(SS("Can't get channels_max."));
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_get_channels_min(hwParams,
|
||||
&channels_min);
|
||||
if (err < 0) {
|
||||
AlsaError(SS("Can't get channels_min."));
|
||||
}
|
||||
|
||||
|
||||
*channels = channels_max;
|
||||
|
||||
if (channels_max > 2 && channels_min <= 2 && channels_min > 0) {
|
||||
unsigned int bestChannelConfig = 2;
|
||||
|
||||
snd_pcm_hw_params_t* test_params;
|
||||
snd_pcm_hw_params_alloca(&test_params);
|
||||
snd_pcm_hw_params_copy(test_params, hwParams);
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_channels(handle, test_params,
|
||||
bestChannelConfig)) >= 0)
|
||||
{
|
||||
*channels = bestChannelConfig;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (*channels > 1024)
|
||||
{
|
||||
// The default PCM device has unlimited channels.
|
||||
@@ -2109,11 +2136,47 @@ namespace pipedal
|
||||
{
|
||||
throw PiPedalLogicException("No outut channels.");
|
||||
}
|
||||
unsigned int channelsMin;
|
||||
err = snd_pcm_hw_params_get_channels_min(playbackHwParams, &channelsMin);
|
||||
if (err < 0)
|
||||
{
|
||||
throw PiPedalLogicException("No outut channels.");
|
||||
}
|
||||
if (playbackChannels > 2 && channelsMin <=2 && channelsMin > 0)
|
||||
{
|
||||
snd_pcm_hw_params_t* test_params;
|
||||
snd_pcm_hw_params_alloca(&test_params);
|
||||
snd_pcm_hw_params_copy(test_params, playbackHwParams);
|
||||
|
||||
|
||||
if (snd_pcm_hw_params_set_channels(playbackHandle,test_params,(unsigned int)2) >= 0)
|
||||
{
|
||||
playbackChannels = 2;
|
||||
}
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_get_channels_max(captureHwParams, &captureChannels);
|
||||
if (err < 0)
|
||||
{
|
||||
throw PiPedalLogicException("No input channels.");
|
||||
}
|
||||
err = snd_pcm_hw_params_get_channels_min(captureHwParams,&channelsMin);
|
||||
if (err >= 0)
|
||||
{
|
||||
if (captureChannels > 2 && channelsMin <= 2 && channelsMin > 0)
|
||||
{
|
||||
snd_pcm_hw_params_t* test_params;
|
||||
snd_pcm_hw_params_alloca(&test_params);
|
||||
snd_pcm_hw_params_copy(test_params, captureHwParams);
|
||||
|
||||
|
||||
if (snd_pcm_hw_params_set_channels(captureHandle,test_params,(unsigned int)2) >= 0)
|
||||
{
|
||||
captureChannels = 2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inputAudioPorts.clear();
|
||||
for (unsigned int i = 0; i < captureChannels; ++i)
|
||||
|
||||
+9
-1
@@ -638,6 +638,8 @@ add_executable(pipedalconfig
|
||||
CommandLineParser.hpp
|
||||
PiPedalException.hpp
|
||||
ConfigMain.cpp
|
||||
alsaCheck.cpp
|
||||
alsaCheck.hpp
|
||||
ModFileTypes.cpp ModFileTypes.hpp
|
||||
PiPedalConfiguration.hpp PiPedalConfiguration.cpp
|
||||
JackServerSettings.hpp JackServerSettings.cpp
|
||||
@@ -647,7 +649,7 @@ add_executable(pipedalconfig
|
||||
|
||||
)
|
||||
|
||||
target_link_libraries(pipedalconfig PRIVATE PiPedalCommon pthread atomic uuid stdc++fs
|
||||
target_link_libraries(pipedalconfig PRIVATE PiPedalCommon pthread atomic uuid stdc++fs asound
|
||||
)
|
||||
|
||||
add_executable(pipedal_latency_test
|
||||
@@ -668,6 +670,12 @@ target_link_libraries(pipedal_latency_test PRIVATE pthread asound PiPedalCommon
|
||||
)
|
||||
|
||||
|
||||
add_executable(pipedal_alsa_info
|
||||
alsaCheck.cpp alsaCheck.hpp
|
||||
alsaCheckMain.cpp
|
||||
)
|
||||
target_link_libraries(pipedal_alsa_info PRIVATE asound)
|
||||
|
||||
add_executable(capturepresets
|
||||
CapturePresetsMain.cpp
|
||||
Storage.cpp
|
||||
|
||||
+49
-14
@@ -24,6 +24,7 @@
|
||||
#include "CommandLineParser.hpp"
|
||||
#include "SystemConfigFile.hpp"
|
||||
#include "ModFileTypes.hpp"
|
||||
#include "alsaCheck.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <stdlib.h>
|
||||
@@ -92,18 +93,19 @@ namespace fs = std::filesystem;
|
||||
#define REMOVE_OLD_SERVICE 0 // Grandfathering: whether to remove the old shutdown service (now pipedaladmind)
|
||||
#define OLD_SHUTDOWN_SERVICE "pipedalshutdownd"
|
||||
|
||||
|
||||
|
||||
void changeUserShell(const char* username, const char* newShell) {
|
||||
struct passwd* pw;
|
||||
void changeUserShell(const char *username, const char *newShell)
|
||||
{
|
||||
struct passwd *pw;
|
||||
struct passwd p;
|
||||
char buf[1024];
|
||||
|
||||
pw = getpwnam(username);
|
||||
if (pw == nullptr) {
|
||||
if (pw == nullptr)
|
||||
{
|
||||
throw std::runtime_error("User not found");
|
||||
}
|
||||
if (strcmp(pw->pw_shell,newShell) == 0) {
|
||||
if (strcmp(pw->pw_shell, newShell) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::string args = SS("/usr/sbin/usermod -s " << newShell << " " << username);
|
||||
@@ -114,7 +116,6 @@ void changeUserShell(const char* username, const char* newShell) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fs::path GetServiceFileName(const std::string &serviceName)
|
||||
{
|
||||
return fs::path(SERVICE_PATH) / (serviceName + ".service");
|
||||
@@ -218,7 +219,7 @@ bool disableAvahiConfigLine(SystemConfigFile &avahi, const std::string §ion,
|
||||
++line;
|
||||
}
|
||||
}
|
||||
avahi.UndoableAddLine(line,lineStart+"no");
|
||||
avahi.UndoableAddLine(line, lineStart + "no");
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -242,7 +243,7 @@ static void AvahiInstall()
|
||||
|
||||
changed |= disableAvahiConfigLine(avahi, "[server]", "use-ipv6=");
|
||||
changed |= disableAvahiConfigLine(avahi, "[publish]", "publish-aaaa-on-ipv4=");
|
||||
|
||||
|
||||
if (changed)
|
||||
{
|
||||
avahi.Save();
|
||||
@@ -1035,12 +1036,13 @@ void Install(const fs::path &programPrefix, const std::string endpointAddress)
|
||||
// add to netdev group
|
||||
sysExec(USERMOD_BIN " -a -G " NETDEV_GROUP_NAME " " SERVICE_ACCOUNT_NAME);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
changeUserShell(SERVICE_ACCOUNT_NAME, "/usr/sbin/nologon");
|
||||
} catch (const std::exception&e)
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cout << "Error: Can't set user shell for pipedal_d. " << e.what() << std::endl;
|
||||
|
||||
}
|
||||
// create and configure /var directory.
|
||||
|
||||
@@ -1162,7 +1164,6 @@ void Install(const fs::path &programPrefix, const std::string endpointAddress)
|
||||
FixPermissions();
|
||||
ModFileTypes::CreateDefaultDirectories("/var/pipedal/audio_uploads");
|
||||
|
||||
|
||||
StopService(false);
|
||||
AvahiInstall();
|
||||
InstallPgpKey();
|
||||
@@ -1281,6 +1282,10 @@ static void PrintHelp()
|
||||
|
||||
<< HangingIndent() << " --disable-hotspot\tDisabled the Wi-Fi hotspot."
|
||||
<< "\n\n"
|
||||
<< HangingIndent() << " --alsa-devices\tList available ALSA hw devices."
|
||||
<< "\n\n"
|
||||
<< HangingIndent() << " --alsa-device [device_id]\tPrint info for the specified ALSA device."
|
||||
<< "\n\n"
|
||||
<< HangingIndent() << " --list-wifi-channels [<country_code>] \tList valid Wifi channels for the current/specified country."
|
||||
<< "\n\n"
|
||||
|
||||
@@ -1364,6 +1369,8 @@ int main(int argc, char **argv)
|
||||
bool fix_permissions = false;
|
||||
bool nosudo = false;
|
||||
bool excludeShutdownService = false;
|
||||
bool alsaDevices = false;
|
||||
std::string alsaDevice;
|
||||
std::string prefixOption;
|
||||
std::string portOption;
|
||||
std::string homeNetwork;
|
||||
@@ -1387,12 +1394,14 @@ int main(int argc, char **argv)
|
||||
parser.AddOption("--home-network", &homeNetwork);
|
||||
parser.AddOption("--no-ethernet", &noEthernet);
|
||||
parser.AddOption("--no-wifi", &noWifi);
|
||||
parser.AddOption("--alsa-devices", &alsaDevices);
|
||||
parser.AddOption("--alsa-device", &alsaDevice);
|
||||
try
|
||||
{
|
||||
parser.Parse(argc, (const char **)argv);
|
||||
|
||||
int actionCount =
|
||||
help + get_current_port + install + uninstall + stop + start + enable + disable + enable_hotspot + disable_hotspot + restart + enable_p2p + disable_p2p + list_p2p_channels + fix_permissions;
|
||||
(!alsaDevice.empty()) + alsaDevices + help + get_current_port + install + uninstall + stop + start + enable + disable + enable_hotspot + disable_hotspot + restart + enable_p2p + disable_p2p + list_p2p_channels + fix_permissions;
|
||||
if (actionCount > 1)
|
||||
{
|
||||
throw std::runtime_error("Please provide only one action.");
|
||||
@@ -1454,6 +1463,32 @@ int main(int argc, char **argv)
|
||||
std::cout << "current port: " << GetCurrentWebServicePort() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (alsaDevices)
|
||||
{
|
||||
try
|
||||
{
|
||||
list_alsa_devices();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "Error: " << e.what() << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (alsaDevice.length() != 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
check_alsa_channel_configs(alsaDevice.c_str());
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cerr << "Error: " << e.what() << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (list_p2p_channels)
|
||||
{
|
||||
return ListP2PChannels(parser.Arguments());
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2024 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "alsaCheck.hpp"
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "ss.hpp"
|
||||
#include <stdexcept>
|
||||
#include "Finally.hpp"
|
||||
|
||||
|
||||
|
||||
void pipedal::check_alsa_channel_configs(const char* device_name) {
|
||||
snd_pcm_t* handle;
|
||||
int err;
|
||||
|
||||
// Open PCM device for playback
|
||||
if ((err = snd_pcm_open(&handle, device_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
||||
throw std::runtime_error(SS("Cannot open audio device " << device_name << ": " << snd_strerror(err)));
|
||||
return;
|
||||
}
|
||||
|
||||
Finally ff([handle] {
|
||||
snd_pcm_close(handle);
|
||||
});
|
||||
// Get hardware parameters
|
||||
snd_pcm_hw_params_t* hw_params;
|
||||
snd_pcm_hw_params_alloca(&hw_params);
|
||||
|
||||
if ((err = snd_pcm_hw_params_any(handle, hw_params)) < 0) {
|
||||
const std::string errorMessage = snd_strerror(err);
|
||||
throw std::runtime_error(SS("Cannot initialize hardware parameter structure: " << errorMessage));
|
||||
}
|
||||
|
||||
// Get channel count range
|
||||
unsigned int min_channels, max_channels;
|
||||
if ((err = snd_pcm_hw_params_get_channels_min(hw_params, &min_channels)) < 0) {
|
||||
const std::string errorMessage = snd_strerror(err);
|
||||
throw std::runtime_error(SS("Cannot get minimum channels: " << errorMessage));
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_get_channels_max(hw_params, &max_channels)) < 0) {
|
||||
std::cerr << "Cannot get maximum channels: " << snd_strerror(err) << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Device: " << device_name << std::endl;
|
||||
std::cout << "Channel range: " << min_channels << " to " << max_channels << std::endl;
|
||||
std::cout << "\nSupported channel configurations:" << std::endl;
|
||||
|
||||
// Test specific channel counts
|
||||
std::vector<unsigned int> common_configs = {1, 2, 4, 6, 8};
|
||||
for (unsigned int channels : common_configs) {
|
||||
if (channels >= min_channels && channels <= max_channels) {
|
||||
snd_pcm_hw_params_t* test_params;
|
||||
snd_pcm_hw_params_alloca(&test_params);
|
||||
snd_pcm_hw_params_copy(test_params, hw_params);
|
||||
|
||||
if (snd_pcm_hw_params_set_channels(handle, test_params, channels) == 0) {
|
||||
std::string config_name;
|
||||
switch (channels) {
|
||||
case 1: config_name = "Mono"; break;
|
||||
case 2: config_name = "Stereo"; break;
|
||||
case 4: config_name = "Quadraphonic"; break;
|
||||
case 6: config_name = "5.1 Surround"; break;
|
||||
case 8: config_name = "7.1 Surround"; break;
|
||||
default: config_name = std::to_string(channels) + " channels";
|
||||
}
|
||||
std::cout << " " << channels << " channels (" << config_name << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void print_device_info(snd_ctl_t* handle, int card, int device) {
|
||||
snd_pcm_info_t* pcminfo;
|
||||
snd_pcm_info_alloca(&pcminfo);
|
||||
snd_pcm_info_set_device(pcminfo, device);
|
||||
snd_pcm_info_set_subdevice(pcminfo, 0);
|
||||
|
||||
// Check playback
|
||||
snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
|
||||
bool has_playback = snd_ctl_pcm_info(handle, pcminfo) >= 0;
|
||||
|
||||
// Check capture
|
||||
snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
|
||||
bool has_capture = snd_ctl_pcm_info(handle, pcminfo) >= 0;
|
||||
|
||||
if (has_playback || has_capture) {
|
||||
char name[32];
|
||||
snprintf(name, sizeof(name), "hw:%d,%d", card, device);
|
||||
|
||||
// Get device name
|
||||
snd_pcm_t* pcm;
|
||||
std::string device_name = "Unknown";
|
||||
if (snd_pcm_open(&pcm, name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) >= 0) {
|
||||
device_name = snd_pcm_name(pcm);
|
||||
snd_pcm_close(pcm);
|
||||
}
|
||||
|
||||
// Print basic info
|
||||
std::cout << "\n Subdevice: " << name << " - " << device_name << std::endl;
|
||||
std::cout << " ID: " << snd_pcm_info_get_id(pcminfo) << std::endl;
|
||||
std::cout << " Capabilities:";
|
||||
if (has_playback) std::cout << " PLAYBACK";
|
||||
if (has_capture) std::cout << " CAPTURE";
|
||||
std::cout << std::endl;
|
||||
|
||||
// Get hardware parameters for more detailed info
|
||||
if (has_playback) {
|
||||
snd_pcm_t* pcm_handle;
|
||||
if (snd_pcm_open(&pcm_handle, name, SND_PCM_STREAM_PLAYBACK, 0) >= 0) {
|
||||
snd_pcm_hw_params_t* hw_params;
|
||||
snd_pcm_hw_params_alloca(&hw_params);
|
||||
|
||||
if (snd_pcm_hw_params_any(pcm_handle, hw_params) >= 0) {
|
||||
unsigned int min_channels, max_channels;
|
||||
unsigned int min_rate, max_rate;
|
||||
|
||||
snd_pcm_hw_params_get_channels_min(hw_params, &min_channels);
|
||||
snd_pcm_hw_params_get_channels_max(hw_params, &max_channels);
|
||||
snd_pcm_hw_params_get_rate_min(hw_params, &min_rate, 0);
|
||||
snd_pcm_hw_params_get_rate_max(hw_params, &max_rate, 0);
|
||||
|
||||
std::cout << " Channels: " << min_channels << " - " << max_channels << std::endl;
|
||||
std::cout << " Sample rates: " << min_rate << " - " << max_rate << " Hz" << std::endl;
|
||||
|
||||
// Get supported formats
|
||||
std::cout << " Supported formats:";
|
||||
for (snd_pcm_format_t fmt = SND_PCM_FORMAT_S8; fmt <= SND_PCM_FORMAT_LAST; fmt = snd_pcm_format_t(fmt + 1)) {
|
||||
if (snd_pcm_hw_params_test_format(pcm_handle, hw_params, fmt) == 0) {
|
||||
std::cout << " " << snd_pcm_format_name(fmt);
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
snd_pcm_close(pcm_handle);
|
||||
} else {
|
||||
std::cout << " (device in use)" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pipedal::list_alsa_devices() {
|
||||
int card = -1;
|
||||
int err;
|
||||
|
||||
std::cout << "=== ALSA Hardware Devices ===" << std::endl;
|
||||
|
||||
// Iterate through cards
|
||||
while ((err = snd_card_next(&card)) >= 0 && card >= 0) {
|
||||
snd_ctl_t* handle;
|
||||
char name[32];
|
||||
snprintf(name, sizeof(name), "hw:%d", card);
|
||||
|
||||
if ((err = snd_ctl_open(&handle, name, 0)) < 0) {
|
||||
std::cerr << "Cannot open control for card " << card << ": " << snd_strerror(err) << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get card info
|
||||
snd_ctl_card_info_t* info;
|
||||
snd_ctl_card_info_alloca(&info);
|
||||
if ((err = snd_ctl_card_info(handle, info)) < 0) {
|
||||
std::cerr << "Cannot get card info: " << snd_strerror(err) << std::endl;
|
||||
snd_ctl_close(handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::cout << "\nSound Card hw:" << snd_ctl_card_info_get_id(info) << std::endl;
|
||||
std::cout << " Name: " << snd_ctl_card_info_get_name(info) << std::endl;
|
||||
std::cout << " Driver: " << snd_ctl_card_info_get_driver(info) << std::endl;
|
||||
|
||||
// Iterate through devices on this card
|
||||
int device = -1;
|
||||
while ((err = snd_ctl_pcm_next_device(handle, &device)) >= 0 && device >= 0) {
|
||||
print_device_info(handle, card, device);
|
||||
}
|
||||
|
||||
snd_ctl_close(handle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2024 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace pipedal {
|
||||
void check_alsa_channel_configs(const char* device_name = "default");
|
||||
void list_alsa_devices();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "CommandLineParser.hpp"
|
||||
#include "alsaCheck.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace pipedal;
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
bool listDevices = false;
|
||||
|
||||
try {
|
||||
CommandLineParser commandLineParser;
|
||||
|
||||
std::string device = "";
|
||||
|
||||
commandLineParser.AddOption("--list",&listDevices);
|
||||
|
||||
commandLineParser.Parse(argc,(const char**)argv);
|
||||
|
||||
if (commandLineParser.Arguments().size() >= 1) {
|
||||
device = commandLineParser.Arguments()[0];
|
||||
}
|
||||
if (listDevices || device.empty()) {
|
||||
list_alsa_devices();
|
||||
} else {
|
||||
check_alsa_channel_configs(device.c_str());
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
} catch (const std::exception &e)
|
||||
{
|
||||
cerr << "Error: " << e.what() << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user