[WASAPI] set stream audio category
[xbmc.git] / xbmc / cores / AudioEngine / Sinks / alsa / ALSADeviceMonitor.cpp
blob2d2bd788c6756d1adcea6472ec3589834d136e8b
1 /*
2 * Copyright (C) 2014-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "ALSADeviceMonitor.h"
11 #include "ServiceBroker.h"
12 #include "cores/AudioEngine/Engines/ActiveAE/ActiveAE.h"
13 #include "utils/log.h"
15 #include "platform/linux/FDEventMonitor.h"
17 #include <libudev.h>
19 CALSADeviceMonitor::CALSADeviceMonitor() :
20 m_udev(NULL),
21 m_udevMonitor(NULL)
25 CALSADeviceMonitor::~CALSADeviceMonitor()
27 Stop();
30 void CALSADeviceMonitor::Start()
32 int err;
34 if (!m_udev)
36 m_udev = udev_new();
37 if (!m_udev)
39 CLog::Log(LOGWARNING, "CALSADeviceMonitor::Start - Unable to open udev handle");
40 return;
43 m_udevMonitor = udev_monitor_new_from_netlink(m_udev, "udev");
44 if (!m_udevMonitor)
46 CLog::Log(LOGERROR, "CALSADeviceMonitor::Start - udev_monitor_new_from_netlink() failed");
47 goto err_unref_udev;
50 err = udev_monitor_filter_add_match_subsystem_devtype(m_udevMonitor, "sound", NULL);
51 if (err)
53 CLog::Log(LOGERROR, "CALSADeviceMonitor::Start - udev_monitor_filter_add_match_subsystem_devtype() failed");
54 goto err_unref_monitor;
57 err = udev_monitor_enable_receiving(m_udevMonitor);
58 if (err)
60 CLog::Log(LOGERROR, "CALSADeviceMonitor::Start - udev_monitor_enable_receiving() failed");
61 goto err_unref_monitor;
64 const auto eventMonitor = CServiceBroker::GetPlatform().GetService<CFDEventMonitor>();
65 eventMonitor->AddFD(CFDEventMonitor::MonitoredFD(udev_monitor_get_fd(m_udevMonitor), POLLIN,
66 FDEventCallback, m_udevMonitor),
67 m_fdMonitorId);
70 return;
72 err_unref_monitor:
73 udev_monitor_unref(m_udevMonitor);
74 m_udevMonitor = NULL;
75 err_unref_udev:
76 udev_unref(m_udev);
77 m_udev = NULL;
80 void CALSADeviceMonitor::Stop()
82 if (m_udev)
84 const auto eventMonitor = CServiceBroker::GetPlatform().GetService<CFDEventMonitor>();
85 eventMonitor->RemoveFD(m_fdMonitorId);
87 udev_monitor_unref(m_udevMonitor);
88 m_udevMonitor = NULL;
89 udev_unref(m_udev);
90 m_udev = NULL;
94 void CALSADeviceMonitor::FDEventCallback(int id, int fd, short revents, void *data)
96 struct udev_monitor *udevMonitor = (struct udev_monitor *)data;
97 bool audioDevicesChanged = false;
98 struct udev_device *device;
100 while ((device = udev_monitor_receive_device(udevMonitor)) != NULL)
102 const char* action = udev_device_get_action(device);
103 const char* soundInitialized = udev_device_get_property_value(device, "SOUND_INITIALIZED");
105 if (!action || !soundInitialized)
106 continue;
108 /* cardX devices emit a "change" event when ready (i.e. all subdevices added) */
109 if (strcmp(action, "change") == 0)
111 CLog::Log(LOGDEBUG, "CALSADeviceMonitor - ALSA card added (\"{}\", \"{}\")",
112 udev_device_get_syspath(device), udev_device_get_devpath(device));
113 audioDevicesChanged = true;
115 else if (strcmp(action, "remove") == 0)
117 CLog::Log(LOGDEBUG, "CALSADeviceMonitor - ALSA card removed");
118 audioDevicesChanged = true;
121 udev_device_unref(device);
124 if (audioDevicesChanged)
126 CServiceBroker::GetActiveAE()->DeviceChange();