@@ -68,6 +68,12 @@ static std::optional<uint32_t> getPortIndexFromName(const char* name) {
6868
6969PipewireEnumerator::PipewireEnumerator (UserSettingsPointer, SoundManager* pManager)
7070 : m_pSoundManager(pManager),
71+ m_pPwThreadLoop(nullptr ),
72+ m_pPwContext(nullptr ),
73+ m_pPwCore(nullptr ),
74+ m_pPwRegistry(nullptr ),
75+ m_pPwMetadata(nullptr ),
76+ m_pPwFilter(nullptr ),
7177 m_soundDevices(std::make_shared<SoundDeviceMap>()),
7278 m_openedDevices(std::make_shared<DeviceMap>()),
7379 m_initialized(false ),
@@ -77,34 +83,72 @@ PipewireEnumerator::PipewireEnumerator(UserSettingsPointer, SoundManager* pManag
7783
7884 pw_init (nullptr , nullptr );
7985
80- m_pThreadLoop = pw_thread_loop_new (" mixxx_loop" , nullptr );
81- m_pContext = pw_context_new (pw_thread_loop_get_loop (m_pThreadLoop), nullptr , 0 );
86+ m_pPwThreadLoop = pw_thread_loop_new (" mixxx_loop" , nullptr );
87+ spa_zero (m_pwRegistryListener);
88+ spa_zero (m_pwMetadataListener);
89+ spa_zero (m_pwFilterListener);
8290}
8391
8492PipewireEnumerator::~PipewireEnumerator () {
85- pw_thread_loop_stop (m_pThreadLoop);
86- spa_hook_remove (&m_registryListener);
87- spa_hook_remove (&m_metadataListener);
88- pw_proxy_destroy ((struct pw_proxy *)m_pRegistry);
89- pw_proxy_destroy ((struct pw_proxy *)m_pMetadata);
90- pw_core_disconnect (m_pCore);
91- pw_context_destroy (m_pContext);
92- pw_thread_loop_destroy (m_pThreadLoop);
93+ pw_thread_loop_stop (m_pPwThreadLoop);
94+
95+ if (m_pPwFilter) {
96+ pw_filter_destroy (m_pPwFilter);
97+ }
98+
99+ if (m_pPwMetadata) {
100+ spa_hook_remove (&m_pwMetadataListener);
101+ pw_proxy_destroy ((struct pw_proxy *)m_pPwMetadata);
102+ }
103+
104+ if (m_pPwRegistry) {
105+ spa_hook_remove (&m_pwRegistryListener);
106+ pw_proxy_destroy ((struct pw_proxy *)m_pPwRegistry);
107+ }
108+
109+ if (m_pPwCore) {
110+ pw_core_disconnect (m_pPwCore);
111+ }
112+
113+ if (m_pPwContext) {
114+ pw_context_destroy (m_pPwContext);
115+ }
116+
117+ pw_thread_loop_destroy (m_pPwThreadLoop);
93118 pw_deinit ();
94119}
95120
96121void PipewireEnumerator::initialize () {
97- m_pCore = pw_context_connect (m_pContext, nullptr , 0 );
122+ if (m_initialized) {
123+ qWarning () << " PipewireEnumerator::initialize already initialized" ;
124+ return ;
125+ }
98126
99- if (!m_pCore) {
127+ if (!m_pPwContext) {
128+ m_pPwContext = pw_context_new (pw_thread_loop_get_loop (m_pPwThreadLoop), nullptr , 0 );
129+ if (!m_pPwContext) {
130+ qWarning () << " PipewireEnumerator::initialize pw_context_new "
131+ " failed with error:"
132+ << spa_strerror (errno);
133+ return ;
134+ }
135+ }
136+
137+ m_pPwCore = pw_context_connect (m_pPwContext, nullptr , 0 );
138+
139+ if (!m_pPwCore) {
140+ qWarning () << " PipewireEnumerator::initialize pw_context_connect "
141+ " failed with error:"
142+ << spa_strerror (errno);
100143 return ;
101144 }
102145
103- m_pRegistry = pw_core_get_registry (m_pCore, PW_VERSION_REGISTRY , 0 );
146+ m_pPwRegistry = pw_core_get_registry (m_pPwCore, PW_VERSION_REGISTRY , 0 );
147+ pw_registry_add_listener (m_pPwRegistry, &m_pwRegistryListener, ®istry_events, this );
104148
105149 // see https://docs.pipewire.org/page_man_pipewire-props_7.html
106150 // and pipewire/keys.h header
107- m_pFilter = pw_filter_new (m_pCore ,
151+ m_pPwFilter = pw_filter_new (m_pPwCore ,
108152 " mixxx" ,
109153 pw_properties_new (PW_KEY_MEDIA_NAME ,
110154 " Mixxx" ,
@@ -122,14 +166,9 @@ void PipewireEnumerator::initialize() {
122166 " Mixxx" ,
123167 nullptr ));
124168
125- spa_zero (m_registryListener);
126- spa_zero (m_metadataListener);
127- spa_zero (m_filterListener);
128-
129- pw_registry_add_listener (m_pRegistry, &m_registryListener, ®istry_events, this );
130- pw_filter_add_listener (m_pFilter, &m_filterListener, &filter_events, this );
169+ pw_filter_add_listener (m_pPwFilter, &m_pwFilterListener, &filter_events, this );
131170
132- int res = pw_filter_connect (m_pFilter ,
171+ int res = pw_filter_connect (m_pPwFilter ,
133172 PW_FILTER_FLAG_RT_PROCESS ,
134173 nullptr ,
135174 0 );
@@ -138,7 +177,7 @@ void PipewireEnumerator::initialize() {
138177 qWarning () << " pw_filter_connect error:" << spa_strerror (res);
139178 }
140179
141- pw_thread_loop_start (m_pThreadLoop );
180+ pw_thread_loop_start (m_pPwThreadLoop );
142181
143182 m_initialized = true ;
144183}
@@ -158,13 +197,13 @@ void PipewireEnumerator::registryEventGlobal(uint32_t id,
158197 return ;
159198 }
160199
161- void * data = pw_registry_bind (m_pRegistry ,
200+ void * data = pw_registry_bind (m_pPwRegistry ,
162201 id,
163202 PW_TYPE_INTERFACE_Metadata,
164203 PW_VERSION_METADATA ,
165204 0 );
166- m_pMetadata = static_cast <pw_metadata*>(data);
167- pw_metadata_add_listener (m_pMetadata , &m_metadataListener , &metadataEvents, this );
205+ m_pPwMetadata = static_cast <pw_metadata*>(data);
206+ pw_metadata_add_listener (m_pPwMetadata , &m_pwMetadataListener , &metadataEvents, this );
168207 } else if (strcmp (pType, PW_TYPE_INTERFACE_Node) == 0 ) {
169208 const char * media_class = spa_dict_lookup (pProps, PW_KEY_MEDIA_CLASS );
170209 const char * media_type = spa_dict_lookup (pProps, PW_KEY_MEDIA_TYPE );
@@ -346,7 +385,7 @@ void PipewireEnumerator::openDevice(uint32_t id,
346385 return ;
347386 }
348387
349- pw_thread_loop_lock (m_pThreadLoop );
388+ pw_thread_loop_lock (m_pPwThreadLoop );
350389
351390 if (rate != m_sampleRate.value () || framesPerBuffer != m_framesPerBuffer) {
352391 std::string rateStr = " 1/" + std::to_string (rate);
@@ -358,7 +397,7 @@ void PipewireEnumerator::openDevice(uint32_t id,
358397 };
359398 spa_dict properties = SPA_DICT_INIT (items, 2 );
360399
361- int res = pw_filter_update_properties (m_pFilter , nullptr , &properties);
400+ int res = pw_filter_update_properties (m_pPwFilter , nullptr , &properties);
362401 if (res >= 0 ) {
363402 m_sampleRate = mixxx::audio::SampleRate (rate);
364403 m_framesPerBuffer = framesPerBuffer;
@@ -387,7 +426,7 @@ void PipewireEnumerator::openDevice(uint32_t id,
387426 " 32 bit float mono audio" ,
388427 nullptr );
389428 pw_properties_setf (props, PW_KEY_PORT_NAME , " in:%zu" , filterPortIndex);
390- void * port_data = pw_filter_add_port (m_pFilter ,
429+ void * port_data = pw_filter_add_port (m_ppwFilter ,
391430 SPA_DIRECTION_INPUT ,
392431 PW_FILTER_PORT_FLAG_MAP_BUFFERS ,
393432 0 ,
@@ -404,7 +443,7 @@ void PipewireEnumerator::openDevice(uint32_t id,
404443 pw_properties* props = pw_properties_new (
405444 PW_KEY_FORMAT_DSP , " 32 bit float mono audio" , nullptr );
406445 pw_properties_setf (props, PW_KEY_PORT_NAME , " out:%zu" , filterPortIndex);
407- void * port_data = pw_filter_add_port (m_pFilter ,
446+ void * port_data = pw_filter_add_port (m_ppwFilter ,
408447 SPA_DIRECTION_OUTPUT ,
409448 PW_FILTER_PORT_FLAG_MAP_BUFFERS ,
410449 0 ,
@@ -413,7 +452,7 @@ void PipewireEnumerator::openDevice(uint32_t id,
413452 0 );
414453 outputs.emplace_back (port_data, i, filterPortIndex);
415454 }
416- pw_thread_loop_unlock (m_pThreadLoop );
455+ pw_thread_loop_unlock (m_pPwThreadLoop );
417456
418457 pOpenedDevices->emplace (id, Device{std::move (inputs), std::move (outputs)});
419458 m_openedDevices.store (pOpenedDevices);
@@ -434,15 +473,15 @@ void PipewireEnumerator::closeDevice(uint32_t id) {
434473
435474 auto & device = pOpenedDevices->at (id);
436475
437- pw_thread_loop_lock (m_pThreadLoop );
476+ pw_thread_loop_lock (m_pPwThreadLoop );
438477 for (auto & port : device.inputs ) {
439478 pw_filter_remove_port (port.pPortData );
440479 }
441480
442481 for (auto & port : device.outputs ) {
443482 pw_filter_remove_port (port.pPortData );
444483 }
445- pw_thread_loop_unlock (m_pThreadLoop );
484+ pw_thread_loop_unlock (m_pPwThreadLoop );
446485
447486 pOpenedDevices->erase (id);
448487 m_openedDevices.store (pOpenedDevices);
@@ -533,7 +572,7 @@ void PipewireEnumerator::createLink(uint32_t outNodeId,
533572 items[props.n_items ++] = SPA_DICT_ITEM_INIT (PW_KEY_LINK_INPUT_PORT , strInPort.c_str ());
534573 items[props.n_items ++] = SPA_DICT_ITEM_INIT (PW_KEY_OBJECT_LINGER , " true" );
535574
536- struct pw_proxy * pProxy = static_cast <pw_proxy*>(pw_core_create_object (m_pCore ,
575+ struct pw_proxy * pProxy = static_cast <pw_proxy*>(pw_core_create_object (m_pPwCore ,
537576 " link-factory" ,
538577 PW_TYPE_INTERFACE_Link,
539578 PW_VERSION_LINK ,
0 commit comments