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.
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"
19 CALSADeviceMonitor::CALSADeviceMonitor() :
25 CALSADeviceMonitor::~CALSADeviceMonitor()
30 void CALSADeviceMonitor::Start()
39 CLog::Log(LOGWARNING
, "CALSADeviceMonitor::Start - Unable to open udev handle");
43 m_udevMonitor
= udev_monitor_new_from_netlink(m_udev
, "udev");
46 CLog::Log(LOGERROR
, "CALSADeviceMonitor::Start - udev_monitor_new_from_netlink() failed");
50 err
= udev_monitor_filter_add_match_subsystem_devtype(m_udevMonitor
, "sound", NULL
);
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
);
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
),
73 udev_monitor_unref(m_udevMonitor
);
80 void CALSADeviceMonitor::Stop()
84 const auto eventMonitor
= CServiceBroker::GetPlatform().GetService
<CFDEventMonitor
>();
85 eventMonitor
->RemoveFD(m_fdMonitorId
);
87 udev_monitor_unref(m_udevMonitor
);
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
)
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();