From 52746c25230d4cd724246ea8a56800de675fc341 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Sat, 3 May 2014 22:54:38 -0700 Subject: [PATCH] Add (temporary terrible) volume controls - Add volume control These volume controls are basically nothing more than sliders. They look terrible and hopefully will be as temporary as they are terrible. - Allow saving of specific non-user sources via obs_load_source and obs_save_source functions. - Save data of desktop/mic audio sources (sync data, volume data, etc), and load the data on startup. - Make it so that a scene is created by default if first time using the application. On certain operating systems where supported, a default capture will be created. Desktop capture on mac, particularly. Not sure what to do about windows because monitor capture on windows 7 is completely terrible and is bad to start users off with. --- build/data/obs-studio/locale/en.txt | 16 +- libobs/obs-source.c | 2 +- libobs/obs.c | 59 +- libobs/obs.h | 6 + libobs/util/windows/ComPtr.hpp | 6 + obs/CMakeLists.txt | 2 + obs/forms/OBSBasic.ui | 507 ++++++++++-------- obs/forms/OBSBasicSettings.ui | 6 + obs/volume-control.cpp | 89 +++ obs/volume-control.hpp | 32 ++ obs/window-basic-main.cpp | 153 +++++- obs/window-basic-main.hpp | 23 +- plugins/rtmp-services/rtmp-common.c | 2 +- vs/2013/obs-studio/obs-studio.vcxproj | 27 + vs/2013/obs-studio/obs-studio.vcxproj.filters | 12 + 15 files changed, 688 insertions(+), 254 deletions(-) create mode 100644 obs/volume-control.cpp create mode 100644 obs/volume-control.hpp diff --git a/build/data/obs-studio/locale/en.txt b/build/data/obs-studio/locale/en.txt index 232ea1c2e..fb6368e1e 100644 --- a/build/data/obs-studio/locale/en.txt +++ b/build/data/obs-studio/locale/en.txt @@ -1,5 +1,15 @@ Language="English" +DesktopDevice1="Desktop Audio" +DesktopDevice2="Desktop Audio 2" +AuxDevice1="Mic/Aux" +AuxDevice2="Mic/Aux 2" +AuxDevice3="Mic/Aux 3" +AuxDevice4="Mic/Aux 4" + +Studio.Basic.Scene="Scene" +Studio.Basic.DisplayCapture="Display Capture" + MainMenu.File="File" MainMenu.File.New="New" @@ -64,9 +74,3 @@ Settings.Video.InvalidResolution="Invalid resolution value. Must be [width]x[he Settings.Video.CurrentlyActive="Video output is currently active. Please turn off any outputs to change video settings." Settings.Audio="Audio" -Settings.Audio.DesktopAudioDevice1="Desktop Audio Device 1:" -Settings.Audio.DesktopAudioDevice2="Desktop Audio Device 2:" -Settings.Audio.AuxAudioDevice1="Auxilary Audio Device 1:" -Settings.Audio.AuxAudioDevice2="Auxilary Audio Device 2:" -Settings.Audio.AuxAudioDevice3="Auxilary Audio Device 3:" -Settings.Audio.AuxAudioDevice4="Auxilary Audio Device 4:" diff --git a/libobs/obs-source.c b/libobs/obs-source.c index a8b28b142..620161ccf 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -100,7 +100,7 @@ bool obs_source_init(struct obs_source *source, { source->refs = 1; source->user_volume = 1.0f; - source->present_volume = 1.0f; + source->present_volume = 0.0f; source->sync_offset = 0; pthread_mutex_init_value(&source->filter_mutex); pthread_mutex_init_value(&source->video_mutex); diff --git a/libobs/obs.c b/libobs/obs.c index 645c1246d..c4fcf7407 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -1033,6 +1033,25 @@ float obs_get_present_volume(void) return obs ? obs->audio.present_volume : 0.0f; } +obs_source_t obs_load_source(obs_data_t source_data) +{ + obs_source_t source; + const char *name = obs_data_getstring(source_data, "name"); + const char *id = obs_data_getstring(source_data, "id"); + obs_data_t settings = obs_data_getobj(source_data, "settings"); + double volume; + + source = obs_source_create(OBS_SOURCE_TYPE_INPUT, id, name, settings); + + obs_data_set_default_double(source_data, "volume", 1.0); + volume = obs_data_getdouble(source_data, "volume"); + obs_source_setvolume(source, (float)volume); + + obs_data_release(settings); + + return source; +} + void obs_load_sources(obs_data_array_t array) { size_t count; @@ -1045,19 +1064,12 @@ void obs_load_sources(obs_data_array_t array) pthread_mutex_lock(&obs->data.user_sources_mutex); for (i = 0; i < count; i++) { - obs_data_t source_data = obs_data_array_item(array, i); + obs_data_t source_data = obs_data_array_item(array, i); + obs_source_t source = obs_load_source(source_data); - const char *name = obs_data_getstring(source_data, "name"); - const char *id = obs_data_getstring(source_data, "id"); - obs_data_t settings = obs_data_getobj(source_data, "settings"); - obs_source_t source; - - source = obs_source_create(OBS_SOURCE_TYPE_INPUT, id, name, - settings); obs_add_source(source); - obs_source_release(source); - obs_data_release(settings); + obs_source_release(source); obs_data_release(source_data); } @@ -1068,23 +1080,26 @@ void obs_load_sources(obs_data_array_t array) pthread_mutex_unlock(&obs->data.user_sources_mutex); } -static void save_source_data(obs_data_array_t array, obs_source_t source) +obs_data_t obs_save_source(obs_source_t source) { - obs_data_t source_data = obs_data_create(); - obs_data_t settings = obs_source_getsettings(source); - const char *name = obs_source_getname(source); - const char *id; + obs_data_t source_data = obs_data_create(); + obs_data_t settings = obs_source_getsettings(source); + float volume = obs_source_getvolume(source); + const char *name = obs_source_getname(source); + const char *id; + + obs_source_save(source); obs_source_gettype(source, NULL, &id); obs_data_setstring(source_data, "name", name); obs_data_setstring(source_data, "id", id); obs_data_setobj (source_data, "settings", settings); + obs_data_setdouble(source_data, "volume", volume); - obs_data_array_push_back(array, source_data); - - obs_data_release(source_data); obs_data_release(settings); + + return source_data; } obs_data_array_t obs_save_sources(void) @@ -1099,9 +1114,11 @@ obs_data_array_t obs_save_sources(void) pthread_mutex_lock(&obs->data.user_sources_mutex); for (i = 0; i < obs->data.user_sources.num; i++) { - obs_source_t source = obs->data.user_sources.array[i]; - obs_source_save(source); - save_source_data(array, source); + obs_source_t source = obs->data.user_sources.array[i]; + obs_data_t source_data = obs_save_source(source); + + obs_data_array_push_back(array, source_data); + obs_data_release(source_data); } pthread_mutex_unlock(&obs->data.user_sources_mutex); diff --git a/libobs/obs.h b/libobs/obs.h index 7623c1248..12d68ce43 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -357,6 +357,12 @@ EXPORT float obs_get_master_volume(void); /** Gets the master presentation volume */ EXPORT float obs_get_present_volume(void); +/** Saves a source to settings data */ +EXPORT obs_data_t obs_save_source(obs_source_t source); + +/** Loads a source from settings data */ +EXPORT obs_source_t obs_load_source(obs_data_t data); + /** Loads sources from a data array */ EXPORT void obs_load_sources(obs_data_array_t array); diff --git a/libobs/util/windows/ComPtr.hpp b/libobs/util/windows/ComPtr.hpp index f4fb831a8..38911e5c0 100644 --- a/libobs/util/windows/ComPtr.hpp +++ b/libobs/util/windows/ComPtr.hpp @@ -16,6 +16,9 @@ #pragma once +/* Oh no I have my own com pointer class, the world is ending, how dare you + * write your own! */ + template class ComPtr { T *ptr; @@ -77,6 +80,9 @@ public: inline T *Get() const {return ptr;} + /* nabbed this one from virtualdub */ + inline T **operator~() {return Assign();} + inline operator T*() const {return ptr;} inline T *operator->() const {return ptr;} diff --git a/obs/CMakeLists.txt b/obs/CMakeLists.txt index b0935c7a1..37d40e87e 100644 --- a/obs/CMakeLists.txt +++ b/obs/CMakeLists.txt @@ -59,6 +59,7 @@ set(obs_SOURCES window-basic-properties.cpp window-namedialog.cpp properties-view.cpp + volume-control.cpp qt-wrappers.cpp) set(obs_HEADERS @@ -71,6 +72,7 @@ set(obs_HEADERS window-namedialog.hpp properties-view.hpp display-helpers.hpp + volume-control.hpp qt-display.hpp qt-wrappers.hpp) diff --git a/obs/forms/OBSBasic.ui b/obs/forms/OBSBasic.ui index a0e995981..a457f3f1d 100644 --- a/obs/forms/OBSBasic.ui +++ b/obs/forms/OBSBasic.ui @@ -54,7 +54,7 @@ - 620 + 720 0 @@ -78,225 +78,294 @@ 0 - - - - - Scenes - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - - - - - - 16 - 16 - - - - false - - - - - - - - - - - - - - - - - - - - Sources - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - - - - - - 16 - 16 - - - - false - - - - - - - - - - - - - - - - - - - - Volume - - - - - - - - 0 - 0 - - - - true - - - - - 0 - 0 - 147 - 131 - - - - - 6 - - - 2 - - - 2 - - - 2 - - - 2 - - - - - - - - - + - + 0 0 - 0 + 150 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Scenes + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + + + + + 16 + 16 + + + + false + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Sources + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + + + + + + 16 + 16 + + + + false + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Volume + + + + + + + Qt::ScrollBarAlwaysOn + + + true + + + + + 0 + 0 + 233 + 16 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + 0 + 0 + + + + + 150 0 @@ -446,6 +515,9 @@ + + false + :/res/images/up.ico:/res/images/up.ico @@ -455,6 +527,9 @@ + + false + :/res/images/up.ico:/res/images/up.ico @@ -464,6 +539,9 @@ + + false + :/res/images/down.ico:/res/images/down.ico @@ -473,6 +551,9 @@ + + false + :/res/images/down.ico:/res/images/down.ico diff --git a/obs/forms/OBSBasicSettings.ui b/obs/forms/OBSBasicSettings.ui index e4e928fd0..bfd297e89 100644 --- a/obs/forms/OBSBasicSettings.ui +++ b/obs/forms/OBSBasicSettings.ui @@ -10,6 +10,12 @@ 602 + + + 0 + 0 + + Settings diff --git a/obs/volume-control.cpp b/obs/volume-control.cpp new file mode 100644 index 000000000..3b5e742ca --- /dev/null +++ b/obs/volume-control.cpp @@ -0,0 +1,89 @@ +#include "volume-control.hpp" +#include "qt-wrappers.hpp" +#include +#include +#include +#include +#include + +using namespace std; + +void VolControl::OBSVolumeChanged(void *data, calldata_t calldata) +{ + VolControl *volControl = static_cast(data); + int vol = (int)(calldata_float(calldata, "volume") * 100.0f + 0.5f); + + QMetaObject::invokeMethod(volControl, "VolumeChanged", + Q_ARG(int, vol)); +} + +void VolControl::VolumeChanged(int vol) +{ + signalChanged = false; + slider->setValue(vol); + signalChanged = true; +} + +void VolControl::SliderChanged(int vol) +{ + if (signalChanged) { + signal_handler_disconnect(obs_source_signalhandler(source), + "volume", OBSVolumeChanged, this); + + obs_source_setvolume(source, float(vol)*0.01f); + + signal_handler_connect(obs_source_signalhandler(source), + "volume", OBSVolumeChanged, this); + } + volLabel->setText(QString::number(vol)); +} + +VolControl::VolControl(OBSSource source_) + : source (source_), + signalChanged (true) +{ + QVBoxLayout *mainLayout = new QVBoxLayout(); + QHBoxLayout *textLayout = new QHBoxLayout(); + int vol = int(obs_source_getvolume(source) * 100.0f); + + nameLabel = new QLabel(); + volLabel = new QLabel(); + slider = new QSlider(Qt::Horizontal); + + QFont font = nameLabel->font(); + font.setPointSize(font.pointSize()-1); + + nameLabel->setText(obs_source_getname(source)); + nameLabel->setFont(font); + volLabel->setText(QString::number(vol)); + volLabel->setFont(font); + slider->setMinimum(0); + slider->setMaximum(100); + slider->setValue(vol); + //slider->setMaximumHeight(16); + + textLayout->setContentsMargins(0, 0, 0, 0); + textLayout->addWidget(nameLabel); + textLayout->addWidget(volLabel); + textLayout->setAlignment(nameLabel, Qt::AlignLeft); + textLayout->setAlignment(volLabel, Qt::AlignRight); + + mainLayout->setContentsMargins(4, 4, 4, 4); + mainLayout->setSpacing(2); + mainLayout->addItem(textLayout); + mainLayout->addWidget(slider); + + setLayout(mainLayout); + + signal_handler_connect(obs_source_signalhandler(source), + "volume", OBSVolumeChanged, this); + + QWidget::connect(slider, SIGNAL(valueChanged(int)), + this, SLOT(SliderChanged(int))); +} + +VolControl::~VolControl() +{ + signal_handler_disconnect(obs_source_signalhandler(source), + "volume", OBSVolumeChanged, this); +} diff --git a/obs/volume-control.hpp b/obs/volume-control.hpp new file mode 100644 index 000000000..2e2bef709 --- /dev/null +++ b/obs/volume-control.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +/* TODO: Make a real volume control that isn't terrible */ + +class QLabel; +class QSlider; + +class VolControl : public QWidget { + Q_OBJECT + +private: + OBSSource source; + QLabel *nameLabel; + QLabel *volLabel; + QSlider *slider; + bool signalChanged; + + static void OBSVolumeChanged(void *param, calldata_t calldata); + +private slots: + void VolumeChanged(int vol); + void SliderChanged(int vol); + +public: + VolControl(OBSSource source); + ~VolControl(); + + inline obs_source_t GetSource() const {return source;} +}; diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp index 7d0450157..79cc7a655 100644 --- a/obs/window-basic-main.cpp +++ b/obs/window-basic-main.cpp @@ -32,6 +32,7 @@ #include "window-basic-properties.hpp" #include "qt-wrappers.hpp" #include "display-helpers.hpp" +#include "volume-control.hpp" #include "ui_OBSBasic.h" @@ -47,13 +48,13 @@ Q_DECLARE_METATYPE(OBSSceneItem); OBSBasic::OBSBasic(QWidget *parent) : OBSMainWindow (parent), + properties (nullptr), streamOutput (nullptr), service (nullptr), aac (nullptr), x264 (nullptr), sceneChanging (false), resizeTimer (0), - properties (nullptr), ui (new Ui::OBSBasic) { ui->setupUi(this); @@ -66,6 +67,20 @@ OBSBasic::OBSBasic(QWidget *parent) }); } +static void SaveAudioDevice(const char *name, int channel, obs_data_t parent) +{ + obs_source_t source = obs_get_output_source(channel); + if (!source) + return; + + obs_data_t data = obs_save_source(source); + + obs_data_setobj(parent, name, data); + + obs_data_release(data); + obs_source_release(source); +} + static obs_data_t GenerateSaveData() { obs_data_t saveData = obs_data_create(); @@ -73,6 +88,12 @@ static obs_data_t GenerateSaveData() obs_source_t currentScene = obs_get_output_source(0); const char *sceneName = obs_source_getname(currentScene); + SaveAudioDevice(DESKTOP_AUDIO_1, 1, saveData); + SaveAudioDevice(DESKTOP_AUDIO_2, 2, saveData); + SaveAudioDevice(AUX_AUDIO_1, 3, saveData); + SaveAudioDevice(AUX_AUDIO_2, 4, saveData); + SaveAudioDevice(AUX_AUDIO_3, 5, saveData); + obs_data_setstring(saveData, "current_scene", sceneName); obs_data_setarray(saveData, "sources", sourcesArray); obs_data_array_release(sourcesArray); @@ -81,6 +102,18 @@ static obs_data_t GenerateSaveData() return saveData; } +void OBSBasic::ClearVolumeControls() +{ + VolControl *control; + + for (size_t i = 0; i < volumes.size(); i++) { + control = volumes[i]; + delete control; + } + + volumes.clear(); +} + void OBSBasic::Save(const char *file) { obs_data_t saveData = GenerateSaveData(); @@ -93,6 +126,45 @@ void OBSBasic::Save(const char *file) obs_data_release(saveData); } +static void LoadAudioDevice(const char *name, int channel, obs_data_t parent) +{ + obs_data_t data = obs_data_getobj(parent, name); + if (!data) + return; + + obs_source_t source = obs_load_source(data); + if (source) { + obs_set_output_source(channel, source); + obs_source_release(source); + } + + obs_data_release(data); +} + +void OBSBasic::CreateDefaultScene() +{ + obs_scene_t scene = obs_scene_create(Str("Studio.Basic.Scene")); + obs_source_t source = obs_scene_getsource(scene); + + obs_add_source(source); + +#ifdef __APPLE__ + source = obs_source_create(OBS_SOURCE_TYPE_INPUT, "display_capture", + Str("Studio.Basic.DisplayCapture"), NULL); + + if (source) { + sourceSceneRefs[source] = 0; + + obs_scene_add(scene, source); + obs_add_source(source); + obs_source_release(source); + } +#endif + + obs_set_output_source(0, obs_scene_getsource(scene)); + obs_scene_release(scene); +} + void OBSBasic::Load(const char *file) { if (!file) { @@ -101,14 +173,22 @@ void OBSBasic::Load(const char *file) } BPtr jsonData = os_quick_read_utf8_file(file); - if (!jsonData) + if (!jsonData) { + CreateDefaultScene(); return; + } obs_data_t data = obs_data_create_from_json(jsonData); obs_data_array_t sources = obs_data_getarray(data, "sources"); const char *sceneName = obs_data_getstring(data, "current_scene"); obs_source_t curScene; + LoadAudioDevice(DESKTOP_AUDIO_1, 1, data); + LoadAudioDevice(DESKTOP_AUDIO_2, 2, data); + LoadAudioDevice(AUX_AUDIO_1, 3, data); + LoadAudioDevice(AUX_AUDIO_2, 4, data); + LoadAudioDevice(AUX_AUDIO_3, 5, data); + obs_load_sources(sources); curScene = obs_get_source_by_name(sceneName); @@ -317,8 +397,24 @@ bool OBSBasic::InitBasicConfig() return InitBasicConfigDefaults(); } +void OBSBasic::InitOBSCallbacks() +{ + signal_handler_connect(obs_signalhandler(), "source_add", + OBSBasic::SourceAdded, this); + signal_handler_connect(obs_signalhandler(), "source_remove", + OBSBasic::SourceRemoved, this); + signal_handler_connect(obs_signalhandler(), "channel_change", + OBSBasic::ChannelChanged, this); + signal_handler_connect(obs_signalhandler(), "source_activate", + OBSBasic::SourceActivated, this); + signal_handler_connect(obs_signalhandler(), "source_deactivate", + OBSBasic::SourceDeactivated, this); +} + void OBSBasic::OBSInit() { + BPtr savePath(os_get_config_path("obs-studio/basic/scenes.json")); + /* make sure it's fully displayed before doing any initialization */ show(); App()->processEvents(); @@ -332,12 +428,7 @@ void OBSBasic::OBSInit() if (!ResetAudio()) throw "Failed to initialize audio"; - signal_handler_connect(obs_signalhandler(), "source_add", - OBSBasic::SourceAdded, this); - signal_handler_connect(obs_signalhandler(), "source_remove", - OBSBasic::SourceRemoved, this); - signal_handler_connect(obs_signalhandler(), "channel_change", - OBSBasic::ChannelChanged, this); + InitOBSCallbacks(); /* TODO: this is a test, all modules will be searched for and loaded * automatically later */ @@ -364,9 +455,7 @@ void OBSBasic::OBSInit() if (!InitService()) throw "Failed to initialize service"; - BPtr savePath(os_get_config_path("obs-studio/basic/scenes.json")); Load(savePath); - ResetAudioDevices(); } @@ -381,6 +470,7 @@ OBSBasic::~OBSBasic() /* free the lists before shutting down to remove the scene/item * references */ + ClearVolumeControls(); ui->sources->clear(); ui->scenes->clear(); obs_shutdown(); @@ -519,6 +609,25 @@ void OBSBasic::UpdateSceneSelection(OBSSource source) } } +void OBSBasic::ActivateAudioSource(OBSSource source) +{ + VolControl *vol = new VolControl(source); + + volumes.push_back(vol); + ui->volumeWidgets->layout()->addWidget(vol); +} + +void OBSBasic::DeactivateAudioSource(OBSSource source) +{ + for (size_t i = 0; i < volumes.size(); i++) { + if (volumes[i]->GetSource() == source) { + delete volumes[i]; + volumes.erase(volumes.begin() + i); + break; + } + } +} + /* OBS Callbacks */ void OBSBasic::SceneItemAdded(void *data, calldata_t params) @@ -561,6 +670,28 @@ void OBSBasic::SourceRemoved(void *data, calldata_t params) Q_ARG(OBSSource, OBSSource(source))); } +void OBSBasic::SourceActivated(void *data, calldata_t params) +{ + obs_source_t source = (obs_source_t)calldata_ptr(params, "source"); + uint32_t flags = obs_source_get_output_flags(source); + + if (flags & OBS_SOURCE_AUDIO) + QMetaObject::invokeMethod(static_cast(data), + "ActivateAudioSource", + Q_ARG(OBSSource, OBSSource(source))); +} + +void OBSBasic::SourceDeactivated(void *data, calldata_t params) +{ + obs_source_t source = (obs_source_t)calldata_ptr(params, "source"); + uint32_t flags = obs_source_get_output_flags(source); + + if (flags & OBS_SOURCE_AUDIO) + QMetaObject::invokeMethod(static_cast(data), + "DeactivateAudioSource", + Q_ARG(OBSSource, OBSSource(source))); +} + void OBSBasic::ChannelChanged(void *data, calldata_t params) { obs_source_t source = (obs_source_t)calldata_ptr(params, "source"); @@ -700,7 +831,7 @@ void OBSBasic::ResetAudioDevice(const char *sourceId, const char *deviceName, obs_data_t settings = obs_data_create(); obs_data_setstring(settings, "device_id", deviceId); source = obs_source_create(OBS_SOURCE_TYPE_INPUT, - sourceId, deviceName, settings); + sourceId, Str(deviceName), settings); obs_data_release(settings); obs_set_output_source(channel, source); diff --git a/obs/window-basic-main.hpp b/obs/window-basic-main.hpp index cea1e83db..c43fb05a5 100644 --- a/obs/window-basic-main.hpp +++ b/obs/window-basic-main.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include "window-main.hpp" #include "window-basic-properties.hpp" @@ -28,15 +29,26 @@ #include class QListWidgetItem; +class VolControl; #include "ui_OBSBasic.h" +#define DESKTOP_AUDIO_1 Str("DesktopAudioDevice1") +#define DESKTOP_AUDIO_2 Str("DesktopAudioDevice2") +#define AUX_AUDIO_1 Str("AuxAudioDevice1") +#define AUX_AUDIO_2 Str("AuxAudioDevice2") +#define AUX_AUDIO_3 Str("AuxAudioDevice3") + class OBSBasic : public OBSMainWindow { Q_OBJECT private: std::unordered_map sourceSceneRefs; + std::vector volumes; + + QPointer properties; + obs_output_t streamOutput; obs_service_t service; obs_encoder_t aac; @@ -50,7 +62,9 @@ private: ConfigFile basicConfig; - QPointer properties; + void CreateDefaultScene(); + + void ClearVolumeControls(); void Save(const char *file); void Load(const char *file); @@ -65,6 +79,8 @@ private: bool InitBasicConfigDefaults(); bool InitBasicConfig(); + void InitOBSCallbacks(); + OBSScene GetCurrentScene(); OBSSceneItem GetCurrentSceneItem(); @@ -92,12 +108,17 @@ private slots: void RemoveScene(OBSSource source); void UpdateSceneSelection(OBSSource source); + void ActivateAudioSource(OBSSource source); + void DeactivateAudioSource(OBSSource source); + private: /* OBS Callbacks */ static void SceneItemAdded(void *data, calldata_t params); static void SceneItemRemoved(void *data, calldata_t params); static void SourceAdded(void *data, calldata_t params); static void SourceRemoved(void *data, calldata_t params); + static void SourceActivated(void *data, calldata_t params); + static void SourceDeactivated(void *data, calldata_t params); static void ChannelChanged(void *data, calldata_t params); static void RenderMain(void *data, uint32_t cx, uint32_t cy); diff --git a/plugins/rtmp-services/rtmp-common.c b/plugins/rtmp-services/rtmp-common.c index fa213d805..4cadb990d 100644 --- a/plugins/rtmp-services/rtmp-common.c +++ b/plugins/rtmp-services/rtmp-common.c @@ -13,7 +13,7 @@ static const char *rtmp_common_getname(const char *locale) UNUSED_PARAMETER(locale); /* TODO: locale */ - return "Other Streaming Services"; + return "Streaming Services"; } static void rtmp_common_update(void *data, obs_data_t settings) diff --git a/vs/2013/obs-studio/obs-studio.vcxproj b/vs/2013/obs-studio/obs-studio.vcxproj index eb2e80bab..bca644cd7 100644 --- a/vs/2013/obs-studio/obs-studio.vcxproj +++ b/vs/2013/obs-studio/obs-studio.vcxproj @@ -131,6 +131,24 @@ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\..\..\..\libobs" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I.\..\..\..\obs" + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing volume-control.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\..\..\..\libobs" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I.\..\..\..\obs" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing volume-control.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\..\..\..\libobs" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I.\..\..\..\obs" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing volume-control.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\..\..\..\libobs" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I.\..\..\..\obs" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing volume-control.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\..\..\..\libobs" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I.\..\..\..\obs" + @@ -177,6 +195,7 @@ + @@ -193,6 +212,10 @@ true true + + true + true + true true @@ -235,6 +258,10 @@ true true + + true + true + true true diff --git a/vs/2013/obs-studio/obs-studio.vcxproj.filters b/vs/2013/obs-studio/obs-studio.vcxproj.filters index fa7d69938..c91cf97ae 100644 --- a/vs/2013/obs-studio/obs-studio.vcxproj.filters +++ b/vs/2013/obs-studio/obs-studio.vcxproj.filters @@ -74,6 +74,9 @@ Header Files + + Header Files + @@ -177,6 +180,15 @@ Source Files + + Generated Files\Debug + + + Generated Files\Release + + + Source Files +