diff --git a/DeviceSource.cpp b/DeviceSource.cpp index 017fc03..13b25ec 100644 --- a/DeviceSource.cpp +++ b/DeviceSource.cpp @@ -150,6 +150,9 @@ void Device::add(GstDevice *device) if (device==nullptr) return; + // lock before change + access_.lock(); + gchar *device_name = gst_device_get_display_name (device); if ( std::find(manager().src_name_.begin(), manager().src_name_.end(), device_name) == manager().src_name_.end()) { @@ -171,6 +174,9 @@ void Device::add(GstDevice *device) list_uptodate_ = false; } g_free (device_name); + + // unlock access + access_.unlock(); } void Device::remove(GstDevice *device) @@ -178,6 +184,9 @@ void Device::remove(GstDevice *device) if (device==nullptr) return; + // lock before change + access_.lock(); + gchar *device_name = gst_device_get_display_name (device); std::vector< std::string >::iterator nameit = src_name_.begin(); @@ -204,47 +213,42 @@ void Device::remove(GstDevice *device) ++coit; } g_free (device_name); + + // unlock access + access_.unlock(); } Device::Device(): list_uptodate_(false) { - + std::thread(launchMonitoring, this).detach(); } -void Device::init() +void Device::launchMonitoring(Device *d) { - GstBus *bus; - GstCaps *caps; + d->monitor_ = gst_device_monitor_new (); - // create GStreamer device monitor to capture - // when a device is plugged in or out - monitor_ = gst_device_monitor_new (); - - bus = gst_device_monitor_get_bus (monitor_); - gst_bus_add_watch (bus, callback_device_monitor, NULL); - gst_object_unref (bus); - - caps = gst_caps_new_empty_simple ("video/x-raw"); - gst_device_monitor_add_filter (monitor_, "Video/Source", caps); + GstCaps *caps = gst_caps_new_empty_simple ("video/x-raw"); + gst_device_monitor_add_filter (d->monitor_, "Video/Source", caps); gst_caps_unref (caps); - gst_device_monitor_set_show_all_devices(monitor_, true); - gst_device_monitor_start (monitor_); + gst_device_monitor_set_show_all_devices(d->monitor_, true); + gst_device_monitor_start (d->monitor_); - // initial fill of the list - GList *devices = gst_device_monitor_get_devices(monitor_); + // Add configs for plugged devices + GList *devices = gst_device_monitor_get_devices(d->monitor_); GList *tmp; for (tmp = devices; tmp ; tmp = tmp->next ) { GstDevice *device = (GstDevice *) tmp->data; - add(device); + d->add(device); gst_object_unref (device); } g_list_free(devices); // Add config for plugged screen - src_name_.push_back("Screen capture"); - src_description_.push_back(gst_plugin_vidcap); + d->access_.lock(); + d->src_name_.push_back("Screen capture"); + d->src_description_.push_back(gst_plugin_vidcap); // Try to auto find resolution DeviceConfigSet confs = getDeviceConfigs(gst_plugin_vidcap); @@ -254,25 +258,48 @@ void Device::init() DeviceConfigSet confscreen; best.fps_numerator = 15; confscreen.insert(best); - src_config_.push_back(confscreen); + d->src_config_.push_back(confscreen); } + d->access_.unlock(); - // TODO Use lib glfw to get monitors - // TODO Detect auto removal of monitors + d->list_uptodate_ = true; + + // create a local g_main_context for this threaded monitor + GMainContext *_gcontext_device = g_main_context_new(); + if (g_main_context_acquire(_gcontext_device)) + g_printerr("Starting Device monitoring... \n"); + + // temporarily push as default the default g_main_context for add_watch + g_main_context_push_thread_default(_gcontext_device); + + GstBus *bus = gst_device_monitor_get_bus (d->monitor_); + gst_bus_add_watch (bus, callback_device_monitor, NULL); + gst_object_unref (bus); + + g_main_context_pop_thread_default(_gcontext_device); + + // start main loop for this context (blocking infinitely) + g_main_loop_run( g_main_loop_new (_gcontext_device, true) ); - list_uptodate_ = true; } - -int Device::numDevices() const +int Device::numDevices() { - return src_name_.size(); + access_.lock(); + int ret = src_name_.size(); + access_.unlock(); + + return ret; } -bool Device::exists(const std::string &device) const +bool Device::exists(const std::string &device) { + access_.lock(); std::vector< std::string >::const_iterator d = std::find(src_name_.begin(), src_name_.end(), device); - return d != src_name_.end(); + bool ret = (d != src_name_.end()); + access_.unlock(); + + return ret; } struct hasDevice: public std::unary_function @@ -307,43 +334,57 @@ Source *Device::createSource(const std::string &device) const return s; } -bool Device::unplugged(const std::string &device) const +bool Device::unplugged(const std::string &device) { if (list_uptodate_) return false; return !exists(device); } -std::string Device::name(int index) const +std::string Device::name(int index) { + std::string ret = ""; + + access_.lock(); if (index > -1 && index < (int) src_name_.size()) - return src_name_[index]; - else - return ""; + ret = src_name_[index]; + access_.unlock(); + + return ret; } -std::string Device::description(int index) const +std::string Device::description(int index) { + std::string ret = ""; + + access_.lock(); if (index > -1 && index < (int) src_description_.size()) - return src_description_[index]; - else - return ""; + ret = src_description_[index]; + access_.unlock(); + + return ret; } -DeviceConfigSet Device::config(int index) const +DeviceConfigSet Device::config(int index) { + DeviceConfigSet ret; + + access_.lock(); if (index > -1 && index < (int) src_config_.size()) - return src_config_[index]; - else - return DeviceConfigSet(); + ret = src_config_[index]; + access_.unlock(); + + return ret; } -int Device::index(const std::string &device) const +int Device::index(const std::string &device) { int i = -1; - std::vector< std::string >::const_iterator p = std::find(src_name_.begin(), src_name_.end(), device); + access_.lock(); + std::vector< std::string >::iterator p = std::find(src_name_.begin(), src_name_.end(), device); if (p != src_name_.end()) i = std::distance(src_name_.begin(), p); + access_.unlock(); return i; } diff --git a/DeviceSource.h b/DeviceSource.h index d041bd3..d322e39 100644 --- a/DeviceSource.h +++ b/DeviceSource.h @@ -100,15 +100,14 @@ public: return _instance; } - void init(); - int numDevices () const; - std::string name (int index) const; - std::string description (int index) const; - DeviceConfigSet config (int index) const; + int numDevices () ; + std::string name (int index) ; + std::string description (int index) ; + DeviceConfigSet config (int index) ; - int index (const std::string &device) const; - bool exists (const std::string &device) const; - bool unplugged (const std::string &device) const; + int index (const std::string &device); + bool exists (const std::string &device) ; + bool unplugged (const std::string &device) ; Source *createSource(const std::string &device) const; @@ -117,9 +116,11 @@ public: private: + static void launchMonitoring(Device *d); void remove(GstDevice *device); void add(GstDevice *device); + std::mutex access_; std::vector< std::string > src_name_; std::vector< std::string > src_description_; std::vector< DeviceConfigSet > src_config_; diff --git a/DialogToolkit.cpp b/DialogToolkit.cpp index c1a6667..7349efb 100644 --- a/DialogToolkit.cpp +++ b/DialogToolkit.cpp @@ -254,9 +254,10 @@ std::string saveSessionFileDialog(const std::string &label, const std::string &p if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT ) { char *save_file_name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) ); - if (save_file_name) + if (save_file_name) { filename = std::string(save_file_name); - g_free( save_file_name ); + g_free( save_file_name ); + } } // remember position @@ -314,9 +315,10 @@ std::string openSessionFileDialog(const std::string &label, const std::string &p if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT ) { char *open_file_name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) ); - if (open_file_name) + if (open_file_name) { filename = std::string(open_file_name); - g_free( open_file_name ); + g_free( open_file_name ); + } } // remember position @@ -371,9 +373,10 @@ std::string openMediaFileDialog(const std::string &label, const std::string &pat if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT ) { char *open_file_name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) ); - if (open_file_name) + if (open_file_name) { filename = std::string(open_file_name); - g_free( open_file_name ); + g_free( open_file_name ); + } } // remember position @@ -428,9 +431,10 @@ std::string openImageFileDialog(const std::string &label, const std::string &pat if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT ) { char *open_file_name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) ); - if (open_file_name) + if (open_file_name) { filename = std::string(open_file_name); - g_free( open_file_name ); + g_free( open_file_name ); + } } // remember position @@ -480,9 +484,10 @@ std::string openFolderDialog(const std::string &label, const std::string &path) if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT ) { char *open_folder_name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) ); - if (open_folder_name) + if (open_folder_name) { foldername = std::string(open_folder_name); - g_free( open_folder_name ); + g_free( open_folder_name ); + } } // remember position diff --git a/MediaPlayer.cpp b/MediaPlayer.cpp index 828e934..1ea2c65 100644 --- a/MediaPlayer.cpp +++ b/MediaPlayer.cpp @@ -374,7 +374,6 @@ void MediaPlayer::execute_open() gst_app_sink_set_max_buffers( GST_APP_SINK(sink), 5); gst_app_sink_set_drop (GST_APP_SINK(sink), true); -#ifdef USE_GST_APPSINK_CALLBACKS // set the callbacks GstAppSinkCallbacks callbacks; callbacks.new_preroll = callback_new_preroll; @@ -388,15 +387,6 @@ void MediaPlayer::execute_open() } gst_app_sink_set_callbacks (GST_APP_SINK(sink), &callbacks, this, NULL); gst_app_sink_set_emit_signals (GST_APP_SINK(sink), false); -#else - // connect signals callbacks - g_signal_connect(G_OBJECT(sink), "new-preroll", G_CALLBACK (callback_new_preroll), this); - if (!media_.isimage) { - g_signal_connect(G_OBJECT(sink), "new-sample", G_CALLBACK (callback_new_sample), this); - g_signal_connect(G_OBJECT(sink), "eos", G_CALLBACK (callback_end_of_stream), this); - } - gst_app_sink_set_emit_signals (GST_APP_SINK(sink), true); -#endif // done with ref to sink gst_object_unref (sink); diff --git a/RenderingManager.cpp b/RenderingManager.cpp index 70bbb6d..5e58839 100644 --- a/RenderingManager.cpp +++ b/RenderingManager.cpp @@ -368,9 +368,6 @@ void Rendering::draw() // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); - // no g_main_loop_run(loop) : update global GMainContext - g_main_context_iteration(NULL, FALSE); - } void Rendering::terminate() diff --git a/Stream.cpp b/Stream.cpp index f089b0c..b456a83 100644 --- a/Stream.cpp +++ b/Stream.cpp @@ -241,7 +241,6 @@ void Stream::execute_open() gst_app_sink_set_max_buffers( GST_APP_SINK(sink), 30); gst_app_sink_set_drop (GST_APP_SINK(sink), true); -#ifdef USE_GST_APPSINK_CALLBACKS // set the callbacks GstAppSinkCallbacks callbacks; callbacks.new_preroll = callback_new_preroll; @@ -256,15 +255,6 @@ void Stream::execute_open() } gst_app_sink_set_callbacks (GST_APP_SINK(sink), &callbacks, this, NULL); gst_app_sink_set_emit_signals (GST_APP_SINK(sink), false); -#else - // connect signals callbacks - g_signal_connect(G_OBJECT(sink), "new-preroll", G_CALLBACK (callback_new_preroll), this); - if (!single_frame_) { - g_signal_connect(G_OBJECT(sink), "new-sample", G_CALLBACK (callback_new_sample), this); - g_signal_connect(G_OBJECT(sink), "eos", G_CALLBACK (callback_end_of_stream), this); - } - gst_app_sink_set_emit_signals (GST_APP_SINK(sink), true); -#endif // set to desired state (PLAY or PAUSE) live_ = false; diff --git a/defines.h b/defines.h index 244f3eb..d075b9b 100644 --- a/defines.h +++ b/defines.h @@ -104,8 +104,6 @@ #define COLOR_SLIDER_CIRCLE 0.11f, 0.11f, 0.11f #define COLOR_STASH_CIRCLE 0.06f, 0.06f, 0.06f -#define USE_GST_APPSINK_CALLBACKS - #define OSC_PORT_RECV_DEFAULT 7000 #define OSC_PORT_SEND_DEFAULT 7001 #define OSC_CONFIG_FILE "osc.xml" diff --git a/main.cpp b/main.cpp index 1e8022c..9951f7f 100644 --- a/main.cpp +++ b/main.cpp @@ -30,7 +30,6 @@ #include "ControlManager.h" #include "Connection.h" #include "Metronome.h" -#include "DeviceSource.h" #if defined(APPLE) extern "C"{ @@ -105,29 +104,24 @@ int main(int argc, char *argv[]) return 1; /// - /// CONTROLLER INIT + /// CONTROLLER INIT (OSC) /// Control::manager().init(); /// - /// METRONOME INIT + /// METRONOME INIT (Ableton Link) /// if ( !Metronome::manager().init() ) return 1; /// - /// RENDERING INIT + /// RENDERING & GST INIT /// if ( !Rendering::manager().init() ) return 1; /// - /// DEVICES INIT - /// - Device::manager().init(); - - /// - /// UI INIT + /// IMGUI INIT /// if ( !UserInterface::manager().Init() ) return 1;