summaryrefslogtreecommitdiffstats
path: root/src/ahl-deviceenum.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ahl-deviceenum.c')
-rw-r--r--src/ahl-deviceenum.c331
1 files changed, 0 insertions, 331 deletions
diff --git a/src/ahl-deviceenum.c b/src/ahl-deviceenum.c
deleted file mode 100644
index 7e67d7a..0000000
--- a/src/ahl-deviceenum.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 2017 "Audiokinetic Inc"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <alsa/asoundlib.h>
-#include <alsa/pcm.h>
-#include <json-c/json.h>
-#include "wrap-json.h"
-
-#include "ahl-binding.h"
-#include "ahl-policy.h"
-
-extern AHLCtxT g_AHLCtx;
-
-// TODO: Hash from endpoint ID information instead
-static endpointID_t CreateNewSourceID()
-{
- endpointID_t newID = g_AHLCtx.nextSourceEndpointID;
- g_AHLCtx.nextSourceEndpointID++;
- return newID;
-}
-
-// TODO: Hash from endpoint ID information instead
-static endpointID_t CreateNewSinkID()
-{
- endpointID_t newID = g_AHLCtx.nextSinkEndpointID;
- g_AHLCtx.nextSinkEndpointID++;
- return newID;
-}
-
-// Watchout: This function uses strtok and is destructive on the input string (use a copy)
-static int SeparateDomainFromDeviceURI( char * in_pDeviceURI, char ** out_pDomain, char ** out_pDevice)
-{
- *out_pDomain = strtok(in_pDeviceURI, ".");
- if (*out_pDomain == NULL)
- {
- AFB_ERROR("Error tokenizing device URI -> %s",in_pDeviceURI);
- return 1;
- }
- // TODO: Validate domain is known string (e.g. ALSA,Pulse,GStreamer)
- *out_pDevice = strtok(NULL, ".");
- if (*out_pDevice == NULL)
- {
- AFB_ERROR("Error tokenizing device URI -> %s",in_pDeviceURI);
- return 1;
- }
- return 0;
-}
-
-static int IsAlsaDomain(const char * in_pDomainStr)
-{
- return (int) (strcasecmp(in_pDomainStr,AHL_DOMAIN_ALSA) == 0);
-}
-
-static int IsPulseDomain(const char * in_pDomainStr)
-{
- return (int) (strcasecmp(in_pDomainStr,AHL_DOMAIN_PULSE) == 0);
-}
-
-static int IsGStreamerDomain(const char * in_pDomainStr)
-{
- return (int) (strcasecmp(in_pDomainStr,AHL_DOMAIN_GSTREAMER) == 0);
-}
-
-static int IsExternalDomain(const char * in_pDomainStr)
-{
- return (int) (strcasecmp(in_pDomainStr,AHL_DOMAIN_EXTERNAL) == 0);
-}
-
-static int FillALSAPCMInfo( snd_pcm_t * in_pPcmHandle, EndpointInfoT * out_pEndpointInfo )
-{
- g_assert_nonnull(in_pPcmHandle);
- g_assert_nonnull(out_pEndpointInfo);
- snd_pcm_type_t pcmType = 0;
- snd_pcm_info_t * pPcmInfo = NULL;
- int iAlsaRet = 0;
- const char * pCardName = NULL;
- int retVal = 0;
- snd_ctl_t * ctlHandle = NULL;
- snd_ctl_card_info_t * ctlInfo = NULL;
-
- snd_pcm_info_alloca(&pPcmInfo);
- snd_ctl_card_info_alloca(&ctlInfo);
-
- // retrieve PCM type
- pcmType = snd_pcm_type(in_pPcmHandle);
- switch (pcmType) {
- case SND_PCM_TYPE_HW:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_HW;
- break;
- case SND_PCM_TYPE_DMIX:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_DMIX;
- break;
- case SND_PCM_TYPE_SOFTVOL:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_SOFTVOL;
- break;
- case SND_PCM_TYPE_PLUG:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_PLUG;
- break;
- default:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_OTHER;
- break;
- }
-
- iAlsaRet = snd_pcm_info(in_pPcmHandle,pPcmInfo);
- if (iAlsaRet < 0)
- {
- AFB_WARNING("Error retrieving PCM device info");
- return 1;
- }
-
- // get card number
- out_pEndpointInfo->alsaInfo.cardNum = snd_pcm_info_get_card(pPcmInfo);
- if ( out_pEndpointInfo->alsaInfo.cardNum < 0 )
- {
- AFB_WARNING("No Alsa card number available");
- return 1;
- }
-
- // get device number
- out_pEndpointInfo->alsaInfo.deviceNum = snd_pcm_info_get_device(pPcmInfo);
- if ( out_pEndpointInfo->alsaInfo.deviceNum < 0 )
- {
- AFB_WARNING("No Alsa device number available");
- return 1;
- }
-
- // get sub-device number
- out_pEndpointInfo->alsaInfo.subDeviceNum = snd_pcm_info_get_subdevice(pPcmInfo);
- if ( out_pEndpointInfo->alsaInfo.subDeviceNum < 0 )
- {
- AFB_WARNING("No Alsa subdevice number available");
- return 1;
- }
-
- char cardName[32];
- sprintf(cardName, "hw:%d", out_pEndpointInfo->alsaInfo.cardNum);
- iAlsaRet = snd_ctl_open(&ctlHandle, cardName, 0);
- if ( iAlsaRet < 0 )
- {
- AFB_WARNING("Could not open ALSA card control");
- return 1;
- }
-
- iAlsaRet = snd_ctl_card_info(ctlHandle, ctlInfo);
- if ( iAlsaRet < 0 )
- {
- AFB_WARNING("Could not retrieve ALSA card info");
- snd_ctl_close(ctlHandle);
- return 1;
- }
-
- // Populate unique target card name
- pCardName = snd_ctl_card_info_get_id(ctlInfo);
- if (pCardName == NULL)
- {
- AFB_WARNING("No Alsa card name available");
- snd_ctl_close(ctlHandle);
- return 1;
- }
- out_pEndpointInfo->gsDeviceName = g_strdup(pCardName);
-
- snd_ctl_close(ctlHandle);
-
- return retVal;
-}
-
-EndpointInfoT * InitEndpointInfo()
-{
- EndpointInfoT * pEndpointInfo = (EndpointInfoT*) malloc(sizeof(EndpointInfoT));
- memset(pEndpointInfo,0,sizeof(EndpointInfoT));
- pEndpointInfo->endpointID = AHL_UNDEFINED;
- pEndpointInfo->type = ENDPOINTTYPE_MAXVALUE;
- pEndpointInfo->deviceURIType = DEVICEURITYPE_MAXVALUE;
- pEndpointInfo->alsaInfo.cardNum = AHL_UNDEFINED;
- pEndpointInfo->alsaInfo.deviceNum = AHL_UNDEFINED;
- pEndpointInfo->alsaInfo.subDeviceNum = AHL_UNDEFINED;
- pEndpointInfo->format.sampleRate = AHL_UNDEFINED;
- pEndpointInfo->format.numChannels = AHL_UNDEFINED;
- pEndpointInfo->format.sampleType = AHL_FORMAT_UNKNOWN;
- pEndpointInfo->pPropTable = g_hash_table_new(g_str_hash, g_str_equal);
- return pEndpointInfo;
-}
-
-void TermEndpointInfo( EndpointInfoT * out_pEndpointInfo )
-{
- #define SAFE_FREE(__ptr__) if(__ptr__) g_free(__ptr__); __ptr__ = NULL;
- SAFE_FREE(out_pEndpointInfo->gsDeviceName);
- SAFE_FREE(out_pEndpointInfo->gsDisplayName);
- SAFE_FREE(out_pEndpointInfo->gsDeviceDomain);
- SAFE_FREE(out_pEndpointInfo->pRoleName);
- SAFE_FREE(out_pEndpointInfo->gsDeviceURI);
- SAFE_FREE(out_pEndpointInfo->gsHALAPIName);
-
- if (out_pEndpointInfo->pPropTable) {
- // Free json_object for all property values
- GHashTableIter iter;
- gpointer key, value;
- g_hash_table_iter_init (&iter, out_pEndpointInfo->pPropTable);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- if (value)
- json_object_put(value);
- }
- g_hash_table_remove_all(out_pEndpointInfo->pPropTable);
- g_hash_table_destroy(out_pEndpointInfo->pPropTable);
- out_pEndpointInfo->pPropTable = NULL;
- }
- // GLib automatically frees item when removed from the array
-}
-
-// For a given audio role
-int EnumerateDevices(json_object * in_jDeviceArray, char * in_pAudioRole, EndpointTypeT in_deviceType, GPtrArray * out_pEndpointArray) {
-
- g_assert_nonnull(in_jDeviceArray);
- int iNumberDevices = json_object_array_length(in_jDeviceArray);
-
- // Parse and validate list of available devices
- for (int i = 0; i < iNumberDevices; i++)
- {
- char * pDeviceURIDomain = NULL;
- char * pFullDeviceURI = NULL;
- char * pDeviceURIPCM = NULL;
- int err = 0;
-
- json_object * jDevice = json_object_array_get_idx(in_jDeviceArray,i);
- if (jDevice == NULL) {
- AFB_WARNING("Invalid device array -> %s",json_object_to_json_string(in_jDeviceArray));
- continue;
- }
- // strip domain name from URI
- pFullDeviceURI = (char *)json_object_get_string(jDevice);
- char * pFullDeviceURICopy = g_strdup(pFullDeviceURI); // strtok is destructive
- err = SeparateDomainFromDeviceURI(pFullDeviceURICopy,&pDeviceURIDomain,&pDeviceURIPCM);
- if (err)
- {
- AFB_WARNING("Invalid device URI string -> %s",pFullDeviceURICopy);
- continue;
- }
-
- EndpointInfoT * pEndpointInfo = InitEndpointInfo();
- g_assert_nonnull(pEndpointInfo);
-
- // non ALSA URI are simply passed to application (no validation) at this time
- // In Non ALSA case devices in config are assumed to be available, if not application can fallback on explicit device selection
- pEndpointInfo->gsDeviceName = g_strdup(pDeviceURIPCM);
- pEndpointInfo->gsDeviceDomain = g_strdup(pDeviceURIDomain);
- pEndpointInfo->gsDeviceURI = g_strdup(pDeviceURIPCM);
- pEndpointInfo->pRoleName = g_strdup(in_pAudioRole);
-
- g_free(pFullDeviceURICopy);
- pFullDeviceURICopy = NULL;
- pDeviceURIDomain = NULL; //Derived from above mem
- pDeviceURIPCM = NULL; //Derived from above mem
-
- if (IsAlsaDomain(pEndpointInfo->gsDeviceDomain))
- {
- // TODO: Missing support for loose name matching
- // This will require using ALSA hints to get PCM names
- // And would iterate over all available devices matching string (possibly all if no filtering is desired for a certain role)
-
- // Get PCM handle
- snd_pcm_t * pPcmHandle = NULL;
- snd_pcm_stream_t streamType = in_deviceType == ENDPOINTTYPE_SOURCE ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK;
- err = snd_pcm_open(&pPcmHandle, pEndpointInfo->gsDeviceURI, streamType, 0);
- if (err < 0)
- {
- AFB_NOTICE("Alsa PCM device was not found -> %s", pEndpointInfo->gsDeviceURI);
- continue;
- }
-
- err = FillALSAPCMInfo(pPcmHandle,pEndpointInfo);
- if (err) {
- AFB_WARNING("Unable to retrieve PCM information for PCM -> %s",pEndpointInfo->gsDeviceURI);
- snd_pcm_close(pPcmHandle);
- continue;
- }
-
- snd_pcm_close(pPcmHandle);
- }
- else if (IsPulseDomain(pEndpointInfo->gsDeviceDomain)) {
- // Pulse domain
- // For now display name is device URI directly, could extrapolated using more heuristics or even usins Pulse API later on
- pEndpointInfo->deviceURIType = DEVICEURITYPE_NOT_ALSA;
- }
- else if (IsGStreamerDomain(pEndpointInfo->gsDeviceDomain)){
- // GStreamer domain
- // For now display name is device URI directly, could extrapolated using more heuristics or even usins GStreamer API later on
- pEndpointInfo->deviceURIType = DEVICEURITYPE_NOT_ALSA;
- }
- else if (IsExternalDomain(pEndpointInfo->gsDeviceDomain)){
- // External domain
- pEndpointInfo->deviceURIType = DEVICEURITYPE_NOT_ALSA;
- }
- else {
- // Unknown domain
- AFB_WARNING("Unknown domain in device URI string -> %s",pFullDeviceURI);
- continue;
- }
-
- pEndpointInfo->endpointID = in_deviceType == ENDPOINTTYPE_SOURCE ? CreateNewSourceID() : CreateNewSinkID();
- pEndpointInfo->type = in_deviceType;
- // Assigned by policy initialization
- pEndpointInfo->gsDisplayName = malloc(AHL_STR_MAX_LENGTH*sizeof(char));
- memset(pEndpointInfo->gsDisplayName,0,AHL_STR_MAX_LENGTH*sizeof(char));
- pEndpointInfo->gsHALAPIName = malloc(AHL_STR_MAX_LENGTH*sizeof(char));
- memset(pEndpointInfo->gsDisplayName,0,AHL_STR_MAX_LENGTH*sizeof(char));
-
- // add to structure to list of available devices
- g_ptr_array_add(out_pEndpointArray, pEndpointInfo);
-
- } // for all devices
-
- AFB_DEBUG ("Audio high-level - Enumerate devices done");
- return 0;
-} \ No newline at end of file