/****************************************************************************** Copyright (C) 2023 by Lain Bailey Zachary Lund Philippe Groarke This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ******************************************************************************/ #include "OBSBasic.hpp" #include #include #include #include #include #include #include #include #include #include #include #include void OBSBasic::copyActionsDynamicProperties() { // Themes need the QAction dynamic properties for (QAction *x : ui->scenesToolbar->actions()) { QWidget *temp = ui->scenesToolbar->widgetForAction(x); if (!temp) continue; for (QByteArray &y : x->dynamicPropertyNames()) { temp->setProperty(y, x->property(y)); } } for (QAction *x : ui->sourcesToolbar->actions()) { QWidget *temp = ui->sourcesToolbar->widgetForAction(x); if (!temp) continue; for (QByteArray &y : x->dynamicPropertyNames()) { temp->setProperty(y, x->property(y)); } } for (QAction *x : ui->mixerToolbar->actions()) { QWidget *temp = ui->mixerToolbar->widgetForAction(x); if (!temp) continue; for (QByteArray &y : x->dynamicPropertyNames()) { temp->setProperty(y, x->property(y)); } } } void OBSBasic::ClearContextBar() { QLayoutItem *la = ui->emptySpace->layout()->itemAt(0); if (la) { delete la->widget(); ui->emptySpace->layout()->removeItem(la); } } void OBSBasic::UpdateContextBarVisibility() { int width = ui->centralwidget->size().width(); ContextBarSize contextBarSizeNew; if (width >= 740) { contextBarSizeNew = ContextBarSize_Normal; } else if (width >= 600) { contextBarSizeNew = ContextBarSize_Reduced; } else { contextBarSizeNew = ContextBarSize_Minimized; } if (contextBarSize == contextBarSizeNew) return; contextBarSize = contextBarSizeNew; UpdateContextBarDeferred(); } static bool is_network_media_source(obs_source_t *source, const char *id) { if (strcmp(id, "ffmpeg_source") != 0) return false; OBSDataAutoRelease s = obs_source_get_settings(source); bool is_local_file = obs_data_get_bool(s, "is_local_file"); return !is_local_file; } void OBSBasic::UpdateContextBarDeferred(bool force) { QMetaObject::invokeMethod(this, "UpdateContextBar", Qt::QueuedConnection, Q_ARG(bool, force)); } void OBSBasic::SourceToolBarActionsSetEnabled() { bool enable = false; bool disableProps = false; OBSSceneItem item = GetCurrentSceneItem(); if (item) { OBSSource source = obs_sceneitem_get_source(item); disableProps = !obs_source_configurable(source); enable = true; } if (disableProps) ui->actionSourceProperties->setEnabled(false); else ui->actionSourceProperties->setEnabled(enable); ui->actionRemoveSource->setEnabled(enable); ui->actionSourceUp->setEnabled(enable); ui->actionSourceDown->setEnabled(enable); RefreshToolBarStyling(ui->sourcesToolbar); } void OBSBasic::UpdateContextBar(bool force) { SourceToolBarActionsSetEnabled(); if (!ui->contextContainer->isVisible() && !force) return; OBSSceneItem item = GetCurrentSceneItem(); if (item) { obs_source_t *source = obs_sceneitem_get_source(item); bool updateNeeded = true; QLayoutItem *la = ui->emptySpace->layout()->itemAt(0); if (la) { if (SourceToolbar *toolbar = dynamic_cast(la->widget())) { if (toolbar->GetSource() == source) updateNeeded = false; } else if (MediaControls *toolbar = dynamic_cast(la->widget())) { if (toolbar->GetSource() == source) updateNeeded = false; } } const char *id = obs_source_get_unversioned_id(source); uint32_t flags = obs_source_get_output_flags(source); ui->sourceInteractButton->setVisible(flags & OBS_SOURCE_INTERACTION); if (contextBarSize >= ContextBarSize_Reduced && (updateNeeded || force)) { ClearContextBar(); if (flags & OBS_SOURCE_CONTROLLABLE_MEDIA) { if (!is_network_media_source(source, id)) { MediaControls *mediaControls = new MediaControls(ui->emptySpace); mediaControls->SetSource(source); ui->emptySpace->layout()->addWidget(mediaControls); } } else if (strcmp(id, "browser_source") == 0) { BrowserToolbar *c = new BrowserToolbar(ui->emptySpace, source); ui->emptySpace->layout()->addWidget(c); } else if (strcmp(id, "wasapi_input_capture") == 0 || strcmp(id, "wasapi_output_capture") == 0 || strcmp(id, "coreaudio_input_capture") == 0 || strcmp(id, "coreaudio_output_capture") == 0 || strcmp(id, "pulse_input_capture") == 0 || strcmp(id, "pulse_output_capture") == 0 || strcmp(id, "alsa_input_capture") == 0) { AudioCaptureToolbar *c = new AudioCaptureToolbar(ui->emptySpace, source); c->Init(); ui->emptySpace->layout()->addWidget(c); } else if (strcmp(id, "wasapi_process_output_capture") == 0) { ApplicationAudioCaptureToolbar *c = new ApplicationAudioCaptureToolbar(ui->emptySpace, source); c->Init(); ui->emptySpace->layout()->addWidget(c); } else if (strcmp(id, "window_capture") == 0 || strcmp(id, "xcomposite_input") == 0) { WindowCaptureToolbar *c = new WindowCaptureToolbar(ui->emptySpace, source); c->Init(); ui->emptySpace->layout()->addWidget(c); } else if (strcmp(id, "monitor_capture") == 0 || strcmp(id, "display_capture") == 0 || strcmp(id, "xshm_input") == 0) { DisplayCaptureToolbar *c = new DisplayCaptureToolbar(ui->emptySpace, source); c->Init(); ui->emptySpace->layout()->addWidget(c); } else if (strcmp(id, "dshow_input") == 0) { DeviceCaptureToolbar *c = new DeviceCaptureToolbar(ui->emptySpace, source); ui->emptySpace->layout()->addWidget(c); } else if (strcmp(id, "game_capture") == 0) { GameCaptureToolbar *c = new GameCaptureToolbar(ui->emptySpace, source); ui->emptySpace->layout()->addWidget(c); } else if (strcmp(id, "image_source") == 0) { ImageSourceToolbar *c = new ImageSourceToolbar(ui->emptySpace, source); ui->emptySpace->layout()->addWidget(c); } else if (strcmp(id, "color_source") == 0) { ColorSourceToolbar *c = new ColorSourceToolbar(ui->emptySpace, source); ui->emptySpace->layout()->addWidget(c); } else if (strcmp(id, "text_ft2_source") == 0 || strcmp(id, "text_gdiplus") == 0) { TextSourceToolbar *c = new TextSourceToolbar(ui->emptySpace, source); ui->emptySpace->layout()->addWidget(c); } } else if (contextBarSize == ContextBarSize_Minimized) { ClearContextBar(); } QIcon icon; if (strcmp(id, "scene") == 0) icon = GetSceneIcon(); else if (strcmp(id, "group") == 0) icon = GetGroupIcon(); else icon = GetSourceIcon(id); QPixmap pixmap = icon.pixmap(QSize(16, 16)); ui->contextSourceIcon->setPixmap(pixmap); ui->contextSourceIconSpacer->hide(); ui->contextSourceIcon->show(); const char *name = obs_source_get_name(source); ui->contextSourceLabel->setText(name); ui->sourceFiltersButton->setEnabled(true); ui->sourcePropertiesButton->setEnabled(obs_source_configurable(source)); } else { ClearContextBar(); ui->contextSourceIcon->hide(); ui->contextSourceIconSpacer->show(); ui->contextSourceLabel->setText(QTStr("ContextBar.NoSelectedSource")); ui->sourceFiltersButton->setEnabled(false); ui->sourcePropertiesButton->setEnabled(false); ui->sourceInteractButton->setVisible(false); } if (contextBarSize == ContextBarSize_Normal) { ui->sourcePropertiesButton->setText(QTStr("Properties")); ui->sourceFiltersButton->setText(QTStr("Filters")); ui->sourceInteractButton->setText(QTStr("Interact")); } else { ui->sourcePropertiesButton->setText(""); ui->sourceFiltersButton->setText(""); ui->sourceInteractButton->setText(""); } } void OBSBasic::ShowContextBar() { on_toggleContextBar_toggled(true); ui->toggleContextBar->setChecked(true); } void OBSBasic::HideContextBar() { on_toggleContextBar_toggled(false); ui->toggleContextBar->setChecked(false); } void OBSBasic::on_toggleContextBar_toggled(bool visible) { config_set_bool(App()->GetUserConfig(), "BasicWindow", "ShowContextToolbars", visible); this->ui->contextContainer->setVisible(visible); UpdateContextBar(true); }