bool Timelapse::on_shmdata_disconnect(const std::string& shmpath) { std::unique_lock<std::mutex> lock(timelapse_mtx_); pmanage<MPtr(&PContainer::enable)>(img_name_id_); if (!stop_timelapse(shmpath)) return false; if (timelapse_.size() == 1) pmanage<MPtr(&PContainer::enable)>(img_name_id_); return true; }
GstBusSyncReply AVPlayer::bus_async(GstMessage* msg) { switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: { th_->run_async([this]() { pmanage<MPtr(&PContainer::set_str_str)>("started", "false"); }); break; } case GST_MESSAGE_STATE_CHANGED: { if (position_id_ == 0) { gst_element_query_duration( gst_pipeline_->get_pipeline(), GST_FORMAT_TIME, &track_duration_); if (track_duration_ != 0) { position_id_ = pmanage<MPtr(&PContainer::make_int)>("track_position", [this](const int& pos) { std::lock_guard<std::mutex> lock(seek_mutex_); position_ = pos; seek_called_ = true; gst_pipeline_->play(false); return true; }, [this]() { return position_; }, "Track position", "Current position of the track", 0, 0, track_duration_ / GST_SECOND); position_task_ = std::make_unique<PeriodicTask<>>( [this]() { gint64 position; gst_element_query_position( gst_pipeline_->get_pipeline(), GST_FORMAT_TIME, &position); position_ = static_cast<int>(position / GST_SECOND); pmanage<MPtr(&PContainer::notify)>(position_id_); }, std::chrono::milliseconds(500)); } } std::lock_guard<std::mutex> lock(seek_mutex_); if (seek_called_) { seek_called_ = false; gst_element_seek_simple(gst_pipeline_->get_pipeline(), GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position_ * GST_SECOND); gst_pipeline_->play(true); } break; } default: break; } return GST_BUS_PASS; }
void Logger::log_handler(const gchar* log_domain, GLogLevelFlags log_level, const gchar* message, gpointer user_data) { Logger* context = static_cast<Logger*>(user_data); if (context->mute_) return; gboolean update_last_line = TRUE; std::string tmp_message = std::string((nullptr == message) ? "null-message" : message); std::string tmp_log_domain = std::string((nullptr == log_domain) ? "null-log-domain" : log_domain); std::string tmp_level = std::string("unknown"); switch (log_level) { case G_LOG_LEVEL_ERROR: tmp_level = std::string("error"); break; case G_LOG_LEVEL_CRITICAL: tmp_level = std::string("critical"); break; case G_LOG_LEVEL_WARNING: tmp_level = std::string("warning"); break; case G_LOG_LEVEL_MESSAGE: if (context->debug_ || context->verbose_) tmp_level = std::string("message"); else update_last_line = FALSE; break; case G_LOG_LEVEL_INFO: if (context->debug_ || context->verbose_) tmp_level = std::string("info"); else update_last_line = FALSE; break; case G_LOG_LEVEL_DEBUG: if (context->debug_) tmp_level = std::string("debug"); else update_last_line = FALSE; break; default: break; } if (update_last_line) { { auto lock = context->pmanage<MPtr(&PContainer::get_lock)>(context->last_line_id_); context->last_line_ = tmp_log_domain + "-" + tmp_level + ": " + tmp_message; } context->pmanage<MPtr(&PContainer::notify)>(context->last_line_id_); } }
gboolean GstVideoCodec::reset_codec_configuration(gpointer /*unused */, gpointer user_data) { GstVideoCodec* context = static_cast<GstVideoCodec*>(user_data); auto& quid = context->quid_; auto* codec_sel = &context->codecs_; codec_sel->select(context->codecs_.get_index("x264enc")); quid->pmanage<MPtr(&PContainer::notify)>(context->codec_id_); context->make_codec_properties(); quid->pmanage<MPtr(&PContainer::set_str)>(quid->pmanage<MPtr(&PContainer::get_id)>("bitrate"), "4096"); quid->pmanage<MPtr(&PContainer::set_str)>(quid->pmanage<MPtr(&PContainer::get_id)>("pass"), "cbr"); return TRUE; }
bool JackToShmdata::stop() { { std::lock_guard<std::mutex> lock(input_ports_mutex_); input_ports_.clear(); } shm_.reset(nullptr); pmanage<MPtr(&PContainer::enable)>(auto_connect_id_); pmanage<MPtr(&PContainer::enable)>(num_channels_id_); pmanage<MPtr(&PContainer::enable)>(client_name_id_); pmanage<MPtr(&PContainer::enable)>(connect_to_id_); pmanage<MPtr(&PContainer::enable)>(index_id_); return true; }
bool PulseSrc::stop() { shm_sub_.reset(nullptr); prune_tree(".shmdata.writer." + shmpath_); pmanage<MPtr(&PContainer::remove)>(volume_id_); volume_id_ = 0; pmanage<MPtr(&PContainer::remove)>(mute_id_); mute_id_ = 0; if (!remake_elements()) return false; volume_id_ = pmanage<MPtr(&PContainer::push)>( "volume", GPropToProp::to_prop(G_OBJECT(pulsesrc_.get_raw()), "volume")); mute_id_ = pmanage<MPtr(&PContainer::push)>( "mute", GPropToProp::to_prop(G_OBJECT(pulsesrc_.get_raw()), "mute")); gst_pipeline_ = std::make_unique<GstPipeliner>(nullptr, nullptr); return true; }
int JackToShmdata::jack_process(jack_nframes_t nframes, void* arg) { auto context = static_cast<JackToShmdata*>(arg); { std::lock_guard<std::mutex> lock(context->port_to_connect_in_jack_process_mutex_); for (auto& it : context->port_to_connect_in_jack_process_) jack_connect(context->jack_client_.get_raw(), it.first.c_str(), it.second.c_str()); context->port_to_connect_in_jack_process_.clear(); } { std::unique_lock<std::mutex> lock(context->input_ports_mutex_, std::defer_lock); if (lock.try_lock()) { std::size_t num_chan = context->input_ports_.size(); if (0 == num_chan) return 0; std::vector<jack_sample_t*> jack_bufs; for (auto& port : context->input_ports_) { jack_sample_t* buf = (jack_sample_t*)jack_port_get_buffer(port.get_raw(), nframes); if (!buf) return 0; jack_bufs.emplace_back(buf); } std::size_t index = 0; for (unsigned int j = 0; j < nframes; ++j) { for (unsigned int i = 0; i < num_chan; ++i) { context->buf_[index] = jack_bufs[i][j]; ++index; } } size_t size = nframes * num_chan * sizeof(jack_sample_t); context->shm_->writer<MPtr(&shmdata::Writer::copy_to_shm)>(context->buf_.data(), size); context->shm_->bytes_written(size); } // locked } // releasing lock return 0; }
bool PulseSink::on_shmdata_disconnect() { pmanage<MPtr(&PContainer::enable)>(devices_enum_id_); prune_tree(".shmdata.reader." + shmpath_); shm_sub_.reset(); On_scope_exit { gst_pipeline_ = std::make_unique<GstPipeliner>(nullptr, nullptr); }; return remake_elements(); }
bool PulseSink::on_shmdata_connect(const std::string& shmpath) { pmanage<MPtr(&PContainer::disable)>(devices_enum_id_, ShmdataConnector::disabledWhenConnectedMsg); shmpath_ = shmpath; g_object_set(G_OBJECT(shmsrc_.get_raw()), "socket-path", shmpath_.c_str(), nullptr); if (!devices_.empty()) g_object_set(G_OBJECT(pulsesink_.get_raw()), "device", devices_.at(devices_enum_.get()).name_.c_str(), nullptr); shm_sub_ = std::make_unique<GstShmdataSubscriber>( shmsrc_.get_raw(), [this](const std::string& caps) { this->graft_tree( ".shmdata.reader." + shmpath_, ShmdataUtils::make_tree(caps, ShmdataUtils::get_category(caps), ShmdataStat())); }, ShmdataStat::make_tree_updater(this, ".shmdata.reader." + shmpath_)); gst_bin_add_many(GST_BIN(gst_pipeline_->get_pipeline()), shmsrc_.get_raw(), audioconvert_.get_raw(), pulsesink_.get_raw(), nullptr); gst_element_link_many(shmsrc_.get_raw(), audioconvert_.get_raw(), pulsesink_.get_raw(), nullptr); gst_pipeline_->play(true); return true; }
PJWhiteList::PJWhiteList() : mode_id_(SIPPlugin::this_->pmanage<MPtr(&PContainer::make_selection<>)>( "mode", [this](size_t val) { mode_.select(val); return true; }, [this]() { return mode_.get(); }, "Access list mode", "Control which incoming calls are accepted", mode_)), everybody_(mode_.get_index("everybody")) { SIPPlugin::this_->install_method( "Authorized Incoming Call From", // long name "authorize", // name "authorize incoming call from an buddy", // description "success", // return desc Method::make_arg_description("SIP url", // long name "url", // name "string", // description "Authorized", // long name "authorized", // name "boolean", // description nullptr), (Method::method_ptr)&authorize_buddy_cb, G_TYPE_BOOLEAN, Method::make_arg_type_description(G_TYPE_STRING, G_TYPE_BOOLEAN, nullptr), this); }
bool GstVideoCodec::start() { hide(); if (0 == quid_->pmanage<MPtr(&PContainer::get<Selection<>::index_t>)>(codec_id_)) return true; shmsink_sub_ = std::make_unique<GstShmdataSubscriber>( shm_encoded_.get_raw(), [this](const std::string& caps) { this->quid_->graft_tree( ".shmdata.writer." + shm_encoded_path_, ShmdataUtils::make_tree(caps, ShmdataUtils::get_category(caps), ShmdataStat())); }, ShmdataStat::make_tree_updater(quid_, ".shmdata.writer." + shm_encoded_path_)); shmsrc_sub_ = std::make_unique<GstShmdataSubscriber>( shmsrc_.get_raw(), [this](const std::string& caps) { this->quid_->graft_tree( ".shmdata.reader." + shmpath_to_encode_, ShmdataUtils::make_tree(caps, ShmdataUtils::get_category(caps), ShmdataStat())); }, ShmdataStat::make_tree_updater(quid_, ".shmdata.reader." + shmpath_to_encode_)); make_bin(); g_object_set(G_OBJECT(gst_pipeline_->get_pipeline()), "async-handling", TRUE, nullptr); if (copy_buffers_) g_object_set(G_OBJECT(shmsrc_.get_raw()), "copy-buffers", TRUE, nullptr); gst_pipeline_->play(true); return true; }
RTMP::RTMP(quid::Config&& conf) : Quiddity(std::forward<quid::Config>(conf)), shmcntr_(static_cast<Quiddity*>(this)), gst_pipeline_(std::make_unique<GstPipeliner>(nullptr, nullptr)) { stream_app_url_id_ = pmanage<MPtr(&PContainer::make_string)>( "stream_app_url", [this](const std::string& val) { stream_app_url_ = val; if (!stream_key_.empty() && (!audio_shmpath_.empty() || !video_shmpath_.empty())) return create_gst_pipeline(); return true; }, [this]() { return stream_app_url_; }, "Stream application URL", "RTMP address used to stream.", stream_app_url_); stream_key_id_ = pmanage<MPtr(&PContainer::make_string)>( "stream_key", [this](const std::string& val) { stream_key_ = val; if (!stream_app_url_.empty() && (!audio_shmpath_.empty() || !video_shmpath_.empty())) return create_gst_pipeline(); return true; }, [this]() { return stream_key_; }, "Stream key", "Stream application-specific stream key needed to link to application account.", stream_key_); shmcntr_.install_connect_method( [this](const std::string& shmpath) { if (StringUtils::ends_with(shmpath, "video-encoded")) return on_shmdata_connect(shmpath, ShmType::VIDEO); else return on_shmdata_connect(shmpath, ShmType::AUDIO); }, [this](const std::string& shmpath) { if (StringUtils::ends_with(shmpath, "video-encoded")) return on_shmdata_disconnect(ShmType::VIDEO); else return on_shmdata_disconnect(ShmType::AUDIO); }, nullptr, [this](const std::string& caps) { return can_sink_caps(caps); }, std::numeric_limits<unsigned int>::max()); }
bool Timelapse::on_shmdata_connect(const std::string& shmpath) { std::unique_lock<std::mutex> lock(timelapse_mtx_); if (timelapse_.size() == 1) { pmanage<MPtr(&PContainer::disable)>(img_name_id_, ShmdataConnector::disabledWhenConnectedMsg); img_name_.clear(); } return start_timelapse(shmpath); }
bool PulseSink::remake_elements() { pmanage<MPtr(&PContainer::remove)>(volume_id_); volume_id_ = 0; pmanage<MPtr(&PContainer::remove)>(mute_id_); mute_id_ = 0; if (!UGstElem::renew(pulsesink_, {"volume", "mute", "slave-method", "client-name", "device"}) || !UGstElem::renew(shmsrc_) || !UGstElem::renew(audioconvert_)) return false; volume_id_ = pmanage<MPtr(&PContainer::push)>( "volume", GPropToProp::to_prop(G_OBJECT(pulsesink_.get_raw()), "volume")); mute_id_ = pmanage<MPtr(&PContainer::push)>( "mute", GPropToProp::to_prop(G_OBJECT(pulsesink_.get_raw()), "mute")); if (!devices_.empty()) g_object_set(G_OBJECT(pulsesink_.get_raw()), "device", devices_.at(devices_enum_.get()).name_.c_str(), nullptr); return true; }
bool AVPlayer::stop() { position_task_.reset(); gst_pipeline_ = std::make_unique<GstPipeliner>(nullptr, nullptr); pmanage<MPtr(&PContainer::remove)>(position_id_); position_id_ = 0; track_duration_ = 0; pause_ = false; files_list_.clear(); return true; }
Logger::Logger(const std::string&) : last_line_id_(pmanage<MPtr(&PContainer::make_string)>("last-line", nullptr, [this]() { std::unique_lock<std::mutex> lock( last_line_mutex_); return last_line_; }, "Last Log Line", "Provide last log line", last_line_)) { pmanage<MPtr(&PContainer::make_bool)>("mute", [this](bool val) { mute_ = val; return true; }, [this]() { return mute_; }, "Mute", "Mute log messages", mute_); pmanage<MPtr(&PContainer::make_bool)>("debug", [this](bool val) { debug_ = val; return true; }, [this]() { return debug_; }, "Debug", "Enable debug log level", debug_); pmanage<MPtr(&PContainer::make_bool)>("verbose", [this](bool val) { verbose_ = val; return true; }, [this]() { return verbose_; }, "Verbose", "Enable verbose log level", verbose_); }
bool NVdecPlugin::on_shmdata_connect(const std::string& shmpath) { shmfollower_.reset(nullptr); shmfollower_ = std::make_unique<ShmdataFollower>( this, shmpath, [this](void* data, size_t size) { this->on_shmreader_data(data, size); }, [this](const std::string& data_descr) { this->on_shmreader_server_connected(data_descr); }, [this]() { this->on_shmreader_server_disconnected(); }); pmanage<MPtr(&PContainer::disable)>(devices_id_, ShmdataConnector::disabledWhenConnectedMsg); return static_cast<bool>(shmfollower_.get()); }
bool Timelapse::start_timelapse(const std::string& shmpath) { { auto timelapse = timelapse_.find(shmpath); if (timelapse_.end() != timelapse) timelapse_.erase(timelapse); } auto img_path = img_dir_; auto img_from_shmpath = img_dir_.empty() ? shmpath : shmpath.substr(shmpath.find_last_of("/") + 1); img_path += img_name_.empty() ? img_from_shmpath : img_name_; if (num_files_ && std::string::npos == img_path.find('%')) img_path += "_%d.jpg"; else if (img_name_.empty()) img_path += ".jpg"; timelapse_config_ = GstVideoTimelapseConfig(shmpath, img_path); timelapse_config_.framerate_num_ = framerate_.numerator(); timelapse_config_.framerate_denom_ = framerate_.denominator(); timelapse_config_.width_ = width_; timelapse_config_.height_ = height_; timelapse_config_.jpg_quality_ = jpg_quality_; timelapse_config_.max_files_ = max_files_; auto new_timelapse = std::make_unique<GstVideoTimelapse>( timelapse_config_, [this, shmpath](const std::string& caps) { graft_tree(".shmdata.reader." + shmpath, ShmdataUtils::make_tree(caps, ShmdataUtils::get_category(caps), ShmdataStat())); }, ShmdataStat::make_tree_updater(this, ".shmdata.reader." + shmpath), nullptr, [this, shmpath](std::string&& file_name) { if (!notify_last_file_) return; { auto lock = pmanage<MPtr(&PContainer::get_lock)>(last_image_id_); last_image_ = file_name; } pmanage<MPtr(&PContainer::notify)>(last_image_id_); }); if (!new_timelapse.get()) return false; timelapse_[shmpath] = std::move(new_timelapse); return true; }
bool GstVideoCodec::stop() { show(); if (0 != quid_->pmanage<MPtr(&PContainer::get<Selection<>::index_t>)>(codec_id_)) { shmsink_sub_.reset(); shmsrc_sub_.reset(); quid_->prune_tree(".shmdata.writer." + shm_encoded_path_); quid_->prune_tree(".shmdata.reader." + shmpath_to_encode_); remake_codec_elements(); make_codec_properties(); gst_pipeline_ = std::make_unique<GstPipeliner>(nullptr, nullptr); } return true; }
bool ExternalShmdataWriter::init() { pmanage<MPtr(&PContainer::make_string)>( "shmdata-path", [this](const std::string& val) { shmdata_path_ = val; shm_ = std::make_unique<ShmdataFollower>( this, shmdata_path_, nullptr, nullptr, nullptr, ".shmdata.writer."); return true; }, [this]() { return shmdata_path_; }, "Shmdata Path", "Path Of The Shmdata The Include", ""); return true; }
ProtocolMapper::ProtocolMapper(quid::Config&& conf) : Quiddity(std::forward<quid::Config>(conf)) { config_file_id_ = pmanage<MPtr(&PContainer::make_string)>( "config_file", [this](const std::string& val) { config_file_ = val; auto file_content = FileUtils::get_file_content(val); if (file_content.first.empty()) { message("ERROR: %", file_content.second); return false; } auto tree = JSONSerializer::deserialize(file_content.first); if (!tree) { message("ERROR: % is not a valid json file", val); return false; } protocol_reader_.reset(); protocol_reader_ = ProtocolReader::create_protocol_reader(this, tree.get()); if (!protocol_reader_) { warning("Could not create protocol reader (protocol-mapper)."); return false; } // Create quiddity properties from "commands" section of the json. if (!protocol_reader_->make_properties(this, tree->get_tree("commands").get())) return false; pmanage<MPtr(&PContainer::disable)>(config_file_id_, "Service already loaded"); return true; }, [this]() { return config_file_; }, "Path to command description file", "Load the command description", config_file_); }
bool PulseSrc::init() { init_startable(this); if (!pulsesrc_ || !shmsink_) return false; shmpath_ = make_file_name("audio"); g_object_set(G_OBJECT(pulsesrc_.get_raw()), "client-name", get_name().c_str(), nullptr); g_object_set(G_OBJECT(shmsink_.get_raw()), "socket-path", shmpath_.c_str(), nullptr); std::unique_lock<std::mutex> lock(devices_mutex_); GstUtils::g_idle_add_full_with_context(mainloop_->get_main_context(), G_PRIORITY_DEFAULT_IDLE, async_get_pulse_devices, this, nullptr); // waiting for devices to be updated devices_cond_.wait(lock); if (!connected_to_pulse_) { g_message("ERROR:Not connected to pulse, cannot initialize."); return false; } volume_id_ = pmanage<MPtr(&PContainer::push)>( "volume", GPropToProp::to_prop(G_OBJECT(pulsesrc_.get_raw()), "volume")); mute_id_ = pmanage<MPtr(&PContainer::push)>( "mute", GPropToProp::to_prop(G_OBJECT(pulsesrc_.get_raw()), "mute")); return true; }
void GstVideoCodec::make_codec_properties() { uninstall_codec_properties(); guint num_properties = 0; GParamSpec** props = g_object_class_list_properties(G_OBJECT_GET_CLASS(codec_element_.get_raw()), &num_properties); On_scope_exit { g_free(props); }; for (guint i = 0; i < num_properties; i++) { auto param_name = g_param_spec_get_name(props[i]); if (param_black_list_.end() == param_black_list_.find(param_name)) { quid_->pmanage<MPtr(&PContainer::push_parented)>( param_name, "codec_params", GPropToProp::to_prop(G_OBJECT(codec_element_.get_raw()), param_name)); codec_properties_.push_back(param_name); } } }
PContainer::prop_id_t GstVideoCodec::install_codec() { return quid_->pmanage<MPtr(&PContainer::make_selection<>)>( "codec", [this](const Selection<>::index_t& val) { uninstall_codec_properties(); codecs_.select(val); if (0 == val) return true; std::string codec_name = codecs_.get_attached(); codec_element_.mute(codec_name.c_str()); if (codec_name == "x264enc") copy_buffers_ = true; else copy_buffers_ = false; remake_codec_elements(); make_codec_properties(); if (codec_name == "x264enc") g_object_set(G_OBJECT(codec_element_.get_raw()), "byte-stream", TRUE, nullptr); return true; }, [this]() { return codecs_.get(); }, "Video Codecs", "Selected video codec for encoding", codecs_); }
void PulseSrc::get_source_info_callback(pa_context* pulse_context, const pa_source_info* i, int is_last, void* user_data) { PulseSrc* context = static_cast<PulseSrc*>(user_data); if (is_last < 0) { g_debug("Failed to get source information: %s", pa_strerror(pa_context_errno(pulse_context))); return; } if (is_last) { pa_operation* operation = pa_context_drain(pulse_context, nullptr, nullptr); if (operation) pa_operation_unref(operation); // registering enum for devices context->update_capture_device(); context->devices_id_ = context->pmanage<MPtr(&PContainer::make_selection<>)>( "device", [context](const size_t& val) { context->devices_.select(val); return true; }, [context]() { return context->devices_.get(); }, "Device", "Audio capture device to use", context->devices_); // signal init we are done std::unique_lock<std::mutex> lock(context->devices_mutex_); context->devices_cond_.notify_all(); return; } DeviceDescription description; switch (i->state) { case PA_SOURCE_INIT: description.state_ = "INIT"; // g_print ("state: INIT \n"); break; case PA_SOURCE_UNLINKED: description.state_ = "UNLINKED"; // g_print ("state: UNLINKED \n"); break; case PA_SOURCE_INVALID_STATE: description.state_ = "n/a"; // g_print ("state: n/a \n"); break; case PA_SOURCE_RUNNING: description.state_ = "RUNNING"; // g_print ("state: RUNNING \n"); break; case PA_SOURCE_IDLE: description.state_ = "IDLE"; // g_print ("state: IDLE \n"); break; case PA_SOURCE_SUSPENDED: description.state_ = "SUSPENDED"; // g_print ("state: SUSPENDED \n"); break; } description.name_ = i->name; if (i->description == nullptr) description.description_ = ""; else description.description_ = i->description; description.sample_format_ = pa_sample_format_to_string(i->sample_spec.format); gchar* rate = g_strdup_printf("%u", i->sample_spec.rate); description.sample_rate_ = rate; g_free(rate); gchar* channels = g_strdup_printf("%u", i->sample_spec.channels); description.channels_ = channels; g_free(channels); // g_print ("Name: %s\n" // "Description: %s\n" // " format: %s\n" // " rate: %u\n" // " channels: %u\n", // //"Channel Map: %s\n", // i->name, // i->description,// warning this can be nullptr // pa_sample_format_to_string (i->sample_spec.format), // i->sample_spec.rate, // i->sample_spec.channels//, // // pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) // ); if (i->ports) { pa_source_port_info** p; // printf("\tPorts:\n"); for (p = i->ports; *p; p++) { // printf("\t\t%s: %s (priority. %u)\n", (*p)->name, (*p)->description, // (*p)->priority); description.ports_.push_back(std::make_pair((*p)->name, (*p)->description)); } } if (i->active_port) { // printf("\tActive Port: %s\n", i->active_port->name); description.active_port_ = i->active_port->description; } else description.active_port_ = "n/a"; context->capture_devices_.push_back(description); // if (i->formats) { // uint8_t j; // printf("\tFormats:\n"); // for (j = 0; j < i->n_formats; j++) // printf("\t\t%s\n", pa_format_info_snprint(f, sizeof(f), i->formats[j])); // } }
std::string QuiddityManager::get_serialized_command_history() const { auto quiddities = manager_impl_->get_instances(); for (auto& it : quiddities_at_reset_) { auto tmp = std::find(quiddities.begin(), quiddities.end(), it); if (quiddities.end() != tmp) quiddities.erase(tmp); } if (quiddities.empty()) { g_warning("nothing to save"); return {}; } InfoTree::ptr tree = InfoTree::make(); // saving history for (unsigned int i = 0; i < command_history_.history_.size(); i++) { tree->graft(std::string("history.") + std::to_string(i), command_history_.history_[i]->get_info_tree()); } tree->tag_as_array("history", true); // saving per-quiddity information auto quid_str = std::string(".quiddities."); for (auto& quid_name : quiddities) { // name and class auto quid_class = manager_impl_->get_quiddity(quid_name)->get_documentation()->get_class_name(); tree->graft(quid_str + quid_name, InfoTree::make(quid_class)); // saving custom tree if some is provided auto custom_tree = manager_impl_->get_quiddity(quid_name)->on_saving(); if (custom_tree && !custom_tree->empty()) tree->graft(".custom_states." + quid_name, std::move(custom_tree)); // user data auto quid_user_data_tree = user_data<MPtr(&InfoTree::get_tree)>(quid_name, "."); if (!quid_user_data_tree->empty()) { tree->graft(".userdata." + quid_name, user_data<MPtr(&InfoTree::get_tree)>(quid_name, ".")); } // writable property values use_prop<MPtr(&PContainer::update_values_in_tree)>(quid_name); auto props = use_tree<MPtr(&InfoTree::get_child_keys)>(quid_name, "property"); for (auto& prop : props) { if (use_tree<MPtr(&InfoTree::branch_get_value)>( quid_name, std::string("property.") + prop + ".writable")) { tree->graft(".properties." + quid_name + "." + prop, InfoTree::make(use_tree<MPtr(&InfoTree::branch_get_value)>( quid_name, std::string("property.") + prop + ".value"))); } } // Record shmdata connections. // Ignore them if no connect-to methods is installed for this quiddity. if (!manager_impl_->get_quiddity(quid_name)->has_method("connect")) continue; auto readers = use_tree<MPtr(&InfoTree::get_child_keys)>(quid_name, "shmdata.reader"); int nb = 0; for (auto& reader : readers) { if (!reader.empty()) { tree->graft(".readers." + quid_name + ".reader_" + std::to_string(++nb), InfoTree::make(reader)); } } tree->tag_as_array(".readers." + quid_name, true); } // calling on_saved callback for (auto& quid_name : quiddities) { manager_impl_->get_quiddity(quid_name)->on_saved(); } return JSONSerializer::serialize(tree.get()); }
PropertyQuid::PropertyQuid(quid::Config&& conf) : Quiddity(std::forward<quid::Config>(conf)), bool_id_(pmanage<MPtr(&PContainer::make_bool)>("bool_", [this](bool val) { bool_ = val; return true; }, [this]() { return bool_; }, "Bool Example", "This property is an example for type bool", bool_)), string_id_( pmanage<MPtr(&PContainer::make_string)>("string_", [this](const std::string& val) { string_ = val; return true; }, [this]() { return string_; }, "String Example", "This property is an example for type string", string_)), char_id_(pmanage<MPtr(&PContainer::make_char)>("char_", [this](const char& val) { char_ = val; return true; }, [this]() { return char_; }, "Char Example", "This property is an example for type char", char_)), color_id_(pmanage<MPtr(&PContainer::make_color)>("color_", [this](const Color& val) { color_ = val; return true; }, [this]() { return color_; }, "Color Example", "This property is an example for type color", color_)), integral_group_id_(pmanage<MPtr(&PContainer::make_group)>( "integrals", "Integral Group Example", "This property is an example for grouping integral types")), int_id_(pmanage<MPtr(&PContainer::make_parented_int)>( // PContainer factory "int_", // string id "integrals", // parent [this](int val) { int_ = val; return true; }, // setter [this]() { return int_; }, // getter "Int Example", // name "This property is an example for type int", // description int_, // default value -10, // min 10)), // max short_id_(pmanage<MPtr(&PContainer::make_parented_short)>( "short_", "integrals", [this](short val) { short_ = val; return true; }, [this]() { return short_; }, "Short Example", "This property is an example for type short", short_, -11, 11)), long_id_(pmanage<MPtr(&PContainer::make_parented_long)>( "long_", "integrals", [this](long val) { long_ = val; return true; }, [this]() { return long_; }, "Long Example", "This property is an example for type long", long_, -20, 20)), long_long_id_(pmanage<MPtr(&PContainer::make_parented_long_long)>( "long_long_", "integrals", [this](long long val) { long_long_ = val; return true; }, [this]() { return long_long_; }, "Long Long Example", "This property is an example for type long long", long_long_, -21, 21)), unsigned_int_id_(pmanage<MPtr(&PContainer::make_parented_unsigned_int)>( "unsigned_int_", "integrals", [this](unsigned int val) { unsigned_int_ = val; return true; }, [this]() { return unsigned_int_; }, "Unsigned Int Example", "This property is an example for type unsigned int", unsigned_int_, 0, 10)), unsigned_short_id_(pmanage<MPtr(&PContainer::make_parented_unsigned_short)>( "unsigned_short_", "integrals", [this](unsigned short val) { unsigned_short_ = val; return true; }, [this]() { return unsigned_short_; }, "Unsigned Short Example", "This property is an example for type unsigned short", unsigned_short_, 1, 11)), unsigned_long_id_(pmanage<MPtr(&PContainer::make_parented_unsigned_long)>( "unsigned_long_", "integrals", [this](unsigned long val) { unsigned_long_ = val; return true; }, [this]() { return unsigned_long_; }, "Unsigned Long Example", "This property is an example for type unsigned long", unsigned_long_, 4, 200)), unsigned_long_long_id_(pmanage<MPtr(&PContainer::make_parented_unsigned_long_long)>( "unsigned_long_long_", "integrals", [this](unsigned long long val) { unsigned_long_long_ = val; return true; }, [this]() { return unsigned_long_long_; }, "Unsigned Long Long Example", "This property is an example for type unsigned long long", unsigned_long_long_, 2, 210)), floating_point_group_id_(pmanage<MPtr(&PContainer::make_group)>( "floats", "Floating Point Group Example", "This property is an example for grouping floating points")), float_id_(pmanage<MPtr(&PContainer::make_parented_float)>( "float_", "floats", [this](float val) { float_ = val; return true; }, [this]() { return float_; }, "Float Example", "This property is an example for type float", float_, -1.f, 1.f)), double_id_(pmanage<MPtr(&PContainer::make_parented_double)>( "double_", "floats", [this](double val) { double_ = val; return true; }, [this]() { return double_; }, "Double Example", "This property is an example for type double", double_, -1.f, 10.f)), long_double_id_(pmanage<MPtr(&PContainer::make_parented_long_double)>( "long_double_", "floats", [this](long double val) { long_double_ = val; return true; }, [this]() { return long_double_; }, "Long Double Example", "This property is an example for type long double", long_double_, -1.f, 10.f)), selection_id_( pmanage<MPtr(&PContainer::make_selection<>)>("enum_", [this](const IndexOrName& val) { selection_.select(val); return true; }, [this]() { return selection_.get(); }, "Selection Example", "This property is an example for type enum", selection_)), tuple_id_( pmanage<MPtr(&PContainer::make_tuple<MyTuple>)>("tuple_", [this](const MyTuple& val) { tuple_ = val; return true; }, [this]() { return tuple_; }, "Tuple Example", "This property is an example for tuple", tuple_)), fraction_id_( pmanage<MPtr(&PContainer::make_fraction)>("fraction_", [this](const Fraction& val) { fraction_ = val; return true; }, [this]() { return fraction_; }, "Fraction Example", "This property is an example for fraction", fraction_, -10, 1, // min num/denom 10, 10) // max num/denom ) { // std::cout << pmanage<MPtr(&PContainer::get<int>)>( int_id_) << std::endl; // std::cout << pmanage<MPtr(&PContainer::get<unsigned int>)>( uint_id_) << // std::endl; pmanage<MPtr(&PContainer::set<MyTuple>)>( tuple_id_, std::make_tuple<long long, float, std::string>(2, 2.2, "a22")); std::cout << std::get<0>(tuple_) << " " // 2 << std::get<1>(tuple_) << " " // 2.2 << std::get<2>(tuple_) << "\n"; // a22 // creating some custom infos InfoTree::ptr tree = InfoTree::make(); tree->graft(".child1.child2", InfoTree::make("switch")); tree->graft(".child1.child3", InfoTree::make(1.2f)); tree->graft(".child1.child2.bla1", InfoTree::make("wire")); tree->graft(".child1.child2.bla2", InfoTree::make("hub")); // attaching it to the quiddity (at the root) graft_tree(".custom.information.", tree); debug("hello from plugin"); }
Timelapse::Timelapse(const std::string&) : img_dir_id_(pmanage<MPtr(&PContainer::make_string)>( "imgdir", [this](const std::string& val) { img_dir_ = val; if (!img_dir_.empty() && img_dir_.back() != '/') img_dir_ += '/'; auto file_prepared = FileUtils::prepare_writable_dir(val); if (!file_prepared.first) { g_warning("error preparing %s directory for writing: %s", val.c_str(), file_prepared.second.c_str()); return false; } updated_config_.store(true); return true; }, [this]() { return img_dir_; }, "Image Directory", "Directory where to store jpeg files to be produced. If empty, the " "path will be <video_shmdata_path>.jpg", img_dir_)), img_name_id_(pmanage<MPtr(&PContainer::make_string)>( "imgname", [this](const std::string& val) { img_name_ = val; updated_config_.store(true); return true; }, [this]() { return img_name_; }, "Image Name", "Name of the jpeg files to be produced. You can use printf format " "for numbering files (for instance %05d). If empty, the name will " "take the input shmdata name with option file number and jpg " "extension", img_name_)), num_files_id_(pmanage<MPtr(&PContainer::make_bool)>("num_files", [this](const bool& num_files) { num_files_ = num_files; updated_config_.store(true); return true; }, [this]() { return num_files_; }, "Number Files", "Automatically number produced files", num_files_)), notify_last_file_id_( pmanage<MPtr(&PContainer::make_bool)>("notify_last_files", [this](const bool& notify) { notify_last_file_ = notify; return true; }, [this]() { return notify_last_file_; }, "Notify last file produced", "Update last file property with produced jpg file", notify_last_file_)), framerate_id_( pmanage<MPtr(&PContainer::make_fraction)>("framerate", [this](const Fraction& val) { framerate_ = val; updated_config_.store(true); return true; }, [this]() { return framerate_; }, "Framerate", "Number of image to be produced by seconds", framerate_, 1, 1, // min num/denom 60, 5)), // max num/denom max_files_id_(pmanage<MPtr(&PContainer::make_unsigned_int)>( "maxfiles", [this](unsigned int val) { max_files_ = val; updated_config_.store(true); return true; }, [this]() { return max_files_; }, "Max files", "Maximum number of files simultaneously present on disk", max_files_, 0, 4294967295)), jpg_quality_id_( pmanage<MPtr(&PContainer::make_unsigned_int)>("quality", [this](unsigned int val) { jpg_quality_ = val; updated_config_.store(true); return true; }, [this]() { return jpg_quality_; }, "JPEG quality", "Quality of the produced jpeg image", jpg_quality_, 0, 100)), last_image_id_(pmanage<MPtr(&PContainer::make_string)>("last_image", nullptr, [this]() { return last_image_; }, "Last image written", "Path of the last jpeg file written", last_image_)), width_id_(pmanage<MPtr(&PContainer::make_unsigned_int)>("width", [this](unsigned int val) { width_ = val; updated_config_.store(true); return true; }, [this]() { return width_; }, "Width", "Width of the scaled image", width_, 0, 8192)), height_id_(pmanage<MPtr(&PContainer::make_unsigned_int)>("height", [this](unsigned int val) { height_ = val; updated_config_.store(true); return true; }, [this]() { return height_; }, "Height", "Height of the scaled image", height_, 0, 8192)), relaunch_task_( [this]() { if (updated_config_.exchange(false)) { std::unique_lock<std::mutex> lock(timelapse_mtx_); std::vector<std::string> shmdatas; for (auto& it : timelapse_) shmdatas.push_back(it.first); timelapse_.clear(); for (auto& it : shmdatas) start_timelapse(it); } }, std::chrono::milliseconds(200)), shmcntr_(static_cast<Quiddity*>(this)), timelapse_config_{std::string(), std::string()} {} // end ctor
void QuiddityManager::execute_command() { switch (command_->id_) { case QuiddityCommand::set_property: if (manager_impl_->props<MPtr(&PContainer::set_str_str)>( command_->args_[0], command_->args_[1], command_->args_[2])) command_->result_.push_back("true"); else command_->result_.push_back("false"); break; case QuiddityCommand::get_classes: command_->result_ = manager_impl_->get_classes(); break; case QuiddityCommand::get_classes_doc: command_->result_.push_back(manager_impl_->get_classes_doc()); break; case QuiddityCommand::get_class_doc: command_->result_.push_back(manager_impl_->get_class_doc(command_->args_[0])); break; case QuiddityCommand::get_quiddities_description: command_->result_.push_back(manager_impl_->get_quiddities_description()); break; case QuiddityCommand::get_quiddity_description: command_->result_.push_back(manager_impl_->get_quiddity_description(command_->args_[0])); break; case QuiddityCommand::create: command_->result_.push_back(manager_impl_->create(command_->args_[0])); break; case QuiddityCommand::create_nick_named: command_->result_.push_back(manager_impl_->create(command_->args_[0], command_->args_[1])); break; case QuiddityCommand::remove: if (manager_impl_->remove(command_->args_[0])) command_->result_.push_back("true"); else command_->result_.push_back("false"); break; case QuiddityCommand::get_methods_description: command_->result_.push_back(manager_impl_->get_methods_description(command_->args_[0])); break; case QuiddityCommand::get_method_description: command_->result_.push_back( manager_impl_->get_method_description(command_->args_[0], command_->args_[1])); break; case QuiddityCommand::get_methods_description_by_class: command_->result_.push_back( manager_impl_->get_methods_description_by_class(command_->args_[0])); break; case QuiddityCommand::get_method_description_by_class: command_->result_.push_back( manager_impl_->get_method_description_by_class(command_->args_[0], command_->args_[1])); break; case QuiddityCommand::invoke: { std::string* result = nullptr; if (manager_impl_->invoke( command_->args_[0], command_->args_[1], &result, command_->vector_arg_)) { command_->success_ = true; // result_.push_back ("true"); if (nullptr == result) command_->result_.push_back("error"); else command_->result_.push_back(*result); } else command_->success_ = false; // result_.push_back ("false"); if (nullptr != result) delete result; } break; case QuiddityCommand::subscribe_signal: if (manager_impl_->subscribe_signal( command_->args_[0], command_->args_[1], command_->args_[2])) command_->result_.push_back("true"); else command_->result_.push_back("false"); break; case QuiddityCommand::unsubscribe_signal: if (manager_impl_->unsubscribe_signal( command_->args_[0], command_->args_[1], command_->args_[2])) command_->result_.push_back("true"); else command_->result_.push_back("false"); break; default: g_debug("** unknown command, cannot launch %s\n", QuiddityCommand::get_string_from_id(command_->id_)); } }
bool Timelapse::on_shmdata_disconnect_all() { std::unique_lock<std::mutex> lock(timelapse_mtx_); pmanage<MPtr(&PContainer::enable)>(img_name_id_); timelapse_.clear(); return true; }