2020#include " osn-error.hpp"
2121#include " nodeobs_api.h"
2222#include " shared.hpp"
23+ #include < sstream>
2324#include " memory-manager.h"
2425#include " osn-video.hpp"
2526#include " osn-encoders.hpp"
@@ -3864,46 +3865,87 @@ void OBS_settings::saveGenericSettings(std::vector<SubCategory> genericSettings,
38643865 config_save_safe (config, " tmp" , nullptr );
38653866}
38663867
3867- void getDevices (const char *source_id, const char *property_name, std::vector<ipc::value> &rval)
3868+ // Gets the devices using a "dummy" source object that does not exist. For most
3869+ // plugins this is fine but should be avoided for plugins like mac-coreaudio
3870+ // because it will create a reconnect_thread. Triggers the following callbacks
3871+ // on the obs_source_info: get_properties, get_defaults, and get_updates.
3872+ void getDevicesUsingDummySource (const char *source_id, const char *property_name, std::vector<ipc::value> &rval)
38683873{
3869- auto settings = obs_get_source_defaults (source_id);
3870- if (!settings)
3871- return ;
3874+ OBSDataAutoRelease settings = obs_get_source_defaults (source_id);
3875+ if (!settings) {
3876+ std::ostringstream ss;
3877+ ss << " Could not get settings for source id: " << source_id;
3878+ PRETTY_ERROR_RETURN (ErrorCode::Error, ss.str ());
3879+ }
38723880
38733881 const char *dummy_device_name = " does_not_exist" ;
38743882 obs_data_set_string (settings, property_name, dummy_device_name);
3875- if (strcmp (source_id, " dshow_input" ) == 0 ) {
3876- obs_data_set_string (settings, " video_device_id" , dummy_device_name);
3877- obs_data_set_string (settings, " audio_device_id" , dummy_device_name);
3878- }
38793883
38803884 // Create a dummy source so that the "device" property can be init
3881- auto dummy_source = obs_source_create (source_id, dummy_device_name, settings, nullptr );
3885+ OBSSourceAutoRelease dummy_source = obs_source_create (source_id, dummy_device_name, settings, nullptr );
38823886 if (!dummy_source) {
3883- obs_data_release (settings);
3884- return ;
3887+ std::ostringstream ss;
3888+ ss << " Could not create source: " << source_id;
3889+ PRETTY_ERROR_RETURN (ErrorCode::Error, ss.str ());
38853890 }
38863891
38873892 auto props = obs_source_properties (dummy_source);
38883893 if (!props) {
3889- obs_source_release (dummy_source) ;
3890- obs_data_release (settings) ;
3891- return ;
3894+ std::ostringstream ss ;
3895+ ss << " Could not get source properties for source id: " << source_id ;
3896+ PRETTY_ERROR_RETURN (ErrorCode::Error, ss. str ()) ;
38923897 }
38933898
38943899 auto prop = obs_properties_get (props, property_name);
38953900 if (!prop) {
38963901 obs_properties_destroy (props);
3897- obs_source_release (dummy_source) ;
3898- obs_data_release (settings) ;
3899- return ;
3902+ std::ostringstream ss ;
3903+ ss << " Could not get source property " << property_name << " for source id: " << source_id ;
3904+ PRETTY_ERROR_RETURN (ErrorCode::Error, ss. str ()) ;
39003905 }
39013906
3907+ rval.push_back (ipc::value ((uint64_t )ErrorCode::Ok));
39023908 size_t items = obs_property_list_item_count (prop);
3903- if (rval.size () > 1 )
3904- rval[1 ].value_union .ui64 += items;
3905- else
3906- rval.push_back (ipc::value ((uint64_t )items));
3909+ rval.push_back (ipc::value ((uint64_t )items));
3910+
3911+ for (size_t idx = 0 ; idx < items; idx++) {
3912+ const char *description = obs_property_list_item_name (prop, idx);
3913+ const char *device_id = obs_property_list_item_string (prop, idx);
3914+
3915+ if (!description || !strcmp (description, " " ) || !device_id || !strcmp (device_id, " " )) {
3916+ rval[1 ].value_union .ui64 --;
3917+ continue ;
3918+ }
3919+
3920+ rval.push_back (ipc::value (description));
3921+ rval.push_back (ipc::value (device_id));
3922+ }
3923+
3924+ obs_properties_destroy (props);
3925+ }
3926+
3927+ // Gets the devices from the source using a property list without triggering
3928+ // obs_source_info.get_updates callback.
3929+ void getDevices (const char *source_id, const char *property_name, std::vector<ipc::value> &rval)
3930+ {
3931+ auto props = obs_get_source_properties (source_id);
3932+ if (!props) {
3933+ std::ostringstream ss;
3934+ ss << " Could not get source properties for source id: " << source_id;
3935+ PRETTY_ERROR_RETURN (ErrorCode::Error, ss.str ());
3936+ }
3937+
3938+ auto prop = obs_properties_get (props, property_name);
3939+ if (!prop) {
3940+ obs_properties_destroy (props);
3941+ std::ostringstream ss;
3942+ ss << " Could not get source property " << property_name << " for source id: " << source_id;
3943+ PRETTY_ERROR_RETURN (ErrorCode::Error, ss.str ());
3944+ }
3945+
3946+ rval.push_back (ipc::value ((uint64_t )ErrorCode::Ok));
3947+ size_t items = obs_property_list_item_count (prop);
3948+ rval.push_back (ipc::value ((uint64_t )items));
39073949
39083950 for (size_t idx = 0 ; idx < items; idx++) {
39093951 const char *description = obs_property_list_item_name (prop, idx);
@@ -3919,8 +3961,6 @@ void getDevices(const char *source_id, const char *property_name, std::vector<ip
39193961 }
39203962
39213963 obs_properties_destroy (props);
3922- obs_data_release (settings);
3923- obs_source_release (dummy_source);
39243964}
39253965
39263966#ifdef WIN32
@@ -4057,9 +4097,8 @@ void enumAudioDevices(std::vector<ipc::value> &rval, EDataFlow dataFlow)
40574097
40584098void OBS_settings::OBS_settings_getInputAudioDevices (void *data, const int64_t id, const std::vector<ipc::value> &args, std::vector<ipc::value> &rval)
40594099{
4060- rval.push_back (ipc::value ((uint64_t )ErrorCode::Ok));
4061-
40624100#ifdef WIN32
4101+ rval.push_back (ipc::value ((uint64_t )ErrorCode::Ok));
40634102 rval.push_back (ipc::value ((uint32_t )1 ));
40644103 rval.push_back (ipc::value (" Default" ));
40654104 rval.push_back (ipc::value (" default" ));
@@ -4074,9 +4113,8 @@ void OBS_settings::OBS_settings_getInputAudioDevices(void *data, const int64_t i
40744113
40754114void OBS_settings::OBS_settings_getOutputAudioDevices (void *data, const int64_t id, const std::vector<ipc::value> &args, std::vector<ipc::value> &rval)
40764115{
4077- rval.push_back (ipc::value ((uint64_t )ErrorCode::Ok));
4078-
40794116#ifdef WIN32
4117+ rval.push_back (ipc::value ((uint64_t )ErrorCode::Ok));
40804118 rval.push_back (ipc::value ((uint32_t )1 ));
40814119 rval.push_back (ipc::value (" Default" ));
40824120 rval.push_back (ipc::value (" default" ));
@@ -4091,15 +4129,12 @@ void OBS_settings::OBS_settings_getOutputAudioDevices(void *data, const int64_t
40914129
40924130void OBS_settings::OBS_settings_getVideoDevices (void *data, const int64_t id, const std::vector<ipc::value> &args, std::vector<ipc::value> &rval)
40934131{
4094- rval.push_back (ipc::value ((uint64_t )ErrorCode::Ok));
4095-
40964132#ifdef WIN32
4133+ rval.push_back (ipc::value ((uint64_t )ErrorCode::Ok));
40974134 rval.push_back (ipc::value ((uint32_t )0 ));
40984135 enumVideoDevices (rval);
40994136#elif __APPLE__
4100- const char *source_id = " macos_avcapture" ;
4101- const char *property_name = " device" ;
4102- getDevices (source_id, property_name, rval);
4137+ getDevicesUsingDummySource (" macos_avcapture" , " device" , rval);
41034138#endif
41044139
41054140 AUTO_DEBUG ;
0 commit comments