2013-11-07 15:45:03 -08:00
|
|
|
/******************************************************************************
|
2015-02-19 11:02:54 -08:00
|
|
|
Copyright (C) 2013-2015 by Hugh Bailey <obs.jim@gmail.com>
|
2014-05-15 14:04:18 -07:00
|
|
|
Zachary Lund <admin@computerquip.com>
|
2015-02-19 11:02:54 -08:00
|
|
|
Philippe Groarke <philippe.groarke@gmail.com>
|
2013-11-07 15:45:03 -08:00
|
|
|
|
|
|
|
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
|
2013-12-02 21:24:38 -08:00
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
2013-11-07 15:45:03 -08:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
2013-11-08 23:19:38 -08:00
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2013-11-07 15:45:03 -08:00
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
******************************************************************************/
|
|
|
|
|
2014-07-13 23:56:28 -07:00
|
|
|
#include <time.h>
|
2013-12-22 16:42:02 -08:00
|
|
|
#include <obs.hpp>
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
#include <QMessageBox>
|
2014-01-25 08:08:56 -08:00
|
|
|
#include <QShowEvent>
|
2014-08-21 18:18:42 -07:00
|
|
|
#include <QDesktopServices>
|
2014-02-10 09:22:35 -08:00
|
|
|
#include <QFileDialog>
|
2013-12-29 08:17:00 -08:00
|
|
|
|
2014-05-18 17:44:10 -07:00
|
|
|
#include <util/dstr.h>
|
2014-03-06 20:08:12 -08:00
|
|
|
#include <util/util.hpp>
|
|
|
|
#include <util/platform.h>
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
#include <graphics/math-defs.h>
|
2014-03-06 20:08:12 -08:00
|
|
|
|
2013-11-23 22:38:52 -08:00
|
|
|
#include "obs-app.hpp"
|
2014-03-06 20:08:12 -08:00
|
|
|
#include "platform.hpp"
|
2015-03-22 20:51:21 -07:00
|
|
|
#include "visibility-item-widget.hpp"
|
2015-06-27 18:18:40 -07:00
|
|
|
#include "item-widget-helpers.hpp"
|
2014-01-24 20:19:50 -08:00
|
|
|
#include "window-basic-settings.hpp"
|
2013-12-29 07:54:06 -08:00
|
|
|
#include "window-namedialog.hpp"
|
2014-05-10 18:47:48 -07:00
|
|
|
#include "window-basic-source-select.hpp"
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
#include "window-basic-main.hpp"
|
2015-02-06 03:17:33 -08:00
|
|
|
#include "window-basic-main-outputs.hpp"
|
2014-03-23 01:07:54 -07:00
|
|
|
#include "window-basic-properties.hpp"
|
2014-05-18 17:44:10 -07:00
|
|
|
#include "window-log-reply.hpp"
|
2015-04-04 01:40:15 -07:00
|
|
|
#include "window-projector.hpp"
|
2014-09-02 19:11:55 -07:00
|
|
|
#include "window-remux.hpp"
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
#include "qt-wrappers.hpp"
|
2014-03-23 01:07:54 -07:00
|
|
|
#include "display-helpers.hpp"
|
2014-05-03 22:54:38 -07:00
|
|
|
#include "volume-control.hpp"
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
#include "remote-text.hpp"
|
2014-01-04 12:53:36 -08:00
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
#include "ui_OBSBasic.h"
|
2014-01-09 17:51:51 -08:00
|
|
|
|
2014-05-18 17:44:10 -07:00
|
|
|
#include <fstream>
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
#include <sstream>
|
|
|
|
|
2014-04-16 13:35:01 -07:00
|
|
|
#include <QScreen>
|
|
|
|
#include <QWindow>
|
|
|
|
|
2014-06-15 19:48:02 -07:00
|
|
|
#define PREVIEW_EDGE_SIZE 10
|
|
|
|
|
2013-12-29 07:54:06 -08:00
|
|
|
using namespace std;
|
2013-11-22 15:20:52 -08:00
|
|
|
|
2014-02-02 13:26:23 -08:00
|
|
|
Q_DECLARE_METATYPE(OBSScene);
|
|
|
|
Q_DECLARE_METATYPE(OBSSceneItem);
|
2014-10-29 07:53:59 -07:00
|
|
|
Q_DECLARE_METATYPE(OBSSource);
|
2014-08-02 01:33:53 -07:00
|
|
|
Q_DECLARE_METATYPE(obs_order_movement);
|
2015-06-27 00:28:40 -07:00
|
|
|
Q_DECLARE_METATYPE(std::vector<std::shared_ptr<OBSSignal>>);
|
2014-02-02 13:26:23 -08:00
|
|
|
|
2015-06-27 18:21:45 -07:00
|
|
|
template <typename T>
|
|
|
|
static T GetOBSRef(QListWidgetItem *item)
|
|
|
|
{
|
|
|
|
return item->data(static_cast<int>(QtDataRole::OBSRef)).value<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
static void SetOBSRef(QListWidgetItem *item, T &&val)
|
|
|
|
{
|
|
|
|
item->setData(static_cast<int>(QtDataRole::OBSRef),
|
|
|
|
QVariant::fromValue(val));
|
|
|
|
}
|
|
|
|
|
2014-07-27 12:48:14 -07:00
|
|
|
static void AddExtraModulePaths()
|
|
|
|
{
|
2015-01-15 23:44:38 -08:00
|
|
|
char base_module_dir[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
int ret = GetConfigPath(base_module_dir, sizeof(base_module_dir),
|
2015-01-15 23:44:38 -08:00
|
|
|
"obs-studio/plugins/%module%");
|
2014-08-31 07:28:36 -07:00
|
|
|
|
2015-01-15 23:44:38 -08:00
|
|
|
if (ret <= 0)
|
2014-07-27 12:48:14 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
string path = (char*)base_module_dir;
|
|
|
|
obs_add_module_path((path + "/bin").c_str(), (path + "/data").c_str());
|
|
|
|
}
|
|
|
|
|
2014-10-15 13:00:43 -07:00
|
|
|
static QList<QKeySequence> DeleteKeys;
|
|
|
|
|
2014-02-02 14:23:38 -08:00
|
|
|
OBSBasic::OBSBasic(QWidget *parent)
|
2014-05-20 23:27:27 -07:00
|
|
|
: OBSMainWindow (parent),
|
2014-05-18 17:44:10 -07:00
|
|
|
ui (new Ui::OBSBasic)
|
2014-02-02 14:23:38 -08:00
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
2015-04-02 21:35:46 -07:00
|
|
|
ui->previewDisabledLabel->setVisible(false);
|
|
|
|
|
2015-02-16 23:45:34 -08:00
|
|
|
copyActionsDynamicProperties();
|
2014-04-16 13:35:01 -07:00
|
|
|
|
2015-03-22 20:51:21 -07:00
|
|
|
ui->sources->setItemDelegate(new VisibilityItemDelegate(ui->sources));
|
|
|
|
|
2015-04-02 18:10:06 -07:00
|
|
|
int width = config_get_int(App()->GlobalConfig(), "BasicWindow", "cx");
|
2015-02-12 20:49:23 -08:00
|
|
|
|
|
|
|
// Check if no values are saved (new installation).
|
|
|
|
if (width != 0) {
|
2015-04-02 18:10:06 -07:00
|
|
|
int height = config_get_int(App()->GlobalConfig(),
|
|
|
|
"BasicWindow", "cy");
|
|
|
|
int posx = config_get_int(App()->GlobalConfig(), "BasicWindow",
|
2015-02-12 20:49:23 -08:00
|
|
|
"posx");
|
2015-04-02 18:10:06 -07:00
|
|
|
int posy = config_get_int(App()->GlobalConfig(), "BasicWindow",
|
2015-02-12 20:49:23 -08:00
|
|
|
"posy");
|
|
|
|
|
2015-03-25 11:31:21 -07:00
|
|
|
setGeometry(posx, posy, width, height);
|
2015-02-12 20:49:23 -08:00
|
|
|
}
|
|
|
|
|
2015-01-16 00:06:54 -08:00
|
|
|
char styleSheetPath[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
int ret = GetConfigPath(styleSheetPath, sizeof(styleSheetPath),
|
2015-01-16 00:06:54 -08:00
|
|
|
"obs-studio/basic/stylesheet.qss");
|
|
|
|
if (ret > 0) {
|
2015-01-17 09:24:00 -08:00
|
|
|
if (QFile::exists(styleSheetPath)) {
|
|
|
|
QString path = QString("file:///") +
|
|
|
|
QT_UTF8(styleSheetPath);
|
|
|
|
App()->setStyleSheet(path);
|
|
|
|
}
|
2015-01-16 00:06:54 -08:00
|
|
|
}
|
|
|
|
|
2014-10-29 07:54:45 -07:00
|
|
|
qRegisterMetaType<OBSScene> ("OBSScene");
|
|
|
|
qRegisterMetaType<OBSSceneItem>("OBSSceneItem");
|
|
|
|
qRegisterMetaType<OBSSource> ("OBSSource");
|
2014-11-01 13:48:58 -07:00
|
|
|
qRegisterMetaType<obs_hotkey_id>("obs_hotkey_id");
|
2014-10-29 07:54:45 -07:00
|
|
|
|
2015-06-26 19:06:34 -07:00
|
|
|
qRegisterMetaTypeStreamOperators<
|
|
|
|
std::vector<std::shared_ptr<OBSSignal>>>(
|
|
|
|
"std::vector<std::shared_ptr<OBSSignal>>");
|
2015-06-27 01:48:58 -07:00
|
|
|
qRegisterMetaTypeStreamOperators<OBSScene>("OBSScene");
|
2015-06-26 18:39:39 -07:00
|
|
|
qRegisterMetaTypeStreamOperators<OBSSceneItem>("OBSSceneItem");
|
2015-06-27 01:48:58 -07:00
|
|
|
|
2014-10-29 09:18:00 -07:00
|
|
|
ui->scenes->setAttribute(Qt::WA_MacShowFocusRect, false);
|
|
|
|
ui->sources->setAttribute(Qt::WA_MacShowFocusRect, false);
|
|
|
|
|
2014-04-16 13:35:01 -07:00
|
|
|
connect(windowHandle(), &QWindow::screenChanged, [this]() {
|
|
|
|
struct obs_video_info ovi;
|
|
|
|
|
|
|
|
if (obs_get_video_info(&ovi))
|
|
|
|
ResizePreview(ovi.base_width, ovi.base_height);
|
|
|
|
});
|
2014-05-15 14:04:18 -07:00
|
|
|
|
|
|
|
stringstream name;
|
|
|
|
name << "OBS " << App()->GetVersionString();
|
|
|
|
|
2014-11-01 13:48:58 -07:00
|
|
|
installEventFilter(CreateShortcutFilter());
|
|
|
|
|
2014-05-18 17:44:10 -07:00
|
|
|
blog(LOG_INFO, "%s", name.str().c_str());
|
2014-05-15 14:04:18 -07:00
|
|
|
setWindowTitle(QT_UTF8(name.str().c_str()));
|
2014-06-30 00:06:01 -07:00
|
|
|
|
|
|
|
connect(ui->scenes->itemDelegate(),
|
|
|
|
SIGNAL(closeEditor(QWidget*,
|
|
|
|
QAbstractItemDelegate::EndEditHint)),
|
|
|
|
this,
|
|
|
|
SLOT(SceneNameEdited(QWidget*,
|
|
|
|
QAbstractItemDelegate::EndEditHint)));
|
|
|
|
|
|
|
|
connect(ui->sources->itemDelegate(),
|
|
|
|
SIGNAL(closeEditor(QWidget*,
|
|
|
|
QAbstractItemDelegate::EndEditHint)),
|
|
|
|
this,
|
|
|
|
SLOT(SceneItemNameEdited(QWidget*,
|
|
|
|
QAbstractItemDelegate::EndEditHint)));
|
2014-07-06 16:18:16 -07:00
|
|
|
|
|
|
|
cpuUsageInfo = os_cpu_usage_info_start();
|
2014-07-06 16:19:27 -07:00
|
|
|
cpuUsageTimer = new QTimer(this);
|
|
|
|
connect(cpuUsageTimer, SIGNAL(timeout()),
|
|
|
|
ui->statusbar, SLOT(UpdateCPUUsage()));
|
|
|
|
cpuUsageTimer->start(3000);
|
2014-07-13 12:46:23 -07:00
|
|
|
|
2014-10-15 13:00:43 -07:00
|
|
|
DeleteKeys =
|
|
|
|
#ifdef __APPLE__
|
|
|
|
QList<QKeySequence>{{Qt::Key_Backspace}} <<
|
|
|
|
#endif
|
|
|
|
QKeySequence::keyBindings(QKeySequence::Delete);
|
|
|
|
|
2014-07-13 12:46:23 -07:00
|
|
|
#ifdef __APPLE__
|
2014-10-15 13:03:22 -07:00
|
|
|
ui->actionRemoveSource->setShortcuts(DeleteKeys);
|
|
|
|
ui->actionRemoveScene->setShortcuts(DeleteKeys);
|
2014-07-20 18:06:02 -07:00
|
|
|
|
|
|
|
ui->action_Settings->setMenuRole(QAction::PreferencesRole);
|
|
|
|
ui->actionE_xit->setMenuRole(QAction::QuitRole);
|
2014-07-13 12:46:23 -07:00
|
|
|
#endif
|
2015-04-02 23:09:13 -07:00
|
|
|
|
|
|
|
auto addNudge = [this](const QKeySequence &seq, const char *s)
|
|
|
|
{
|
|
|
|
QAction *nudge = new QAction(ui->preview);
|
|
|
|
nudge->setShortcut(seq);
|
|
|
|
nudge->setShortcutContext(Qt::WidgetShortcut);
|
|
|
|
ui->preview->addAction(nudge);
|
|
|
|
connect(nudge, SIGNAL(triggered()), this, s);
|
|
|
|
};
|
|
|
|
|
|
|
|
addNudge(Qt::Key_Up, SLOT(NudgeUp()));
|
|
|
|
addNudge(Qt::Key_Down, SLOT(NudgeDown()));
|
|
|
|
addNudge(Qt::Key_Left, SLOT(NudgeLeft()));
|
|
|
|
addNudge(Qt::Key_Right, SLOT(NudgeRight()));
|
2014-02-02 14:23:38 -08:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
static void SaveAudioDevice(const char *name, int channel, obs_data_t *parent)
|
2014-05-03 22:54:38 -07:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_get_output_source(channel);
|
2014-05-03 22:54:38 -07:00
|
|
|
if (!source)
|
|
|
|
return;
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_data_t *data = obs_save_source(source);
|
2014-05-03 22:54:38 -07:00
|
|
|
|
2014-08-05 11:09:29 -07:00
|
|
|
obs_data_set_obj(parent, name, data);
|
2014-05-03 22:54:38 -07:00
|
|
|
|
|
|
|
obs_data_release(data);
|
|
|
|
obs_source_release(source);
|
|
|
|
}
|
|
|
|
|
2015-06-25 03:53:48 -07:00
|
|
|
static obs_data_t *GenerateSaveData(obs_data_array_t *sceneOrder)
|
2014-04-26 23:47:50 -07:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_data_t *saveData = obs_data_create();
|
|
|
|
obs_data_array_t *sourcesArray = obs_save_sources();
|
|
|
|
obs_source_t *currentScene = obs_get_output_source(0);
|
2014-08-04 08:41:15 -07:00
|
|
|
const char *sceneName = obs_source_get_name(currentScene);
|
2014-04-26 23:47:50 -07:00
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
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);
|
|
|
|
|
2014-08-05 11:09:29 -07:00
|
|
|
obs_data_set_string(saveData, "current_scene", sceneName);
|
2015-06-25 03:53:48 -07:00
|
|
|
obs_data_set_array(saveData, "scene_order", sceneOrder);
|
2014-08-05 11:09:29 -07:00
|
|
|
obs_data_set_array(saveData, "sources", sourcesArray);
|
2014-04-26 23:47:50 -07:00
|
|
|
obs_data_array_release(sourcesArray);
|
|
|
|
obs_source_release(currentScene);
|
|
|
|
|
|
|
|
return saveData;
|
|
|
|
}
|
|
|
|
|
2015-02-16 23:45:34 -08:00
|
|
|
void OBSBasic::copyActionsDynamicProperties()
|
|
|
|
{
|
|
|
|
// Themes need the QAction dynamic properties
|
|
|
|
for (QAction *x : ui->scenesToolbar->actions()) {
|
|
|
|
QWidget* temp = ui->scenesToolbar->widgetForAction(x);
|
|
|
|
|
|
|
|
for (QByteArray &y : x->dynamicPropertyNames()) {
|
|
|
|
temp->setProperty(y, x->property(y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (QAction *x : ui->sourcesToolbar->actions()) {
|
|
|
|
QWidget* temp = ui->sourcesToolbar->widgetForAction(x);
|
|
|
|
|
|
|
|
for (QByteArray &y : x->dynamicPropertyNames()) {
|
|
|
|
temp->setProperty(y, x->property(y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
void OBSBasic::ClearVolumeControls()
|
|
|
|
{
|
|
|
|
VolControl *control;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < volumes.size(); i++) {
|
|
|
|
control = volumes[i];
|
|
|
|
delete control;
|
|
|
|
}
|
|
|
|
|
|
|
|
volumes.clear();
|
|
|
|
}
|
|
|
|
|
2015-06-25 03:53:48 -07:00
|
|
|
obs_data_array_t *OBSBasic::SaveSceneListOrder()
|
|
|
|
{
|
|
|
|
obs_data_array_t *sceneOrder = obs_data_array_create();
|
|
|
|
|
|
|
|
for (int i = 0; i < ui->scenes->count(); i++) {
|
|
|
|
obs_data_t *data = obs_data_create();
|
|
|
|
obs_data_set_string(data, "name",
|
|
|
|
QT_TO_UTF8(ui->scenes->item(i)->text()));
|
|
|
|
obs_data_array_push_back(sceneOrder, data);
|
|
|
|
obs_data_release(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sceneOrder;
|
|
|
|
}
|
|
|
|
|
2014-04-26 23:47:50 -07:00
|
|
|
void OBSBasic::Save(const char *file)
|
|
|
|
{
|
2015-06-25 03:53:48 -07:00
|
|
|
obs_data_array_t *sceneOrder = SaveSceneListOrder();
|
|
|
|
obs_data_t *saveData = GenerateSaveData(sceneOrder);
|
2014-08-05 11:09:29 -07:00
|
|
|
const char *jsonData = obs_data_get_json(saveData);
|
2014-04-26 23:47:50 -07:00
|
|
|
|
2015-02-12 21:11:12 -08:00
|
|
|
if (!!jsonData) {
|
|
|
|
/* TODO: maybe a message box here? */
|
|
|
|
bool success = os_quick_write_utf8_file(file, jsonData,
|
|
|
|
strlen(jsonData), false);
|
|
|
|
if (!success)
|
|
|
|
blog(LOG_ERROR, "Could not save scene data to %s",
|
|
|
|
file);
|
|
|
|
}
|
2014-04-26 23:47:50 -07:00
|
|
|
|
|
|
|
obs_data_release(saveData);
|
2015-06-25 03:53:48 -07:00
|
|
|
obs_data_array_release(sceneOrder);
|
2014-04-26 23:47:50 -07:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
static void LoadAudioDevice(const char *name, int channel, obs_data_t *parent)
|
2014-05-03 22:54:38 -07:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_data_t *data = obs_data_get_obj(parent, name);
|
2014-05-03 22:54:38 -07:00
|
|
|
if (!data)
|
|
|
|
return;
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_load_source(data);
|
2014-05-03 22:54:38 -07:00
|
|
|
if (source) {
|
|
|
|
obs_set_output_source(channel, source);
|
|
|
|
obs_source_release(source);
|
|
|
|
}
|
|
|
|
|
|
|
|
obs_data_release(data);
|
|
|
|
}
|
|
|
|
|
2015-06-23 18:47:22 -07:00
|
|
|
static inline bool HasAudioDevices(const char *source_id)
|
|
|
|
{
|
|
|
|
const char *output_id = source_id;
|
|
|
|
obs_properties_t *props = obs_get_source_properties(
|
|
|
|
OBS_SOURCE_TYPE_INPUT, output_id);
|
|
|
|
size_t count = 0;
|
|
|
|
|
|
|
|
if (!props)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
obs_property_t *devices = obs_properties_get(props, "device_id");
|
|
|
|
if (devices)
|
|
|
|
count = obs_property_list_item_count(devices);
|
|
|
|
|
|
|
|
obs_properties_destroy(props);
|
|
|
|
|
|
|
|
return count != 0;
|
|
|
|
}
|
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
void OBSBasic::CreateDefaultScene()
|
|
|
|
{
|
2015-06-30 05:49:31 -07:00
|
|
|
disableSaving++;
|
|
|
|
|
2015-06-23 18:47:22 -07:00
|
|
|
bool hasDesktopAudio = HasAudioDevices(App()->OutputAudioSource());
|
|
|
|
bool hasInputAudio = HasAudioDevices(App()->InputAudioSource());
|
|
|
|
|
2015-07-02 16:17:55 -07:00
|
|
|
ClearSceneData();
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_scene_t *scene = obs_scene_create(Str("Basic.Scene"));
|
|
|
|
obs_source_t *source = obs_scene_get_source(scene);
|
2014-05-03 22:54:38 -07:00
|
|
|
|
|
|
|
obs_add_source(source);
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
source = obs_source_create(OBS_SOURCE_TYPE_INPUT, "display_capture",
|
2014-11-01 13:41:17 -07:00
|
|
|
Str("Basic.DisplayCapture"), NULL, nullptr);
|
2014-05-03 22:54:38 -07:00
|
|
|
|
|
|
|
if (source) {
|
|
|
|
obs_scene_add(scene, source);
|
|
|
|
obs_add_source(source);
|
|
|
|
obs_source_release(source);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-08-04 08:41:15 -07:00
|
|
|
obs_set_output_source(0, obs_scene_get_source(scene));
|
2014-05-03 22:54:38 -07:00
|
|
|
obs_scene_release(scene);
|
2015-06-23 18:47:22 -07:00
|
|
|
|
|
|
|
if (hasDesktopAudio)
|
|
|
|
ResetAudioDevice(App()->OutputAudioSource(), "default",
|
|
|
|
Str("Basic.DesktopDevice1"), 1);
|
|
|
|
if (hasInputAudio)
|
|
|
|
ResetAudioDevice(App()->InputAudioSource(), "default",
|
|
|
|
Str("Basic.AuxDevice1"), 3);
|
2015-06-30 05:49:31 -07:00
|
|
|
|
|
|
|
disableSaving--;
|
2014-05-03 22:54:38 -07:00
|
|
|
}
|
|
|
|
|
2015-06-25 03:53:48 -07:00
|
|
|
static void ReorderItemByName(QListWidget *lw, const char *name, int newIndex)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < lw->count(); i++) {
|
|
|
|
QListWidgetItem *item = lw->item(i);
|
|
|
|
|
|
|
|
if (strcmp(name, QT_TO_UTF8(item->text())) == 0) {
|
|
|
|
if (newIndex != i) {
|
|
|
|
item = lw->takeItem(i);
|
|
|
|
lw->insertItem(newIndex, item);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::LoadSceneListOrder(obs_data_array_t *array)
|
|
|
|
{
|
|
|
|
size_t num = obs_data_array_count(array);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < num; i++) {
|
|
|
|
obs_data_t *data = obs_data_array_item(array, i);
|
|
|
|
const char *name = obs_data_get_string(data, "name");
|
|
|
|
|
|
|
|
ReorderItemByName(ui->scenes, name, (int)i);
|
|
|
|
|
|
|
|
obs_data_release(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-26 23:47:50 -07:00
|
|
|
void OBSBasic::Load(const char *file)
|
|
|
|
{
|
|
|
|
if (!file) {
|
|
|
|
blog(LOG_ERROR, "Could not find file %s", file);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BPtr<char> jsonData = os_quick_read_utf8_file(file);
|
2014-05-03 22:54:38 -07:00
|
|
|
if (!jsonData) {
|
|
|
|
CreateDefaultScene();
|
2015-07-02 16:15:51 -07:00
|
|
|
SaveProject();
|
2014-04-26 23:47:50 -07:00
|
|
|
return;
|
2014-05-03 22:54:38 -07:00
|
|
|
}
|
2014-04-26 23:47:50 -07:00
|
|
|
|
2015-06-30 05:49:31 -07:00
|
|
|
disableSaving++;
|
|
|
|
|
2015-07-02 16:17:55 -07:00
|
|
|
ClearSceneData();
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_data_t *data = obs_data_create_from_json(jsonData);
|
2015-06-25 03:53:48 -07:00
|
|
|
obs_data_array_t *sceneOrder = obs_data_get_array(data, "scene_order");
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_data_array_t *sources = obs_data_get_array(data, "sources");
|
2014-08-05 11:09:29 -07:00
|
|
|
const char *sceneName = obs_data_get_string(data,
|
|
|
|
"current_scene");
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *curScene;
|
2014-04-26 23:47:50 -07:00
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
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);
|
|
|
|
|
2014-04-26 23:47:50 -07:00
|
|
|
obs_load_sources(sources);
|
|
|
|
|
2015-06-25 03:53:48 -07:00
|
|
|
if (sceneOrder)
|
|
|
|
LoadSceneListOrder(sceneOrder);
|
|
|
|
|
2014-04-26 23:47:50 -07:00
|
|
|
curScene = obs_get_source_by_name(sceneName);
|
|
|
|
obs_set_output_source(0, curScene);
|
|
|
|
obs_source_release(curScene);
|
|
|
|
|
|
|
|
obs_data_array_release(sources);
|
2015-06-25 03:53:48 -07:00
|
|
|
obs_data_array_release(sceneOrder);
|
2014-04-26 23:47:50 -07:00
|
|
|
obs_data_release(data);
|
2015-06-30 05:49:31 -07:00
|
|
|
|
|
|
|
disableSaving--;
|
2014-04-26 23:47:50 -07:00
|
|
|
}
|
|
|
|
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
#define SERVICE_PATH "obs-studio/basic/service.json"
|
|
|
|
|
|
|
|
void OBSBasic::SaveService()
|
|
|
|
{
|
|
|
|
if (!service)
|
|
|
|
return;
|
|
|
|
|
2015-01-15 23:44:38 -08:00
|
|
|
char serviceJsonPath[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
int ret = GetConfigPath(serviceJsonPath, sizeof(serviceJsonPath),
|
2015-01-15 23:44:38 -08:00
|
|
|
SERVICE_PATH);
|
|
|
|
if (ret <= 0)
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
return;
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_data_t *data = obs_data_create();
|
|
|
|
obs_data_t *settings = obs_service_get_settings(service);
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
|
2015-02-07 08:19:34 -08:00
|
|
|
obs_data_set_string(data, "type", obs_service_get_type(service));
|
2014-08-05 11:09:29 -07:00
|
|
|
obs_data_set_obj(data, "settings", settings);
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
|
2014-08-05 11:09:29 -07:00
|
|
|
const char *json = obs_data_get_json(data);
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
|
|
|
|
os_quick_write_utf8_file(serviceJsonPath, json, strlen(json), false);
|
|
|
|
|
|
|
|
obs_data_release(settings);
|
|
|
|
obs_data_release(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OBSBasic::LoadService()
|
|
|
|
{
|
|
|
|
const char *type;
|
|
|
|
|
2015-01-15 23:44:38 -08:00
|
|
|
char serviceJsonPath[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
int ret = GetConfigPath(serviceJsonPath, sizeof(serviceJsonPath),
|
2015-01-15 23:44:38 -08:00
|
|
|
SERVICE_PATH);
|
|
|
|
if (ret <= 0)
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
return false;
|
|
|
|
|
|
|
|
BPtr<char> jsonText = os_quick_read_utf8_file(serviceJsonPath);
|
|
|
|
if (!jsonText)
|
|
|
|
return false;
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_data_t *data = obs_data_create_from_json(jsonText);
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
|
|
|
|
obs_data_set_default_string(data, "type", "rtmp_common");
|
2014-08-05 11:09:29 -07:00
|
|
|
type = obs_data_get_string(data, "type");
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_data_t *settings = obs_data_get_obj(data, "settings");
|
2015-04-04 15:03:40 -07:00
|
|
|
obs_data_t *hotkey_data = obs_data_get_obj(data, "hotkeys");
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
|
2014-11-01 13:41:17 -07:00
|
|
|
service = obs_service_create(type, "default_service", settings,
|
2015-04-04 15:03:40 -07:00
|
|
|
hotkey_data);
|
2015-05-03 17:07:43 -07:00
|
|
|
obs_service_release(service);
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
|
2015-04-04 15:03:40 -07:00
|
|
|
obs_data_release(hotkey_data);
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
obs_data_release(settings);
|
|
|
|
obs_data_release(data);
|
|
|
|
|
|
|
|
return !!service;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OBSBasic::InitService()
|
|
|
|
{
|
|
|
|
if (LoadService())
|
|
|
|
return true;
|
|
|
|
|
2014-11-01 13:41:17 -07:00
|
|
|
service = obs_service_create("rtmp_common", "default_service", nullptr,
|
|
|
|
nullptr);
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
if (!service)
|
|
|
|
return false;
|
2015-05-03 17:07:43 -07:00
|
|
|
obs_service_release(service);
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-03-06 20:08:12 -08:00
|
|
|
bool OBSBasic::InitBasicConfigDefaults()
|
|
|
|
{
|
|
|
|
vector<MonitorInfo> monitors;
|
|
|
|
GetMonitors(monitors);
|
|
|
|
|
|
|
|
if (!monitors.size()) {
|
|
|
|
OBSErrorBox(NULL, "There appears to be no monitors. Er, this "
|
|
|
|
"technically shouldn't be possible.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t cx = monitors[0].cx;
|
|
|
|
uint32_t cy = monitors[0].cy;
|
|
|
|
|
2015-06-25 01:06:46 -07:00
|
|
|
config_set_default_string(basicConfig, "Output", "Mode", "Simple");
|
2015-02-06 03:17:33 -08:00
|
|
|
|
2014-05-20 23:27:27 -07:00
|
|
|
config_set_default_string(basicConfig, "SimpleOutput", "FilePath",
|
|
|
|
GetDefaultVideoSavePath().c_str());
|
2015-05-29 09:45:54 -07:00
|
|
|
config_set_default_string(basicConfig, "SimpleOutput", "RecFormat",
|
|
|
|
"flv");
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
config_set_default_uint (basicConfig, "SimpleOutput", "VBitrate",
|
|
|
|
2500);
|
2015-06-05 08:57:01 -07:00
|
|
|
config_set_default_uint (basicConfig, "SimpleOutput", "ABitrate", 160);
|
2014-07-03 18:07:33 -07:00
|
|
|
config_set_default_bool (basicConfig, "SimpleOutput", "Reconnect",
|
|
|
|
true);
|
2015-03-07 10:06:52 -08:00
|
|
|
config_set_default_uint (basicConfig, "SimpleOutput", "RetryDelay",
|
|
|
|
10);
|
2014-07-03 18:07:33 -07:00
|
|
|
config_set_default_uint (basicConfig, "SimpleOutput", "MaxRetries",
|
|
|
|
20);
|
2014-08-25 07:48:51 -07:00
|
|
|
config_set_default_bool (basicConfig, "SimpleOutput", "UseAdvanced",
|
|
|
|
false);
|
2014-09-24 20:23:42 -07:00
|
|
|
config_set_default_bool (basicConfig, "SimpleOutput", "UseCBR", true);
|
2015-02-06 03:56:19 -08:00
|
|
|
config_set_default_bool (basicConfig, "SimpleOutput", "UseBufsize",
|
|
|
|
false);
|
|
|
|
config_set_default_int (basicConfig, "SimpleOutput", "Bufsize", 2500);
|
2014-08-25 07:48:51 -07:00
|
|
|
config_set_default_string(basicConfig, "SimpleOutput", "Preset",
|
|
|
|
"veryfast");
|
2014-03-10 13:10:35 -07:00
|
|
|
|
2015-01-26 13:41:22 -08:00
|
|
|
config_set_default_bool (basicConfig, "AdvOut", "Reconnect", true);
|
2015-03-07 10:06:52 -08:00
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "RetryDelay", 10);
|
2015-01-26 13:41:22 -08:00
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "MaxRetries", 20);
|
2015-02-10 20:06:00 -08:00
|
|
|
config_set_default_bool (basicConfig, "AdvOut", "ApplyServiceSettings",
|
|
|
|
true);
|
2015-01-26 13:41:22 -08:00
|
|
|
config_set_default_bool (basicConfig, "AdvOut", "UseRescale", false);
|
|
|
|
config_set_default_bool (basicConfig, "AdvOut", "Multitrack", false);
|
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "TrackIndex", 1);
|
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "TrackCount", 1);
|
|
|
|
config_set_default_string(basicConfig, "AdvOut", "Encoder", "obs_x264");
|
|
|
|
|
|
|
|
config_set_default_string(basicConfig, "AdvOut", "RecType", "Standard");
|
|
|
|
|
|
|
|
config_set_default_string(basicConfig, "AdvOut", "RecFilePath",
|
|
|
|
GetDefaultVideoSavePath().c_str());
|
2015-05-29 09:45:54 -07:00
|
|
|
config_set_default_string(basicConfig, "AdvOut", "RecFormat", "flv");
|
2015-01-26 13:41:22 -08:00
|
|
|
config_set_default_bool (basicConfig, "AdvOut", "RecUseRescale",
|
|
|
|
false);
|
|
|
|
config_set_default_bool (basicConfig, "AdvOut", "RecMultitrack",
|
|
|
|
false);
|
2015-05-30 21:45:14 -07:00
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "RecTracks", (1<<0));
|
2015-01-26 13:41:22 -08:00
|
|
|
config_set_default_string(basicConfig, "AdvOut", "RecEncoder",
|
|
|
|
"none");
|
|
|
|
|
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "FFVBitrate", 2500);
|
|
|
|
config_set_default_bool (basicConfig, "AdvOut", "FFUseRescale",
|
|
|
|
false);
|
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "FFABitrate", 160);
|
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "FFAudioTrack", 1);
|
|
|
|
|
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "Track1Bitrate", 160);
|
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "Track2Bitrate", 160);
|
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "Track3Bitrate", 160);
|
|
|
|
config_set_default_uint (basicConfig, "AdvOut", "Track4Bitrate", 160);
|
|
|
|
|
2014-03-06 20:08:12 -08:00
|
|
|
config_set_default_uint (basicConfig, "Video", "BaseCX", cx);
|
|
|
|
config_set_default_uint (basicConfig, "Video", "BaseCY", cy);
|
|
|
|
|
|
|
|
cx = cx * 10 / 15;
|
|
|
|
cy = cy * 10 / 15;
|
|
|
|
config_set_default_uint (basicConfig, "Video", "OutputCX", cx);
|
|
|
|
config_set_default_uint (basicConfig, "Video", "OutputCY", cy);
|
|
|
|
|
|
|
|
config_set_default_uint (basicConfig, "Video", "FPSType", 0);
|
|
|
|
config_set_default_string(basicConfig, "Video", "FPSCommon", "30");
|
|
|
|
config_set_default_uint (basicConfig, "Video", "FPSInt", 30);
|
|
|
|
config_set_default_uint (basicConfig, "Video", "FPSNum", 30);
|
|
|
|
config_set_default_uint (basicConfig, "Video", "FPSDen", 1);
|
2014-12-15 01:08:46 -08:00
|
|
|
config_set_default_string(basicConfig, "Video", "ScaleType", "bicubic");
|
2015-01-09 20:16:30 -08:00
|
|
|
config_set_default_string(basicConfig, "Video", "ColorFormat", "NV12");
|
|
|
|
config_set_default_string(basicConfig, "Video", "ColorSpace", "709");
|
|
|
|
config_set_default_string(basicConfig, "Video", "ColorRange",
|
|
|
|
"Partial");
|
2014-03-06 20:08:12 -08:00
|
|
|
|
|
|
|
config_set_default_uint (basicConfig, "Audio", "SampleRate", 44100);
|
|
|
|
config_set_default_string(basicConfig, "Audio", "ChannelSetup",
|
|
|
|
"Stereo");
|
|
|
|
config_set_default_uint (basicConfig, "Audio", "BufferingTime", 1000);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OBSBasic::InitBasicConfig()
|
|
|
|
{
|
2015-01-15 23:44:38 -08:00
|
|
|
char configPath[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
int ret = GetConfigPath(configPath, sizeof(configPath),
|
2015-01-15 23:44:38 -08:00
|
|
|
"obs-studio/basic/basic.ini");
|
|
|
|
if (ret <= 0) {
|
|
|
|
OBSErrorBox(nullptr, "Failed to get base.ini path");
|
|
|
|
return false;
|
|
|
|
}
|
2014-03-06 20:08:12 -08:00
|
|
|
|
2014-05-12 15:30:36 -07:00
|
|
|
int code = basicConfig.Open(configPath, CONFIG_OPEN_ALWAYS);
|
|
|
|
if (code != CONFIG_SUCCESS) {
|
|
|
|
OBSErrorBox(NULL, "Failed to open basic.ini: %d", code);
|
2014-03-06 20:08:12 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return InitBasicConfigDefaults();
|
|
|
|
}
|
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
void OBSBasic::InitOBSCallbacks()
|
|
|
|
{
|
2015-06-27 00:29:17 -07:00
|
|
|
signalHandlers.reserve(signalHandlers.size() + 6);
|
|
|
|
signalHandlers.emplace_back(obs_get_signal_handler(), "source_add",
|
2014-05-03 22:54:38 -07:00
|
|
|
OBSBasic::SourceAdded, this);
|
2015-06-27 00:29:17 -07:00
|
|
|
signalHandlers.emplace_back(obs_get_signal_handler(), "source_remove",
|
2014-05-03 22:54:38 -07:00
|
|
|
OBSBasic::SourceRemoved, this);
|
2015-06-27 00:29:17 -07:00
|
|
|
signalHandlers.emplace_back(obs_get_signal_handler(), "channel_change",
|
2014-05-03 22:54:38 -07:00
|
|
|
OBSBasic::ChannelChanged, this);
|
2015-06-27 00:29:17 -07:00
|
|
|
signalHandlers.emplace_back(obs_get_signal_handler(), "source_activate",
|
2014-05-03 22:54:38 -07:00
|
|
|
OBSBasic::SourceActivated, this);
|
2015-06-27 00:29:17 -07:00
|
|
|
signalHandlers.emplace_back(obs_get_signal_handler(), "source_deactivate",
|
2014-05-03 22:54:38 -07:00
|
|
|
OBSBasic::SourceDeactivated, this);
|
2015-06-27 00:29:17 -07:00
|
|
|
signalHandlers.emplace_back(obs_get_signal_handler(), "source_rename",
|
2014-06-30 00:06:01 -07:00
|
|
|
OBSBasic::SourceRenamed, this);
|
2014-05-03 22:54:38 -07:00
|
|
|
}
|
|
|
|
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
void OBSBasic::InitPrimitives()
|
|
|
|
{
|
2014-08-04 05:48:58 -07:00
|
|
|
obs_enter_graphics();
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_render_start(true);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
gs_vertex2f(0.0f, 0.0f);
|
|
|
|
gs_vertex2f(0.0f, 1.0f);
|
|
|
|
gs_vertex2f(1.0f, 1.0f);
|
|
|
|
gs_vertex2f(1.0f, 0.0f);
|
|
|
|
gs_vertex2f(0.0f, 0.0f);
|
2014-08-07 23:42:07 -07:00
|
|
|
box = gs_render_save();
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_render_start(true);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
for (int i = 0; i <= 360; i += (360/20)) {
|
|
|
|
float pos = RAD(float(i));
|
|
|
|
gs_vertex2f(cosf(pos), sinf(pos));
|
|
|
|
}
|
2014-08-07 23:42:07 -07:00
|
|
|
circle = gs_render_save();
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
2014-08-04 05:48:58 -07:00
|
|
|
obs_leave_graphics();
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
}
|
|
|
|
|
2015-02-06 03:17:33 -08:00
|
|
|
void OBSBasic::ResetOutputs()
|
|
|
|
{
|
2015-01-26 13:41:22 -08:00
|
|
|
const char *mode = config_get_string(basicConfig, "Output", "Mode");
|
|
|
|
bool advOut = astrcmpi(mode, "Advanced") == 0;
|
|
|
|
|
2015-02-06 03:17:33 -08:00
|
|
|
if (!outputHandler || !outputHandler->Active()) {
|
|
|
|
outputHandler.reset();
|
2015-01-26 13:41:22 -08:00
|
|
|
outputHandler.reset(advOut ?
|
|
|
|
CreateAdvancedOutputHandler(this) :
|
|
|
|
CreateSimpleOutputHandler(this));
|
2015-02-06 03:17:33 -08:00
|
|
|
} else {
|
|
|
|
outputHandler->Update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-02 14:23:38 -08:00
|
|
|
void OBSBasic::OBSInit()
|
|
|
|
{
|
2015-01-15 23:44:38 -08:00
|
|
|
char savePath[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
int ret = GetConfigPath(savePath, sizeof(savePath),
|
2015-01-15 23:44:38 -08:00
|
|
|
"obs-studio/basic/scenes.json");
|
|
|
|
if (ret <= 0)
|
|
|
|
throw "Failed to get scenes.json file path";
|
2014-05-03 22:54:38 -07:00
|
|
|
|
2014-02-02 14:23:38 -08:00
|
|
|
/* make sure it's fully displayed before doing any initialization */
|
|
|
|
show();
|
|
|
|
App()->processEvents();
|
|
|
|
|
2014-06-25 00:21:16 -07:00
|
|
|
if (!obs_startup(App()->GetLocale()))
|
2014-02-02 14:23:38 -08:00
|
|
|
throw "Failed to initialize libobs";
|
2014-03-06 20:08:12 -08:00
|
|
|
if (!InitBasicConfig())
|
|
|
|
throw "Failed to load basic.ini";
|
2014-02-22 19:14:19 -08:00
|
|
|
if (!ResetAudio())
|
2014-02-02 14:23:38 -08:00
|
|
|
throw "Failed to initialize audio";
|
|
|
|
|
2015-01-15 23:44:38 -08:00
|
|
|
ret = ResetVideo();
|
2014-07-20 17:40:57 -07:00
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
case OBS_VIDEO_MODULE_NOT_FOUND:
|
|
|
|
throw "Failed to initialize video: Graphics module not found";
|
|
|
|
case OBS_VIDEO_NOT_SUPPORTED:
|
2014-08-25 15:52:54 -07:00
|
|
|
throw "Failed to initialize video: Required graphics API "
|
|
|
|
"functionality not found on these drivers or "
|
|
|
|
"unavailable on this equipment";
|
2014-07-20 17:40:57 -07:00
|
|
|
case OBS_VIDEO_INVALID_PARAM:
|
|
|
|
throw "Failed to initialize video: Invalid parameters";
|
|
|
|
default:
|
|
|
|
if (ret != OBS_VIDEO_SUCCESS)
|
|
|
|
throw "Failed to initialize video: Unspecified error";
|
|
|
|
}
|
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
InitOBSCallbacks();
|
2014-11-01 13:48:58 -07:00
|
|
|
InitHotkeys();
|
2014-02-02 14:23:38 -08:00
|
|
|
|
2014-07-27 12:48:14 -07:00
|
|
|
AddExtraModulePaths();
|
(API Change) Refactor module handling
Changed API:
- char *obs_find_plugin_file(const char *sub_path);
Changed to: char *obs_module_file(const char *file);
Cahnge it so you no longer need to specify a sub-path such as:
obs_find_plugin_file("module_name/file.ext")
Instead, now automatically handle the module data path so all you need
to do is:
obs_module_file("file.ext")
- int obs_load_module(const char *name);
Changed to: int obs_open_module(obs_module_t *module,
const char *path,
const char *data_path);
bool obs_init_module(obs_module_t module);
Change the module loading API so that if the front-end chooses, it can
load modules directly from a specified path, and associate a data
directory with it on the spot.
The module will not be initialized immediately; obs_init_module must
be called on the module pointer in order to fully initialize the
module. This is done so a module can be disabled by the front-end if
the it so chooses.
New API:
- void obs_add_module_path(const char *bin, const char *data);
These functions allow you to specify new module search paths to add,
and allow you to search through them, or optionally just load all
modules from them. If the string %module% is included, it will
replace it with the module's name when that string is used as a
lookup. Data paths are now directly added to the module's internal
storage structure, and when obs_find_module_file is used, it will look
up the pointer to the obs_module structure and get its data directory
that way.
Example:
obs_add_module_path("/opt/obs/my-modules/%module%/bin",
"/opt/obs/my-modules/%module%/data");
This would cause it to additionally look for the binary of a
hypthetical module named "foo" at /opt/obs/my-modules/foo/bin/foo.so
(or libfoo.so), and then look for the data in
/opt/obs/my-modules/foo/data.
This gives the front-end more flexibility for handling third-party
plugin modules, or handling all plugin modules in a custom way.
- void obs_find_modules(obs_find_module_callback_t callback, void
*param);
This searches the existing paths for modules and calls the callback
function when any are found. Useful for plugin management and custom
handling of the paths by the front-end if desired.
- void obs_load_all_modules(void);
Search through the paths and both loads and initializes all modules
automatically without custom handling.
- void obs_enum_modules(obs_enum_module_callback_t callback,
void *param);
Enumerates currently opened modules.
2014-07-27 12:00:11 -07:00
|
|
|
obs_load_all_modules();
|
2014-03-07 16:03:34 -08:00
|
|
|
|
2015-02-06 03:17:33 -08:00
|
|
|
ResetOutputs();
|
2014-11-01 13:53:25 -07:00
|
|
|
CreateHotkeys();
|
2015-02-06 03:17:33 -08:00
|
|
|
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
if (!InitService())
|
|
|
|
throw "Failed to initialize service";
|
|
|
|
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
InitPrimitives();
|
|
|
|
|
2015-06-30 05:49:31 -07:00
|
|
|
disableSaving--;
|
2014-04-26 23:47:50 -07:00
|
|
|
Load(savePath);
|
2015-06-30 05:49:31 -07:00
|
|
|
disableSaving++;
|
2014-06-16 19:41:36 -07:00
|
|
|
|
2014-07-13 23:56:28 -07:00
|
|
|
TimedCheckForUpdates();
|
2014-06-16 19:41:36 -07:00
|
|
|
loaded = true;
|
2015-01-04 08:20:15 -08:00
|
|
|
|
2015-04-02 21:35:46 -07:00
|
|
|
bool previewEnabled = config_get_bool(App()->GlobalConfig(),
|
|
|
|
"BasicWindow", "PreviewEnabled");
|
|
|
|
if (!previewEnabled)
|
|
|
|
QMetaObject::invokeMethod(this, "TogglePreview",
|
|
|
|
Qt::QueuedConnection);
|
2015-05-25 01:37:13 -07:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
uint32_t winVer = GetWindowsVersion();
|
|
|
|
if (winVer > 0 && winVer < 0x602) {
|
|
|
|
bool disableAero = config_get_bool(basicConfig, "Video",
|
|
|
|
"DisableAero");
|
|
|
|
SetAeroEnabled(!disableAero);
|
|
|
|
}
|
|
|
|
#endif
|
2015-06-30 05:49:31 -07:00
|
|
|
|
|
|
|
disableSaving--;
|
2014-02-02 14:23:38 -08:00
|
|
|
}
|
|
|
|
|
2014-11-01 13:48:58 -07:00
|
|
|
void OBSBasic::InitHotkeys()
|
|
|
|
{
|
|
|
|
struct obs_hotkeys_translations t = {};
|
|
|
|
t.insert = Str("Hotkeys.Insert");
|
|
|
|
t.del = Str("Hotkeys.Delete");
|
|
|
|
t.home = Str("Hotkeys.Home");
|
|
|
|
t.end = Str("Hotkeys.End");
|
|
|
|
t.page_up = Str("Hotkeys.PageUp");
|
|
|
|
t.page_down = Str("Hotkeys.PageDown");
|
|
|
|
t.num_lock = Str("Hotkeys.NumLock");
|
|
|
|
t.scroll_lock = Str("Hotkeys.ScrollLock");
|
|
|
|
t.caps_lock = Str("Hotkeys.CapsLock");
|
|
|
|
t.backspace = Str("Hotkeys.Backspace");
|
|
|
|
t.tab = Str("Hotkeys.Tab");
|
|
|
|
t.print = Str("Hotkeys.Print");
|
|
|
|
t.pause = Str("Hotkeys.Pause");
|
|
|
|
t.left = Str("Hotkeys.Left");
|
|
|
|
t.right = Str("Hotkeys.Right");
|
|
|
|
t.up = Str("Hotkeys.Up");
|
|
|
|
t.down = Str("Hotkeys.Down");
|
|
|
|
#ifdef _WIN32
|
|
|
|
t.meta = Str("Hotkeys.Windows");
|
|
|
|
#else
|
|
|
|
t.meta = Str("Hotkeys.Super");
|
|
|
|
#endif
|
|
|
|
t.menu = Str("Hotkeys.Menu");
|
|
|
|
t.space = Str("Hotkeys.Space");
|
|
|
|
t.numpad_num = Str("Hotkeys.NumpadNum");
|
|
|
|
t.numpad_multiply = Str("Hotkeys.NumpadMultiply");
|
|
|
|
t.numpad_divide = Str("Hotkeys.NumpadDivide");
|
|
|
|
t.numpad_plus = Str("Hotkeys.NumpadAdd");
|
|
|
|
t.numpad_minus = Str("Hotkeys.NumpadSubtract");
|
|
|
|
t.numpad_decimal = Str("Hotkeys.NumpadDecimal");
|
|
|
|
t.apple_keypad_num = Str("Hotkeys.AppleKeypadNum");
|
|
|
|
t.apple_keypad_multiply = Str("Hotkeys.AppleKeypadMultiply");
|
|
|
|
t.apple_keypad_divide = Str("Hotkeys.AppleKeypadDivide");
|
|
|
|
t.apple_keypad_plus = Str("Hotkeys.AppleKeypadAdd");
|
|
|
|
t.apple_keypad_minus = Str("Hotkeys.AppleKeypadSubtract");
|
|
|
|
t.apple_keypad_decimal = Str("Hotkeys.AppleKeypadDecimal");
|
|
|
|
t.apple_keypad_equal = Str("Hotkeys.AppleKeypadEqual");
|
|
|
|
t.mouse_num = Str("Hotkeys.MouseButton");
|
|
|
|
obs_hotkeys_set_translations(&t);
|
|
|
|
|
|
|
|
obs_hotkeys_set_audio_hotkeys_translations(Str("Mute"), Str("Unmute"),
|
2015-05-12 12:36:19 -07:00
|
|
|
Str("Push-to-mute"), Str("Push-to-talk"));
|
2014-11-01 13:48:58 -07:00
|
|
|
|
|
|
|
obs_hotkeys_set_sceneitem_hotkeys_translations(
|
|
|
|
Str("SceneItemShow"), Str("SceneItemHide"));
|
|
|
|
|
|
|
|
obs_hotkey_enable_callback_rerouting(true);
|
|
|
|
obs_hotkey_set_callback_routing_func(OBSBasic::HotkeyTriggered, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::ProcessHotkey(obs_hotkey_id id, bool pressed)
|
|
|
|
{
|
|
|
|
obs_hotkey_trigger_routed_callback(id, pressed);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::HotkeyTriggered(void *data, obs_hotkey_id id, bool pressed)
|
|
|
|
{
|
|
|
|
OBSBasic &basic = *static_cast<OBSBasic*>(data);
|
|
|
|
QMetaObject::invokeMethod(&basic, "ProcessHotkey",
|
|
|
|
Q_ARG(obs_hotkey_id, id), Q_ARG(bool, pressed));
|
|
|
|
}
|
|
|
|
|
2014-11-01 13:53:25 -07:00
|
|
|
void OBSBasic::CreateHotkeys()
|
|
|
|
{
|
|
|
|
auto LoadHotkeyData = [&](const char *name) -> OBSData
|
|
|
|
{
|
|
|
|
const char *info = config_get_string(basicConfig,
|
|
|
|
"Hotkeys", name);
|
|
|
|
if (!info)
|
|
|
|
return {};
|
|
|
|
|
|
|
|
obs_data_t *data = obs_data_create_from_json(info);
|
|
|
|
if (!data)
|
|
|
|
return {};
|
|
|
|
|
|
|
|
OBSData res = data;
|
|
|
|
obs_data_release(data);
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto LoadHotkeyPair = [&](obs_hotkey_pair_id id, const char *name0,
|
|
|
|
const char *name1)
|
|
|
|
{
|
|
|
|
obs_data_array_t *array0 =
|
|
|
|
obs_data_get_array(LoadHotkeyData(name0), "bindings");
|
|
|
|
obs_data_array_t *array1 =
|
|
|
|
obs_data_get_array(LoadHotkeyData(name1), "bindings");
|
|
|
|
|
|
|
|
obs_hotkey_pair_load(id, array0, array1);
|
|
|
|
obs_data_array_release(array0);
|
|
|
|
obs_data_array_release(array1);
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MAKE_CALLBACK(pred, method) \
|
|
|
|
[](void *data, obs_hotkey_pair_id, obs_hotkey_t*, bool pressed) \
|
|
|
|
{ \
|
|
|
|
OBSBasic &basic = *static_cast<OBSBasic*>(data); \
|
|
|
|
if (pred && pressed) { \
|
|
|
|
method(); \
|
|
|
|
return true; \
|
|
|
|
} \
|
|
|
|
return false; \
|
|
|
|
}
|
|
|
|
|
|
|
|
streamingHotkeys = obs_hotkey_pair_register_frontend(
|
|
|
|
"OBSBasic.StartStreaming",
|
|
|
|
Str("Basic.Hotkeys.StartStreaming"),
|
|
|
|
"OBSBasic.StopStreaming",
|
|
|
|
Str("Basic.Hotkeys.StopStreaming"),
|
|
|
|
MAKE_CALLBACK(!basic.outputHandler->StreamingActive(),
|
|
|
|
basic.StartStreaming),
|
|
|
|
MAKE_CALLBACK(basic.outputHandler->StreamingActive(),
|
|
|
|
basic.StopStreaming),
|
|
|
|
this, this);
|
|
|
|
LoadHotkeyPair(streamingHotkeys,
|
|
|
|
"OBSBasic.StartStreaming", "OBSBasic.StopStreaming");
|
|
|
|
|
|
|
|
recordingHotkeys = obs_hotkey_pair_register_frontend(
|
|
|
|
"OBSBasic.StartRecording",
|
|
|
|
Str("Basic.Hotkeys.StartRecording"),
|
|
|
|
"OBSBasic.StopRecording",
|
|
|
|
Str("Basic.Hotkeys.StopRecording"),
|
|
|
|
MAKE_CALLBACK(!basic.outputHandler->RecordingActive(),
|
|
|
|
basic.StartRecording),
|
|
|
|
MAKE_CALLBACK(basic.outputHandler->RecordingActive(),
|
|
|
|
basic.StopRecording),
|
|
|
|
this, this);
|
|
|
|
LoadHotkeyPair(recordingHotkeys,
|
|
|
|
"OBSBasic.StartRecording", "OBSBasic.StopRecording");
|
|
|
|
|
|
|
|
#undef MAKE_CALLBACK
|
|
|
|
}
|
|
|
|
|
2015-06-29 00:47:07 -07:00
|
|
|
void OBSBasic::ClearHotkeys()
|
|
|
|
{
|
|
|
|
obs_hotkey_pair_unregister(streamingHotkeys);
|
|
|
|
obs_hotkey_pair_unregister(recordingHotkeys);
|
|
|
|
}
|
|
|
|
|
2014-02-02 14:23:38 -08:00
|
|
|
OBSBasic::~OBSBasic()
|
|
|
|
{
|
2015-04-02 21:35:46 -07:00
|
|
|
bool previewEnabled = obs_preview_enabled();
|
|
|
|
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
/* XXX: any obs data must be released before calling obs_shutdown.
|
|
|
|
* currently, we can't automate this with C++ RAII because of the
|
|
|
|
* delicate nature of obs_shutdown needing to be freed before the UI
|
|
|
|
* can be freed, and we have no control over the destruction order of
|
|
|
|
* the Qt UI stuff, so we have to manually clear any references to
|
|
|
|
* libobs. */
|
2014-07-06 16:19:27 -07:00
|
|
|
delete cpuUsageTimer;
|
2014-07-06 16:18:16 -07:00
|
|
|
os_cpu_usage_info_destroy(cpuUsageInfo);
|
|
|
|
|
2014-11-01 13:48:58 -07:00
|
|
|
obs_hotkey_set_callback_routing_func(nullptr, nullptr);
|
2015-06-29 00:47:07 -07:00
|
|
|
ClearHotkeys();
|
2014-11-01 13:48:58 -07:00
|
|
|
|
2015-05-03 17:07:43 -07:00
|
|
|
service = nullptr;
|
2015-02-06 03:17:33 -08:00
|
|
|
outputHandler.reset();
|
|
|
|
|
2014-09-15 16:16:16 -07:00
|
|
|
if (interaction)
|
|
|
|
delete interaction;
|
|
|
|
|
2014-07-22 13:16:57 -07:00
|
|
|
if (properties)
|
|
|
|
delete properties;
|
|
|
|
|
2015-02-25 21:23:57 -08:00
|
|
|
if (filters)
|
|
|
|
delete filters;
|
|
|
|
|
2014-07-22 13:16:57 -07:00
|
|
|
if (transformWindow)
|
|
|
|
delete transformWindow;
|
2014-03-23 01:07:54 -07:00
|
|
|
|
2014-12-28 00:38:00 -08:00
|
|
|
if (advAudioWindow)
|
|
|
|
delete advAudioWindow;
|
|
|
|
|
2014-08-04 05:48:58 -07:00
|
|
|
obs_enter_graphics();
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_vertexbuffer_destroy(box);
|
|
|
|
gs_vertexbuffer_destroy(circle);
|
2014-08-04 05:48:58 -07:00
|
|
|
obs_leave_graphics();
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
2015-03-18 06:31:08 -07:00
|
|
|
/* When shutting down, sometimes source references can get in to the
|
|
|
|
* event queue, and if we don't forcibly process those events they
|
|
|
|
* won't get processed until after obs_shutdown has been called. I
|
|
|
|
* really wish there were a more elegant way to deal with this via C++,
|
|
|
|
* but Qt doesn't use C++ in a normal way, so you can't really rely on
|
|
|
|
* normal C++ behavior for your data to be freed in the order that you
|
|
|
|
* expect or want it to. */
|
|
|
|
QApplication::sendPostedEvents(this);
|
|
|
|
|
2014-02-02 14:23:38 -08:00
|
|
|
obs_shutdown();
|
2014-07-13 12:38:58 -07:00
|
|
|
|
|
|
|
config_set_int(App()->GlobalConfig(), "General", "LastVersion",
|
|
|
|
LIBOBS_API_VER);
|
2015-03-18 19:37:34 -07:00
|
|
|
|
|
|
|
QRect lastGeom = normalGeometry();
|
|
|
|
|
2015-04-02 18:10:06 -07:00
|
|
|
config_set_int(App()->GlobalConfig(), "BasicWindow", "cx",
|
2015-03-18 19:37:34 -07:00
|
|
|
lastGeom.width());
|
2015-04-02 18:10:06 -07:00
|
|
|
config_set_int(App()->GlobalConfig(), "BasicWindow", "cy",
|
2015-03-18 19:37:34 -07:00
|
|
|
lastGeom.height());
|
2015-04-02 18:10:06 -07:00
|
|
|
config_set_int(App()->GlobalConfig(), "BasicWindow", "posx",
|
2015-03-18 19:37:34 -07:00
|
|
|
lastGeom.x());
|
2015-04-02 18:10:06 -07:00
|
|
|
config_set_int(App()->GlobalConfig(), "BasicWindow", "posy",
|
2015-03-18 19:37:34 -07:00
|
|
|
lastGeom.y());
|
2015-04-02 21:35:46 -07:00
|
|
|
config_set_bool(App()->GlobalConfig(), "BasicWindow", "PreviewEnabled",
|
|
|
|
previewEnabled);
|
2014-07-13 12:38:58 -07:00
|
|
|
config_save(App()->GlobalConfig());
|
2015-05-25 01:37:13 -07:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
uint32_t winVer = GetWindowsVersion();
|
|
|
|
if (winVer > 0 && winVer < 0x602) {
|
|
|
|
bool disableAero = config_get_bool(basicConfig, "Video",
|
|
|
|
"DisableAero");
|
|
|
|
if (disableAero) {
|
|
|
|
SetAeroEnabled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2014-02-02 14:23:38 -08:00
|
|
|
}
|
|
|
|
|
2015-01-04 08:16:59 -08:00
|
|
|
void OBSBasic::SaveProject()
|
|
|
|
{
|
2015-06-30 05:49:31 -07:00
|
|
|
if (disableSaving)
|
|
|
|
return;
|
|
|
|
|
2015-01-15 23:44:38 -08:00
|
|
|
char savePath[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
int ret = GetConfigPath(savePath, sizeof(savePath),
|
2015-01-15 23:44:38 -08:00
|
|
|
"obs-studio/basic/scenes.json");
|
|
|
|
if (ret <= 0)
|
|
|
|
return;
|
|
|
|
|
2015-01-04 08:16:59 -08:00
|
|
|
Save(savePath);
|
|
|
|
}
|
|
|
|
|
2014-02-02 13:26:23 -08:00
|
|
|
OBSScene OBSBasic::GetCurrentScene()
|
2014-01-04 12:53:36 -08:00
|
|
|
{
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
QListWidgetItem *item = ui->scenes->currentItem();
|
2015-06-27 18:21:45 -07:00
|
|
|
return item ? GetOBSRef<OBSScene>(item) : nullptr;
|
2014-01-04 12:53:36 -08:00
|
|
|
}
|
|
|
|
|
2014-09-15 16:04:22 -07:00
|
|
|
OBSSceneItem OBSBasic::GetSceneItem(QListWidgetItem *item)
|
2014-01-30 00:31:52 -08:00
|
|
|
{
|
2015-06-27 18:21:45 -07:00
|
|
|
return item ? GetOBSRef<OBSSceneItem>(item) : nullptr;
|
2014-01-30 00:31:52 -08:00
|
|
|
}
|
|
|
|
|
2014-09-15 16:04:22 -07:00
|
|
|
OBSSceneItem OBSBasic::GetCurrentSceneItem()
|
|
|
|
{
|
|
|
|
return GetSceneItem(ui->sources->currentItem());
|
|
|
|
}
|
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
void OBSBasic::UpdateSources(OBSScene scene)
|
|
|
|
{
|
2015-06-27 18:18:40 -07:00
|
|
|
ClearListItems(ui->sources);
|
2014-02-02 16:03:55 -08:00
|
|
|
|
|
|
|
obs_scene_enum_items(scene,
|
2014-09-25 17:44:05 -07:00
|
|
|
[] (obs_scene_t *scene, obs_sceneitem_t *item, void *p)
|
2014-02-02 16:03:55 -08:00
|
|
|
{
|
|
|
|
OBSBasic *window = static_cast<OBSBasic*>(p);
|
2014-03-01 04:54:55 -08:00
|
|
|
window->InsertSceneItem(item);
|
2014-02-14 14:13:36 -08:00
|
|
|
|
|
|
|
UNUSED_PARAMETER(scene);
|
2014-02-02 16:03:55 -08:00
|
|
|
return true;
|
|
|
|
}, this);
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::InsertSceneItem(obs_sceneitem_t *item)
|
2014-03-01 04:54:55 -08:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_sceneitem_get_source(item);
|
2014-03-01 04:54:55 -08:00
|
|
|
|
2015-03-22 20:51:21 -07:00
|
|
|
QListWidgetItem *listItem = new QListWidgetItem();
|
2015-06-27 18:21:45 -07:00
|
|
|
SetOBSRef(listItem, OBSSceneItem(item));
|
2014-03-01 04:54:55 -08:00
|
|
|
|
|
|
|
ui->sources->insertItem(0, listItem);
|
2015-06-27 19:29:26 -07:00
|
|
|
ui->sources->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
|
2014-06-16 19:41:36 -07:00
|
|
|
|
2015-03-22 20:51:21 -07:00
|
|
|
SetupVisibilityItem(ui->sources, listItem, item);
|
|
|
|
|
2014-06-16 19:41:36 -07:00
|
|
|
/* if the source was just created, open properties dialog */
|
2014-07-22 13:16:57 -07:00
|
|
|
if (sourceSceneRefs[source] == 0 && loaded)
|
|
|
|
CreatePropertiesWindow(source);
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::CreateInteractionWindow(obs_source_t *source)
|
2014-09-15 16:16:16 -07:00
|
|
|
{
|
|
|
|
if (interaction)
|
|
|
|
interaction->close();
|
|
|
|
|
|
|
|
interaction = new OBSBasicInteraction(this, source);
|
|
|
|
interaction->Init();
|
|
|
|
interaction->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::CreatePropertiesWindow(obs_source_t *source)
|
2014-07-22 13:16:57 -07:00
|
|
|
{
|
|
|
|
if (properties)
|
|
|
|
properties->close();
|
|
|
|
|
|
|
|
properties = new OBSBasicProperties(this, source);
|
|
|
|
properties->Init();
|
|
|
|
properties->setAttribute(Qt::WA_DeleteOnClose, true);
|
2014-03-01 04:54:55 -08:00
|
|
|
}
|
|
|
|
|
2015-02-25 21:23:57 -08:00
|
|
|
void OBSBasic::CreateFiltersWindow(obs_source_t *source)
|
|
|
|
{
|
|
|
|
if (filters)
|
|
|
|
filters->close();
|
|
|
|
|
|
|
|
filters = new OBSBasicFilters(this, source);
|
|
|
|
filters->Init();
|
|
|
|
filters->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
|
|
}
|
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
/* Qt callbacks for invokeMethod */
|
|
|
|
|
|
|
|
void OBSBasic::AddScene(OBSSource source)
|
2013-12-28 04:33:16 -08:00
|
|
|
{
|
2014-08-04 08:41:15 -07:00
|
|
|
const char *name = obs_source_get_name(source);
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_scene_t *scene = obs_scene_from_source(source);
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
|
|
|
|
QListWidgetItem *item = new QListWidgetItem(QT_UTF8(name));
|
2015-06-27 18:21:45 -07:00
|
|
|
SetOBSRef(item, OBSScene(scene));
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
ui->scenes->addItem(item);
|
2014-01-04 12:53:36 -08:00
|
|
|
|
2014-11-01 13:53:05 -07:00
|
|
|
obs_hotkey_register_source(source, "OBSBasic.SelectScene",
|
|
|
|
Str("Basic.Hotkeys.SelectScene"),
|
|
|
|
[](void *data,
|
|
|
|
obs_hotkey_id, obs_hotkey_t*, bool pressed)
|
|
|
|
{
|
|
|
|
auto potential_source = static_cast<obs_source_t*>(data);
|
|
|
|
auto source = obs_source_get_ref(potential_source);
|
|
|
|
if (source && pressed)
|
|
|
|
obs_set_output_source(0, source);
|
|
|
|
obs_source_release(source);
|
|
|
|
}, static_cast<obs_source_t*>(source));
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
signal_handler_t *handler = obs_source_get_signal_handler(source);
|
2015-06-27 00:28:40 -07:00
|
|
|
|
|
|
|
std::vector<std::shared_ptr<OBSSignal>> handlers{
|
|
|
|
std::make_shared<OBSSignal>(handler, "item_add",
|
|
|
|
OBSBasic::SceneItemAdded, this),
|
|
|
|
std::make_shared<OBSSignal>(handler, "item_remove",
|
|
|
|
OBSBasic::SceneItemRemoved, this),
|
|
|
|
std::make_shared<OBSSignal>(handler, "item_select",
|
|
|
|
OBSBasic::SceneItemSelected, this),
|
|
|
|
std::make_shared<OBSSignal>(handler, "item_deselect",
|
|
|
|
OBSBasic::SceneItemDeselected, this),
|
|
|
|
std::make_shared<OBSSignal>(handler, "reorder",
|
|
|
|
OBSBasic::SceneReordered, this),
|
|
|
|
};
|
|
|
|
|
|
|
|
item->setData(static_cast<int>(QtDataRole::OBSSignals),
|
|
|
|
QVariant::fromValue(handlers));
|
2015-06-30 05:49:31 -07:00
|
|
|
|
|
|
|
SaveProject();
|
2013-12-28 04:33:16 -08:00
|
|
|
}
|
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
void OBSBasic::RemoveScene(OBSSource source)
|
2013-12-28 21:29:13 -08:00
|
|
|
{
|
2014-08-04 08:41:15 -07:00
|
|
|
const char *name = obs_source_get_name(source);
|
2013-12-28 21:29:13 -08:00
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
QListWidgetItem *sel = ui->scenes->currentItem();
|
|
|
|
QList<QListWidgetItem*> items = ui->scenes->findItems(QT_UTF8(name),
|
|
|
|
Qt::MatchExactly);
|
2014-01-06 19:20:18 -08:00
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
if (sel != nullptr) {
|
|
|
|
if (items.contains(sel))
|
2015-06-27 18:18:40 -07:00
|
|
|
ClearListItems(ui->sources);
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
delete sel;
|
2014-01-06 19:20:18 -08:00
|
|
|
}
|
2015-06-30 05:49:31 -07:00
|
|
|
|
|
|
|
SaveProject();
|
2014-01-04 12:53:36 -08:00
|
|
|
}
|
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
void OBSBasic::AddSceneItem(OBSSceneItem item)
|
2014-01-04 12:53:36 -08:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_scene_t *scene = obs_sceneitem_get_scene(item);
|
|
|
|
obs_source_t *source = obs_sceneitem_get_source(item);
|
2014-01-06 19:20:18 -08:00
|
|
|
|
2014-03-01 04:54:55 -08:00
|
|
|
if (GetCurrentScene() == scene)
|
|
|
|
InsertSceneItem(item);
|
2014-01-06 19:20:18 -08:00
|
|
|
|
|
|
|
sourceSceneRefs[source] = sourceSceneRefs[source] + 1;
|
2015-06-30 05:49:31 -07:00
|
|
|
SaveProject();
|
2014-01-04 12:53:36 -08:00
|
|
|
}
|
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
void OBSBasic::RemoveSceneItem(OBSSceneItem item)
|
2014-01-04 12:53:36 -08:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_scene_t *scene = obs_sceneitem_get_scene(item);
|
2014-01-04 12:53:36 -08:00
|
|
|
|
2014-01-06 19:20:18 -08:00
|
|
|
if (GetCurrentScene() == scene) {
|
2014-01-23 22:58:48 -08:00
|
|
|
for (int i = 0; i < ui->sources->count(); i++) {
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
QListWidgetItem *listItem = ui->sources->item(i);
|
2014-01-06 19:20:18 -08:00
|
|
|
|
2015-06-27 18:21:45 -07:00
|
|
|
if (GetOBSRef<OBSSceneItem>(listItem) == item) {
|
2015-06-27 18:18:40 -07:00
|
|
|
DeleteListItem(ui->sources, listItem);
|
2014-01-06 19:20:18 -08:00
|
|
|
break;
|
|
|
|
}
|
2014-01-04 18:26:15 -08:00
|
|
|
}
|
|
|
|
}
|
2014-01-06 19:20:18 -08:00
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_sceneitem_get_source(item);
|
2014-01-06 19:20:18 -08:00
|
|
|
|
|
|
|
int scenes = sourceSceneRefs[source] - 1;
|
2014-05-11 23:20:45 -07:00
|
|
|
sourceSceneRefs[source] = scenes;
|
|
|
|
|
2014-01-06 19:20:18 -08:00
|
|
|
if (scenes == 0) {
|
|
|
|
obs_source_remove(source);
|
|
|
|
sourceSceneRefs.erase(source);
|
|
|
|
}
|
2015-06-30 05:49:31 -07:00
|
|
|
|
|
|
|
SaveProject();
|
2014-01-04 12:53:36 -08:00
|
|
|
}
|
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
void OBSBasic::UpdateSceneSelection(OBSSource source)
|
2014-01-04 12:53:36 -08:00
|
|
|
{
|
|
|
|
if (source) {
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_scene_t *scene = obs_scene_from_source(source);
|
2014-08-04 08:41:15 -07:00
|
|
|
const char *name = obs_source_get_name(source);
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
|
2014-04-26 23:47:50 -07:00
|
|
|
if (!scene)
|
|
|
|
return;
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
QList<QListWidgetItem*> items =
|
|
|
|
ui->scenes->findItems(QT_UTF8(name), Qt::MatchExactly);
|
|
|
|
|
2014-02-20 21:04:14 -08:00
|
|
|
if (items.count()) {
|
|
|
|
sceneChanging = true;
|
|
|
|
ui->scenes->setCurrentItem(items.first());
|
|
|
|
sceneChanging = false;
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
UpdateSources(scene);
|
2014-01-04 12:53:36 -08:00
|
|
|
}
|
2013-12-28 21:29:13 -08:00
|
|
|
}
|
2014-01-04 12:53:36 -08:00
|
|
|
}
|
|
|
|
|
2014-06-30 00:06:01 -07:00
|
|
|
static void RenameListValues(QListWidget *listWidget, const QString &newName,
|
|
|
|
const QString &prevName)
|
|
|
|
{
|
|
|
|
QList<QListWidgetItem*> items =
|
|
|
|
listWidget->findItems(prevName, Qt::MatchExactly);
|
|
|
|
|
|
|
|
for (int i = 0; i < items.count(); i++)
|
|
|
|
items[i]->setText(newName);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::RenameSources(QString newName, QString prevName)
|
|
|
|
{
|
|
|
|
RenameListValues(ui->scenes, newName, prevName);
|
2014-07-08 11:58:48 -07:00
|
|
|
|
|
|
|
for (size_t i = 0; i < volumes.size(); i++) {
|
|
|
|
if (volumes[i]->GetName().compare(prevName) == 0)
|
|
|
|
volumes[i]->SetName(newName);
|
|
|
|
}
|
2015-06-30 05:49:31 -07:00
|
|
|
|
|
|
|
SaveProject();
|
2014-06-30 00:06:01 -07:00
|
|
|
}
|
|
|
|
|
2014-10-13 13:14:06 -07:00
|
|
|
void OBSBasic::SelectSceneItem(OBSScene scene, OBSSceneItem item, bool select)
|
|
|
|
{
|
2015-06-26 18:32:33 -07:00
|
|
|
if (scene != GetCurrentScene() || ignoreSelectionUpdate)
|
2014-10-13 13:14:06 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
for (int i = 0; i < ui->sources->count(); i++) {
|
|
|
|
QListWidgetItem *witem = ui->sources->item(i);
|
2015-06-27 18:21:45 -07:00
|
|
|
QVariant data =
|
|
|
|
witem->data(static_cast<int>(QtDataRole::OBSRef));
|
2014-10-13 13:14:06 -07:00
|
|
|
if (!data.canConvert<OBSSceneItem>())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (item != data.value<OBSSceneItem>())
|
|
|
|
continue;
|
|
|
|
|
2015-06-26 18:34:08 -07:00
|
|
|
if (select)
|
|
|
|
ui->sources->setCurrentItem(witem,
|
|
|
|
QItemSelectionModel::ClearAndSelect);
|
2015-04-04 04:20:54 -07:00
|
|
|
|
2014-10-13 13:14:06 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-20 18:57:06 -07:00
|
|
|
void OBSBasic::GetAudioSourceFilters()
|
|
|
|
{
|
|
|
|
QAction *action = reinterpret_cast<QAction*>(sender());
|
|
|
|
VolControl *vol = action->property("volControl").value<VolControl*>();
|
|
|
|
obs_source_t *source = vol->GetSource();
|
|
|
|
|
|
|
|
CreateFiltersWindow(source);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::GetAudioSourceProperties()
|
|
|
|
{
|
|
|
|
QAction *action = reinterpret_cast<QAction*>(sender());
|
|
|
|
VolControl *vol = action->property("volControl").value<VolControl*>();
|
|
|
|
obs_source_t *source = vol->GetSource();
|
|
|
|
|
|
|
|
CreatePropertiesWindow(source);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::VolControlContextMenu()
|
|
|
|
{
|
|
|
|
VolControl *vol = reinterpret_cast<VolControl*>(sender());
|
|
|
|
|
|
|
|
QAction filtersAction(QTStr("Filters"), this);
|
|
|
|
QAction propertiesAction(QTStr("Properties"), this);
|
|
|
|
|
|
|
|
connect(&filtersAction, &QAction::triggered,
|
|
|
|
this, &OBSBasic::GetAudioSourceFilters,
|
|
|
|
Qt::DirectConnection);
|
|
|
|
connect(&propertiesAction, &QAction::triggered,
|
|
|
|
this, &OBSBasic::GetAudioSourceProperties,
|
|
|
|
Qt::DirectConnection);
|
|
|
|
|
|
|
|
filtersAction.setProperty("volControl",
|
|
|
|
QVariant::fromValue<VolControl*>(vol));
|
|
|
|
propertiesAction.setProperty("volControl",
|
|
|
|
QVariant::fromValue<VolControl*>(vol));
|
|
|
|
|
|
|
|
QMenu popup(this);
|
|
|
|
popup.addAction(&filtersAction);
|
|
|
|
popup.addAction(&propertiesAction);
|
|
|
|
popup.exec(QCursor::pos());
|
|
|
|
}
|
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
void OBSBasic::ActivateAudioSource(OBSSource source)
|
|
|
|
{
|
2015-06-20 18:57:06 -07:00
|
|
|
VolControl *vol = new VolControl(source, true);
|
|
|
|
|
|
|
|
connect(vol, &VolControl::ConfigClicked,
|
|
|
|
this, &OBSBasic::VolControlContextMenu);
|
2014-05-03 22:54:38 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
bool OBSBasic::QueryRemoveSource(obs_source_t *source)
|
2014-06-30 01:13:32 -07:00
|
|
|
{
|
2014-08-04 08:41:15 -07:00
|
|
|
const char *name = obs_source_get_name(source);
|
2014-06-30 13:45:58 -07:00
|
|
|
|
|
|
|
QString text = QTStr("ConfirmRemove.Text");
|
|
|
|
text.replace("$1", QT_UTF8(name));
|
2014-06-30 01:13:32 -07:00
|
|
|
|
2015-01-16 01:21:11 -08:00
|
|
|
QMessageBox remove_source(this);
|
2014-08-24 08:56:50 -07:00
|
|
|
remove_source.setText(text);
|
|
|
|
QAbstractButton *Yes = remove_source.addButton(QTStr("Yes"),
|
|
|
|
QMessageBox::YesRole);
|
2014-08-15 10:07:00 -07:00
|
|
|
remove_source.addButton(QTStr("No"), QMessageBox::NoRole);
|
|
|
|
remove_source.setIcon(QMessageBox::Question);
|
|
|
|
remove_source.setWindowTitle(QTStr("ConfirmRemove.Title"));
|
|
|
|
remove_source.exec();
|
|
|
|
|
|
|
|
return Yes == remove_source.clickedButton();
|
2014-06-30 13:45:58 -07:00
|
|
|
}
|
2014-06-30 01:13:32 -07:00
|
|
|
|
2014-07-13 23:56:28 -07:00
|
|
|
#define UPDATE_CHECK_INTERVAL (60*60*24*4) /* 4 days */
|
|
|
|
|
2014-10-05 15:32:18 -07:00
|
|
|
#ifdef UPDATE_SPARKLE
|
|
|
|
void init_sparkle_updater(bool update_to_undeployed);
|
|
|
|
void trigger_sparkle_update();
|
|
|
|
#endif
|
|
|
|
|
2014-07-13 23:56:28 -07:00
|
|
|
void OBSBasic::TimedCheckForUpdates()
|
|
|
|
{
|
2014-10-05 15:32:18 -07:00
|
|
|
#ifdef UPDATE_SPARKLE
|
|
|
|
init_sparkle_updater(config_get_bool(App()->GlobalConfig(), "General",
|
|
|
|
"UpdateToUndeployed"));
|
|
|
|
#else
|
2014-07-13 23:56:28 -07:00
|
|
|
long long lastUpdate = config_get_int(App()->GlobalConfig(), "General",
|
|
|
|
"LastUpdateCheck");
|
|
|
|
uint32_t lastVersion = config_get_int(App()->GlobalConfig(), "General",
|
|
|
|
"LastVersion");
|
|
|
|
|
|
|
|
if (lastVersion < LIBOBS_API_VER) {
|
|
|
|
lastUpdate = 0;
|
|
|
|
config_set_int(App()->GlobalConfig(), "General",
|
|
|
|
"LastUpdateCheck", 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
long long t = (long long)time(nullptr);
|
|
|
|
long long secs = t - lastUpdate;
|
|
|
|
|
|
|
|
if (secs > UPDATE_CHECK_INTERVAL)
|
|
|
|
CheckForUpdates();
|
2014-10-05 15:32:18 -07:00
|
|
|
#endif
|
2014-07-13 23:56:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::CheckForUpdates()
|
|
|
|
{
|
2014-10-05 15:32:18 -07:00
|
|
|
#ifdef UPDATE_SPARKLE
|
|
|
|
trigger_sparkle_update();
|
|
|
|
#else
|
2014-07-13 23:56:28 -07:00
|
|
|
ui->actionCheckForUpdates->setEnabled(false);
|
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
if (updateCheckThread) {
|
|
|
|
updateCheckThread->wait();
|
|
|
|
delete updateCheckThread;
|
|
|
|
}
|
2014-07-14 08:51:57 -07:00
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
RemoteTextThread *thread = new RemoteTextThread(
|
|
|
|
"https://obsproject.com/obs2_update/basic.json");
|
|
|
|
updateCheckThread = thread;
|
|
|
|
connect(thread, &RemoteTextThread::Result,
|
|
|
|
this, &OBSBasic::updateFileFinished);
|
|
|
|
updateCheckThread->start();
|
2014-10-05 15:32:18 -07:00
|
|
|
#endif
|
2014-07-13 23:56:28 -07:00
|
|
|
}
|
|
|
|
|
2014-07-14 03:48:30 -07:00
|
|
|
#ifdef __APPLE__
|
|
|
|
#define VERSION_ENTRY "mac"
|
2014-07-17 07:03:27 -07:00
|
|
|
#elif _WIN32
|
|
|
|
#define VERSION_ENTRY "windows"
|
2014-07-14 03:48:30 -07:00
|
|
|
#else
|
|
|
|
#define VERSION_ENTRY "other"
|
|
|
|
#endif
|
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
void OBSBasic::updateFileFinished(const QString &text, const QString &error)
|
2014-07-13 23:56:28 -07:00
|
|
|
{
|
|
|
|
ui->actionCheckForUpdates->setEnabled(true);
|
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
if (text.isEmpty()) {
|
|
|
|
blog(LOG_WARNING, "Update check failed: %s", QT_TO_UTF8(error));
|
2014-07-13 23:56:28 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
obs_data_t *returnData = obs_data_create_from_json(QT_TO_UTF8(text));
|
2014-08-25 12:22:58 -07:00
|
|
|
obs_data_t *versionData = obs_data_get_obj(returnData, VERSION_ENTRY);
|
2014-08-05 11:09:29 -07:00
|
|
|
const char *description = obs_data_get_string(returnData,
|
|
|
|
"description");
|
|
|
|
const char *download = obs_data_get_string(versionData, "download");
|
2014-07-13 23:56:28 -07:00
|
|
|
|
|
|
|
if (returnData && versionData && description && download) {
|
2014-08-05 11:09:29 -07:00
|
|
|
long major = obs_data_get_int(versionData, "major");
|
|
|
|
long minor = obs_data_get_int(versionData, "minor");
|
|
|
|
long patch = obs_data_get_int(versionData, "patch");
|
2014-07-13 23:56:28 -07:00
|
|
|
long version = MAKE_SEMANTIC_VERSION(major, minor, patch);
|
|
|
|
|
|
|
|
blog(LOG_INFO, "Update check: latest version is: %ld.%ld.%ld",
|
|
|
|
major, minor, patch);
|
|
|
|
|
|
|
|
if (version > LIBOBS_API_VER) {
|
|
|
|
QString str = QTStr("UpdateAvailable.Text");
|
|
|
|
QMessageBox messageBox(this);
|
|
|
|
|
|
|
|
str = str.arg(QString::number(major),
|
|
|
|
QString::number(minor),
|
|
|
|
QString::number(patch),
|
|
|
|
download);
|
|
|
|
|
|
|
|
messageBox.setWindowTitle(QTStr("UpdateAvailable"));
|
|
|
|
messageBox.setTextFormat(Qt::RichText);
|
|
|
|
messageBox.setText(str);
|
|
|
|
messageBox.setInformativeText(QT_UTF8(description));
|
|
|
|
messageBox.exec();
|
|
|
|
|
|
|
|
long long t = (long long)time(nullptr);
|
|
|
|
config_set_int(App()->GlobalConfig(), "General",
|
|
|
|
"LastUpdateCheck", t);
|
|
|
|
config_save(App()->GlobalConfig());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
blog(LOG_WARNING, "Bad JSON file received from server");
|
|
|
|
}
|
|
|
|
|
|
|
|
obs_data_release(versionData);
|
|
|
|
obs_data_release(returnData);
|
|
|
|
}
|
|
|
|
|
2014-06-30 13:45:58 -07:00
|
|
|
void OBSBasic::RemoveSelectedScene()
|
|
|
|
{
|
|
|
|
OBSScene scene = GetCurrentScene();
|
|
|
|
if (scene) {
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_scene_get_source(scene);
|
2014-06-30 13:45:58 -07:00
|
|
|
if (QueryRemoveSource(source))
|
|
|
|
obs_source_remove(source);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::RemoveSelectedSceneItem()
|
|
|
|
{
|
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
|
|
|
if (item) {
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_sceneitem_get_source(item);
|
2014-06-30 13:45:58 -07:00
|
|
|
if (QueryRemoveSource(source))
|
2014-06-30 01:13:32 -07:00
|
|
|
obs_sceneitem_remove(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-19 11:02:54 -08:00
|
|
|
struct ReorderInfo {
|
|
|
|
int idx = 0;
|
|
|
|
OBSBasic *window;
|
|
|
|
|
|
|
|
inline ReorderInfo(OBSBasic *window_) : window(window_) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
void OBSBasic::ReorderSceneItem(obs_sceneitem_t *item, size_t idx)
|
|
|
|
{
|
|
|
|
int count = ui->sources->count();
|
|
|
|
int idx_inv = count - (int)idx - 1;
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
QListWidgetItem *listItem = ui->sources->item(i);
|
2015-06-27 18:21:45 -07:00
|
|
|
OBSSceneItem sceneItem = GetOBSRef<OBSSceneItem>(listItem);
|
2015-02-19 11:02:54 -08:00
|
|
|
|
|
|
|
if (sceneItem == item) {
|
|
|
|
if ((int)idx_inv != i) {
|
|
|
|
bool sel = (ui->sources->currentRow() == i);
|
|
|
|
|
2015-06-27 18:18:40 -07:00
|
|
|
listItem = TakeListItem(ui->sources, i);
|
2015-02-19 11:02:54 -08:00
|
|
|
if (listItem) {
|
|
|
|
ui->sources->insertItem(idx_inv,
|
|
|
|
listItem);
|
2015-03-22 20:51:21 -07:00
|
|
|
SetupVisibilityItem(ui->sources,
|
|
|
|
listItem, item);
|
|
|
|
|
2015-02-19 11:02:54 -08:00
|
|
|
if (sel)
|
|
|
|
ui->sources->setCurrentRow(
|
|
|
|
idx_inv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::ReorderSources(OBSScene scene)
|
|
|
|
{
|
|
|
|
ReorderInfo info(this);
|
|
|
|
|
2015-06-26 19:00:24 -07:00
|
|
|
if (scene != GetCurrentScene() || ui->sources->IgnoreReorder())
|
2015-02-19 11:02:54 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
obs_scene_enum_items(scene,
|
|
|
|
[] (obs_scene_t*, obs_sceneitem_t *item, void *p)
|
|
|
|
{
|
|
|
|
ReorderInfo *info =
|
|
|
|
reinterpret_cast<ReorderInfo*>(p);
|
|
|
|
|
|
|
|
info->window->ReorderSceneItem(item,
|
|
|
|
info->idx++);
|
|
|
|
return true;
|
|
|
|
}, &info);
|
2015-06-30 05:49:31 -07:00
|
|
|
|
|
|
|
SaveProject();
|
2015-02-19 11:02:54 -08:00
|
|
|
}
|
|
|
|
|
2014-01-04 12:53:36 -08:00
|
|
|
/* OBS Callbacks */
|
|
|
|
|
2015-02-19 11:02:54 -08:00
|
|
|
void OBSBasic::SceneReordered(void *data, calldata_t *params)
|
|
|
|
{
|
|
|
|
OBSBasic *window = static_cast<OBSBasic*>(data);
|
|
|
|
|
|
|
|
obs_scene_t *scene = (obs_scene_t*)calldata_ptr(params, "scene");
|
|
|
|
|
|
|
|
QMetaObject::invokeMethod(window, "ReorderSources",
|
|
|
|
Q_ARG(OBSScene, OBSScene(scene)));
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::SceneItemAdded(void *data, calldata_t *params)
|
2014-01-04 12:53:36 -08:00
|
|
|
{
|
|
|
|
OBSBasic *window = static_cast<OBSBasic*>(data);
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_sceneitem_t *item = (obs_sceneitem_t*)calldata_ptr(params, "item");
|
2013-12-28 21:29:13 -08:00
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
QMetaObject::invokeMethod(window, "AddSceneItem",
|
|
|
|
Q_ARG(OBSSceneItem, OBSSceneItem(item)));
|
2013-12-28 21:29:13 -08:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::SceneItemRemoved(void *data, calldata_t *params)
|
2013-12-28 04:33:16 -08:00
|
|
|
{
|
2014-01-04 12:53:36 -08:00
|
|
|
OBSBasic *window = static_cast<OBSBasic*>(data);
|
2013-12-28 04:33:16 -08:00
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_sceneitem_t *item = (obs_sceneitem_t*)calldata_ptr(params, "item");
|
2014-01-04 12:53:36 -08:00
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
QMetaObject::invokeMethod(window, "RemoveSceneItem",
|
|
|
|
Q_ARG(OBSSceneItem, OBSSceneItem(item)));
|
2014-01-04 12:53:36 -08:00
|
|
|
}
|
|
|
|
|
2014-10-13 13:14:06 -07:00
|
|
|
void OBSBasic::SceneItemSelected(void *data, calldata_t *params)
|
|
|
|
{
|
|
|
|
OBSBasic *window = static_cast<OBSBasic*>(data);
|
|
|
|
|
|
|
|
obs_scene_t *scene = (obs_scene_t*)calldata_ptr(params, "scene");
|
|
|
|
obs_sceneitem_t *item = (obs_sceneitem_t*)calldata_ptr(params, "item");
|
|
|
|
|
|
|
|
QMetaObject::invokeMethod(window, "SelectSceneItem",
|
|
|
|
Q_ARG(OBSScene, scene), Q_ARG(OBSSceneItem, item),
|
|
|
|
Q_ARG(bool, true));
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::SceneItemDeselected(void *data, calldata_t *params)
|
|
|
|
{
|
|
|
|
OBSBasic *window = static_cast<OBSBasic*>(data);
|
|
|
|
|
|
|
|
obs_scene_t *scene = (obs_scene_t*)calldata_ptr(params, "scene");
|
|
|
|
obs_sceneitem_t *item = (obs_sceneitem_t*)calldata_ptr(params, "item");
|
|
|
|
|
|
|
|
QMetaObject::invokeMethod(window, "SelectSceneItem",
|
|
|
|
Q_ARG(OBSScene, scene), Q_ARG(OBSSceneItem, item),
|
|
|
|
Q_ARG(bool, false));
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::SourceAdded(void *data, calldata_t *params)
|
2014-01-04 12:53:36 -08:00
|
|
|
{
|
2014-05-10 18:47:48 -07:00
|
|
|
OBSBasic *window = static_cast<OBSBasic*>(data);
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = (obs_source_t*)calldata_ptr(params, "source");
|
2013-12-28 04:33:16 -08:00
|
|
|
|
2014-08-04 08:41:15 -07:00
|
|
|
if (obs_scene_from_source(source) != NULL)
|
2014-05-10 18:47:48 -07:00
|
|
|
QMetaObject::invokeMethod(window,
|
2014-02-02 16:03:55 -08:00
|
|
|
"AddScene",
|
|
|
|
Q_ARG(OBSSource, OBSSource(source)));
|
2013-12-28 04:33:16 -08:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::SourceRemoved(void *data, calldata_t *params)
|
2013-12-28 04:33:16 -08:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = (obs_source_t*)calldata_ptr(params, "source");
|
2013-12-28 04:33:16 -08:00
|
|
|
|
2014-08-04 08:41:15 -07:00
|
|
|
if (obs_scene_from_source(source) != NULL)
|
2014-02-02 16:03:55 -08:00
|
|
|
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
|
|
|
|
"RemoveScene",
|
|
|
|
Q_ARG(OBSSource, OBSSource(source)));
|
2013-12-28 04:33:16 -08:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::SourceActivated(void *data, calldata_t *params)
|
2014-05-03 22:54:38 -07:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = (obs_source_t*)calldata_ptr(params, "source");
|
2014-05-03 22:54:38 -07:00
|
|
|
uint32_t flags = obs_source_get_output_flags(source);
|
|
|
|
|
|
|
|
if (flags & OBS_SOURCE_AUDIO)
|
|
|
|
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
|
|
|
|
"ActivateAudioSource",
|
|
|
|
Q_ARG(OBSSource, OBSSource(source)));
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::SourceDeactivated(void *data, calldata_t *params)
|
2014-05-03 22:54:38 -07:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = (obs_source_t*)calldata_ptr(params, "source");
|
2014-05-03 22:54:38 -07:00
|
|
|
uint32_t flags = obs_source_get_output_flags(source);
|
|
|
|
|
|
|
|
if (flags & OBS_SOURCE_AUDIO)
|
|
|
|
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
|
|
|
|
"DeactivateAudioSource",
|
|
|
|
Q_ARG(OBSSource, OBSSource(source)));
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::SourceRenamed(void *data, calldata_t *params)
|
2014-06-30 00:06:01 -07:00
|
|
|
{
|
|
|
|
const char *newName = calldata_string(params, "new_name");
|
|
|
|
const char *prevName = calldata_string(params, "prev_name");
|
|
|
|
|
|
|
|
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
|
|
|
|
"RenameSources",
|
|
|
|
Q_ARG(QString, QT_UTF8(newName)),
|
|
|
|
Q_ARG(QString, QT_UTF8(prevName)));
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::ChannelChanged(void *data, calldata_t *params)
|
2014-01-04 12:53:36 -08:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = (obs_source_t*)calldata_ptr(params, "source");
|
2014-03-01 04:54:55 -08:00
|
|
|
uint32_t channel = (uint32_t)calldata_int(params, "channel");
|
2014-01-04 12:53:36 -08:00
|
|
|
|
|
|
|
if (channel == 0)
|
2014-02-02 16:03:55 -08:00
|
|
|
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
|
|
|
|
"UpdateSceneSelection",
|
|
|
|
Q_ARG(OBSSource, OBSSource(source)));
|
2014-01-04 12:53:36 -08:00
|
|
|
}
|
|
|
|
|
2014-06-15 19:48:02 -07:00
|
|
|
void OBSBasic::DrawBackdrop(float cx, float cy)
|
|
|
|
{
|
|
|
|
if (!box)
|
|
|
|
return;
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
gs_effect_t *solid = obs_get_solid_effect();
|
|
|
|
gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
|
|
|
|
gs_technique_t *tech = gs_effect_get_technique(solid, "Solid");
|
2014-06-15 19:48:02 -07:00
|
|
|
|
|
|
|
vec4 colorVal;
|
|
|
|
vec4_set(&colorVal, 0.0f, 0.0f, 0.0f, 1.0f);
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_effect_set_vec4(color, &colorVal);
|
2014-06-15 19:48:02 -07:00
|
|
|
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_technique_begin(tech);
|
|
|
|
gs_technique_begin_pass(tech, 0);
|
2014-06-15 19:48:02 -07:00
|
|
|
gs_matrix_push();
|
|
|
|
gs_matrix_identity();
|
|
|
|
gs_matrix_scale3f(float(cx), float(cy), 1.0f);
|
|
|
|
|
|
|
|
gs_load_vertexbuffer(box);
|
|
|
|
gs_draw(GS_TRISTRIP, 0, 0);
|
|
|
|
|
|
|
|
gs_matrix_pop();
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_technique_end_pass(tech);
|
|
|
|
gs_technique_end(tech);
|
2014-06-15 19:48:02 -07:00
|
|
|
|
|
|
|
gs_load_vertexbuffer(nullptr);
|
|
|
|
}
|
|
|
|
|
2014-02-13 07:58:31 -08:00
|
|
|
void OBSBasic::RenderMain(void *data, uint32_t cx, uint32_t cy)
|
|
|
|
{
|
2014-03-07 09:19:03 -08:00
|
|
|
OBSBasic *window = static_cast<OBSBasic*>(data);
|
2014-04-22 11:24:05 -07:00
|
|
|
obs_video_info ovi;
|
|
|
|
|
|
|
|
obs_get_video_info(&ovi);
|
|
|
|
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
window->previewCX = int(window->previewScale * float(ovi.base_width));
|
|
|
|
window->previewCY = int(window->previewScale * float(ovi.base_height));
|
2014-04-22 11:24:05 -07:00
|
|
|
|
|
|
|
gs_viewport_push();
|
|
|
|
gs_projection_push();
|
2014-06-15 19:48:02 -07:00
|
|
|
|
|
|
|
/* --------------------------------------- */
|
|
|
|
|
2014-04-22 11:24:05 -07:00
|
|
|
gs_ortho(0.0f, float(ovi.base_width), 0.0f, float(ovi.base_height),
|
|
|
|
-100.0f, 100.0f);
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_set_viewport(window->previewX, window->previewY,
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
window->previewCX, window->previewCY);
|
2014-04-22 11:24:05 -07:00
|
|
|
|
2014-06-15 19:48:02 -07:00
|
|
|
window->DrawBackdrop(float(ovi.base_width), float(ovi.base_height));
|
|
|
|
|
2014-02-13 09:21:16 -08:00
|
|
|
obs_render_main_view();
|
2014-06-15 19:48:02 -07:00
|
|
|
gs_load_vertexbuffer(nullptr);
|
2014-04-22 11:24:05 -07:00
|
|
|
|
2014-06-15 19:48:02 -07:00
|
|
|
/* --------------------------------------- */
|
|
|
|
|
2014-07-15 17:01:59 -07:00
|
|
|
QSize previewSize = GetPixelSize(window->ui->preview);
|
|
|
|
float right = float(previewSize.width()) - window->previewX;
|
|
|
|
float bottom = float(previewSize.height()) - window->previewY;
|
2014-06-15 19:48:02 -07:00
|
|
|
|
|
|
|
gs_ortho(-window->previewX, right,
|
|
|
|
-window->previewY, bottom,
|
|
|
|
-100.0f, 100.0f);
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_reset_viewport();
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
|
|
|
window->ui->preview->DrawSceneEditing();
|
|
|
|
|
2014-06-15 19:48:02 -07:00
|
|
|
/* --------------------------------------- */
|
|
|
|
|
2014-04-22 11:24:05 -07:00
|
|
|
gs_projection_pop();
|
|
|
|
gs_viewport_pop();
|
2014-02-14 14:13:36 -08:00
|
|
|
|
|
|
|
UNUSED_PARAMETER(cx);
|
|
|
|
UNUSED_PARAMETER(cy);
|
2014-02-13 07:58:31 -08:00
|
|
|
}
|
|
|
|
|
2014-01-04 12:53:36 -08:00
|
|
|
/* Main class functions */
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_service_t *OBSBasic::GetService()
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
{
|
2015-05-03 17:07:43 -07:00
|
|
|
if (!service) {
|
2014-11-01 13:41:17 -07:00
|
|
|
service = obs_service_create("rtmp_common", NULL, NULL,
|
|
|
|
nullptr);
|
2015-05-03 17:07:43 -07:00
|
|
|
obs_service_release(service);
|
|
|
|
}
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
return service;
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void OBSBasic::SetService(obs_service_t *newService)
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
{
|
2015-05-03 17:07:43 -07:00
|
|
|
if (newService)
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
service = newService;
|
|
|
|
}
|
|
|
|
|
2015-02-07 08:09:57 -08:00
|
|
|
bool OBSBasic::StreamingActive()
|
|
|
|
{
|
|
|
|
if (!outputHandler)
|
|
|
|
return false;
|
|
|
|
return outputHandler->StreamingActive();
|
|
|
|
}
|
|
|
|
|
2014-07-20 17:49:54 -07:00
|
|
|
#ifdef _WIN32
|
|
|
|
#define IS_WIN32 1
|
|
|
|
#else
|
|
|
|
#define IS_WIN32 0
|
|
|
|
#endif
|
|
|
|
|
2014-07-20 17:49:09 -07:00
|
|
|
static inline int AttemptToResetVideo(struct obs_video_info *ovi)
|
|
|
|
{
|
|
|
|
int ret = obs_reset_video(ovi);
|
|
|
|
if (ret == OBS_VIDEO_INVALID_PARAM) {
|
|
|
|
struct obs_video_info new_params = *ovi;
|
|
|
|
|
|
|
|
if (new_params.window_width == 0)
|
|
|
|
new_params.window_width = 512;
|
|
|
|
if (new_params.window_height == 0)
|
|
|
|
new_params.window_height = 512;
|
|
|
|
|
|
|
|
new_params.output_width = new_params.window_width;
|
|
|
|
new_params.output_height = new_params.window_height;
|
|
|
|
new_params.base_width = new_params.window_width;
|
|
|
|
new_params.base_height = new_params.window_height;
|
|
|
|
ret = obs_reset_video(&new_params);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-12-15 01:08:46 -08:00
|
|
|
static inline enum obs_scale_type GetScaleType(ConfigFile &basicConfig)
|
|
|
|
{
|
|
|
|
const char *scaleTypeStr = config_get_string(basicConfig,
|
|
|
|
"Video", "ScaleType");
|
|
|
|
|
|
|
|
if (astrcmpi(scaleTypeStr, "bilinear") == 0)
|
|
|
|
return OBS_SCALE_BILINEAR;
|
|
|
|
else if (astrcmpi(scaleTypeStr, "lanczos") == 0)
|
|
|
|
return OBS_SCALE_LANCZOS;
|
|
|
|
else
|
|
|
|
return OBS_SCALE_BICUBIC;
|
|
|
|
}
|
|
|
|
|
2015-01-09 20:16:30 -08:00
|
|
|
static inline enum video_format GetVideoFormatFromName(const char *name)
|
|
|
|
{
|
|
|
|
if (astrcmpi(name, "I420") == 0)
|
|
|
|
return VIDEO_FORMAT_I420;
|
|
|
|
else if (astrcmpi(name, "NV12") == 0)
|
|
|
|
return VIDEO_FORMAT_NV12;
|
2015-04-17 02:46:48 -07:00
|
|
|
else if (astrcmpi(name, "I444") == 0)
|
|
|
|
return VIDEO_FORMAT_I444;
|
2015-01-09 20:16:30 -08:00
|
|
|
#if 0 //currently unsupported
|
|
|
|
else if (astrcmpi(name, "YVYU") == 0)
|
|
|
|
return VIDEO_FORMAT_YVYU;
|
|
|
|
else if (astrcmpi(name, "YUY2") == 0)
|
|
|
|
return VIDEO_FORMAT_YUY2;
|
|
|
|
else if (astrcmpi(name, "UYVY") == 0)
|
|
|
|
return VIDEO_FORMAT_UYVY;
|
|
|
|
#endif
|
|
|
|
else
|
2015-04-15 18:42:06 -07:00
|
|
|
return VIDEO_FORMAT_RGBA;
|
2015-01-09 20:16:30 -08:00
|
|
|
}
|
|
|
|
|
2014-07-20 17:40:57 -07:00
|
|
|
int OBSBasic::ResetVideo()
|
2013-12-22 22:40:07 -08:00
|
|
|
{
|
|
|
|
struct obs_video_info ovi;
|
2014-07-20 17:40:57 -07:00
|
|
|
int ret;
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
|
2014-03-06 20:08:12 -08:00
|
|
|
GetConfigFPS(ovi.fps_num, ovi.fps_den);
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
|
2015-01-09 20:16:30 -08:00
|
|
|
const char *colorFormat = config_get_string(basicConfig, "Video",
|
|
|
|
"ColorFormat");
|
|
|
|
const char *colorSpace = config_get_string(basicConfig, "Video",
|
|
|
|
"ColorSpace");
|
|
|
|
const char *colorRange = config_get_string(basicConfig, "Video",
|
|
|
|
"ColorRange");
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
ovi.graphics_module = App()->GetRenderModule();
|
2014-03-06 20:08:12 -08:00
|
|
|
ovi.base_width = (uint32_t)config_get_uint(basicConfig,
|
2013-12-22 22:40:07 -08:00
|
|
|
"Video", "BaseCX");
|
2014-03-06 20:08:12 -08:00
|
|
|
ovi.base_height = (uint32_t)config_get_uint(basicConfig,
|
2013-12-22 22:40:07 -08:00
|
|
|
"Video", "BaseCY");
|
2014-03-06 20:08:12 -08:00
|
|
|
ovi.output_width = (uint32_t)config_get_uint(basicConfig,
|
2013-12-22 22:40:07 -08:00
|
|
|
"Video", "OutputCX");
|
2014-03-06 20:08:12 -08:00
|
|
|
ovi.output_height = (uint32_t)config_get_uint(basicConfig,
|
2013-12-22 22:40:07 -08:00
|
|
|
"Video", "OutputCY");
|
2015-01-09 20:16:30 -08:00
|
|
|
ovi.output_format = GetVideoFormatFromName(colorFormat);
|
|
|
|
ovi.colorspace = astrcmpi(colorSpace, "601") == 0 ?
|
|
|
|
VIDEO_CS_601 : VIDEO_CS_709;
|
|
|
|
ovi.range = astrcmpi(colorRange, "Full") == 0 ?
|
|
|
|
VIDEO_RANGE_FULL : VIDEO_RANGE_PARTIAL;
|
2014-02-16 18:28:21 -08:00
|
|
|
ovi.adapter = 0;
|
|
|
|
ovi.gpu_conversion = true;
|
2014-12-15 01:08:46 -08:00
|
|
|
ovi.scale_type = GetScaleType(basicConfig);
|
2014-01-09 17:51:51 -08:00
|
|
|
|
2014-03-07 09:19:03 -08:00
|
|
|
QTToGSWindow(ui->preview->winId(), ovi.window);
|
2013-12-22 22:40:07 -08:00
|
|
|
|
|
|
|
//required to make opengl display stuff on osx(?)
|
2013-12-31 03:02:07 -08:00
|
|
|
ResizePreview(ovi.base_width, ovi.base_height);
|
2013-12-22 22:40:07 -08:00
|
|
|
|
2014-04-16 11:28:02 -07:00
|
|
|
QSize size = GetPixelSize(ui->preview);
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
ovi.window_width = size.width();
|
|
|
|
ovi.window_height = size.height();
|
2013-12-31 03:02:07 -08:00
|
|
|
|
2014-07-20 17:49:09 -07:00
|
|
|
ret = AttemptToResetVideo(&ovi);
|
2014-07-20 17:49:54 -07:00
|
|
|
if (IS_WIN32 && ret != OBS_VIDEO_SUCCESS) {
|
|
|
|
/* Try OpenGL if DirectX fails on windows */
|
2015-01-09 11:19:22 -08:00
|
|
|
if (astrcmpi(ovi.graphics_module, DL_OPENGL) != 0) {
|
2014-10-14 09:07:49 -07:00
|
|
|
blog(LOG_WARNING, "Failed to initialize obs video (%d) "
|
|
|
|
"with graphics_module='%s', retrying "
|
|
|
|
"with graphics_module='%s'",
|
|
|
|
ret, ovi.graphics_module,
|
2015-01-09 11:19:22 -08:00
|
|
|
DL_OPENGL);
|
|
|
|
ovi.graphics_module = DL_OPENGL;
|
2014-07-20 17:49:54 -07:00
|
|
|
ret = AttemptToResetVideo(&ovi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-20 17:40:57 -07:00
|
|
|
if (ret == OBS_VIDEO_SUCCESS)
|
|
|
|
obs_add_draw_callback(OBSBasic::RenderMain, this);
|
2014-02-22 19:14:19 -08:00
|
|
|
|
2014-07-20 17:40:57 -07:00
|
|
|
return ret;
|
2014-01-09 18:08:20 -08:00
|
|
|
}
|
2013-12-31 03:02:07 -08:00
|
|
|
|
2014-02-22 19:14:19 -08:00
|
|
|
bool OBSBasic::ResetAudio()
|
2014-01-09 18:08:20 -08:00
|
|
|
{
|
2015-03-07 04:47:12 -08:00
|
|
|
struct obs_audio_info ai;
|
2014-03-06 20:08:12 -08:00
|
|
|
ai.samples_per_sec = config_get_uint(basicConfig, "Audio",
|
2014-02-23 15:27:19 -08:00
|
|
|
"SampleRate");
|
|
|
|
|
2014-03-06 20:08:12 -08:00
|
|
|
const char *channelSetupStr = config_get_string(basicConfig,
|
2014-02-23 15:27:19 -08:00
|
|
|
"Audio", "ChannelSetup");
|
|
|
|
|
|
|
|
if (strcmp(channelSetupStr, "Mono") == 0)
|
|
|
|
ai.speakers = SPEAKERS_MONO;
|
|
|
|
else
|
|
|
|
ai.speakers = SPEAKERS_STEREO;
|
|
|
|
|
2014-03-06 20:08:12 -08:00
|
|
|
ai.buffer_ms = config_get_uint(basicConfig, "Audio", "BufferingTime");
|
2014-01-09 18:08:20 -08:00
|
|
|
|
|
|
|
return obs_reset_audio(&ai);
|
2013-12-22 22:40:07 -08:00
|
|
|
}
|
|
|
|
|
2015-06-23 18:47:22 -07:00
|
|
|
void OBSBasic::ResetAudioDevice(const char *sourceId, const char *deviceId,
|
2014-05-12 15:30:36 -07:00
|
|
|
const char *deviceDesc, int channel)
|
2014-03-07 16:03:34 -08:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source;
|
|
|
|
obs_data_t *settings;
|
2014-03-07 16:03:34 -08:00
|
|
|
bool same = false;
|
|
|
|
|
|
|
|
source = obs_get_output_source(channel);
|
|
|
|
if (source) {
|
2014-08-04 08:41:15 -07:00
|
|
|
settings = obs_source_get_settings(source);
|
2014-08-05 11:09:29 -07:00
|
|
|
const char *curId = obs_data_get_string(settings, "device_id");
|
2014-03-07 16:03:34 -08:00
|
|
|
|
|
|
|
same = (strcmp(curId, deviceId) == 0);
|
|
|
|
|
|
|
|
obs_data_release(settings);
|
|
|
|
obs_source_release(source);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!same)
|
|
|
|
obs_set_output_source(channel, nullptr);
|
|
|
|
|
|
|
|
if (!same && strcmp(deviceId, "disabled") != 0) {
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_data_t *settings = obs_data_create();
|
2014-08-05 11:09:29 -07:00
|
|
|
obs_data_set_string(settings, "device_id", deviceId);
|
2014-03-07 16:03:34 -08:00
|
|
|
source = obs_source_create(OBS_SOURCE_TYPE_INPUT,
|
2014-11-01 13:41:17 -07:00
|
|
|
sourceId, deviceDesc, settings, nullptr);
|
2014-03-07 16:03:34 -08:00
|
|
|
obs_data_release(settings);
|
|
|
|
|
|
|
|
obs_set_output_source(channel, source);
|
|
|
|
obs_source_release(source);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-31 03:02:07 -08:00
|
|
|
void OBSBasic::ResizePreview(uint32_t cx, uint32_t cy)
|
2013-12-06 05:39:19 -08:00
|
|
|
{
|
2014-01-23 16:00:42 -08:00
|
|
|
QSize targetSize;
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
|
2013-12-06 08:16:33 -08:00
|
|
|
/* resize preview panel to fix to the top section of the window */
|
2014-04-16 11:28:02 -07:00
|
|
|
targetSize = GetPixelSize(ui->preview);
|
2014-03-23 01:07:54 -07:00
|
|
|
GetScaleAndCenterPos(int(cx), int(cy),
|
2014-06-15 19:48:02 -07:00
|
|
|
targetSize.width() - PREVIEW_EDGE_SIZE * 2,
|
|
|
|
targetSize.height() - PREVIEW_EDGE_SIZE * 2,
|
2014-03-23 01:07:54 -07:00
|
|
|
previewX, previewY, previewScale);
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
|
2014-06-15 19:48:02 -07:00
|
|
|
previewX += float(PREVIEW_EDGE_SIZE);
|
|
|
|
previewY += float(PREVIEW_EDGE_SIZE);
|
|
|
|
|
2014-03-07 09:19:03 -08:00
|
|
|
if (isVisible()) {
|
|
|
|
if (resizeTimer)
|
|
|
|
killTimer(resizeTimer);
|
|
|
|
resizeTimer = startTimer(100);
|
|
|
|
}
|
2013-12-31 03:02:07 -08:00
|
|
|
}
|
|
|
|
|
2015-07-02 16:12:47 -07:00
|
|
|
void OBSBasic::CloseDialogs()
|
|
|
|
{
|
|
|
|
QList<QDialog*> childDialogs = this->findChildren<QDialog *>();
|
|
|
|
if (!childDialogs.isEmpty()) {
|
|
|
|
for (int i = 0; i < childDialogs.size(); ++i) {
|
|
|
|
childDialogs.at(i)->close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (QPointer<QWidget> &projector : projectors) {
|
|
|
|
delete projector;
|
|
|
|
projector.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::ClearSceneData()
|
|
|
|
{
|
2015-06-30 05:49:31 -07:00
|
|
|
disableSaving++;
|
|
|
|
|
2015-07-02 16:12:47 -07:00
|
|
|
CloseDialogs();
|
|
|
|
|
|
|
|
ClearVolumeControls();
|
|
|
|
ClearListItems(ui->scenes);
|
|
|
|
ClearListItems(ui->sources);
|
|
|
|
|
|
|
|
obs_set_output_source(0, nullptr);
|
|
|
|
obs_set_output_source(1, nullptr);
|
|
|
|
obs_set_output_source(2, nullptr);
|
|
|
|
obs_set_output_source(3, nullptr);
|
|
|
|
obs_set_output_source(4, nullptr);
|
|
|
|
obs_set_output_source(5, nullptr);
|
|
|
|
|
|
|
|
auto cb = [](void *unused, obs_source_t *source)
|
|
|
|
{
|
|
|
|
obs_source_remove(source);
|
|
|
|
UNUSED_PARAMETER(unused);
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
obs_enum_sources(cb, nullptr);
|
|
|
|
|
|
|
|
sourceSceneRefs.clear();
|
2015-06-30 05:49:31 -07:00
|
|
|
|
|
|
|
disableSaving--;
|
2015-07-02 16:12:47 -07:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::closeEvent(QCloseEvent *event)
|
2013-12-31 03:02:07 -08:00
|
|
|
{
|
2015-02-07 03:39:16 -08:00
|
|
|
if (outputHandler && outputHandler->Active()) {
|
|
|
|
QMessageBox::StandardButton button = QMessageBox::question(
|
|
|
|
this, QTStr("ConfirmExit.Title"),
|
|
|
|
QTStr("ConfirmExit.Text"));
|
|
|
|
|
|
|
|
if (button == QMessageBox::No) {
|
|
|
|
event->ignore();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-17 08:18:51 -07:00
|
|
|
QWidget::closeEvent(event);
|
|
|
|
if (!event->isAccepted())
|
|
|
|
return;
|
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
if (updateCheckThread)
|
|
|
|
updateCheckThread->wait();
|
|
|
|
if (logUploadThread)
|
|
|
|
logUploadThread->wait();
|
|
|
|
|
2015-06-27 00:29:17 -07:00
|
|
|
signalHandlers.clear();
|
|
|
|
|
2014-04-17 08:18:51 -07:00
|
|
|
// remove draw callback in case our drawable surfaces go away before
|
|
|
|
// the destructor gets called
|
|
|
|
obs_remove_draw_callback(OBSBasic::RenderMain, this);
|
2015-03-18 06:19:18 -07:00
|
|
|
|
|
|
|
SaveProject();
|
2015-06-30 05:49:31 -07:00
|
|
|
disableSaving++;
|
2015-03-18 07:02:58 -07:00
|
|
|
|
2015-07-02 16:12:47 -07:00
|
|
|
/* Clear all scene data (dialogs, widgets, widget sub-items, scenes,
|
|
|
|
* sources, etc) so that all references are released before shutdown */
|
|
|
|
ClearSceneData();
|
2013-12-31 06:10:47 -08:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::changeEvent(QEvent *event)
|
2013-12-31 06:10:47 -08:00
|
|
|
{
|
2014-02-14 14:13:36 -08:00
|
|
|
/* TODO */
|
|
|
|
UNUSED_PARAMETER(event);
|
2013-11-23 22:38:52 -08:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::resizeEvent(QResizeEvent *event)
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
struct obs_video_info ovi;
|
|
|
|
|
|
|
|
if (obs_get_video_info(&ovi))
|
|
|
|
ResizePreview(ovi.base_width, ovi.base_height);
|
2014-02-14 14:13:36 -08:00
|
|
|
|
|
|
|
UNUSED_PARAMETER(event);
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
|
|
|
|
2014-03-07 09:19:03 -08:00
|
|
|
void OBSBasic::timerEvent(QTimerEvent *event)
|
|
|
|
{
|
|
|
|
if (event->timerId() == resizeTimer) {
|
|
|
|
killTimer(resizeTimer);
|
|
|
|
resizeTimer = 0;
|
|
|
|
|
2014-04-16 11:28:02 -07:00
|
|
|
QSize size = GetPixelSize(ui->preview);
|
2014-03-07 09:19:03 -08:00
|
|
|
obs_resize(size.width(), size.height());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-21 18:18:42 -07:00
|
|
|
void OBSBasic::on_actionShow_Recordings_triggered()
|
|
|
|
{
|
2015-06-04 11:15:56 -07:00
|
|
|
const char *mode = config_get_string(basicConfig, "Output", "Mode");
|
|
|
|
const char *path = strcmp(mode, "Advanced") ?
|
|
|
|
config_get_string(basicConfig, "SimpleOutput", "FilePath") :
|
|
|
|
config_get_string(basicConfig, "AdvOut", "RecFilePath");
|
2014-08-21 18:18:42 -07:00
|
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
|
|
|
}
|
|
|
|
|
2014-09-02 19:11:55 -07:00
|
|
|
void OBSBasic::on_actionRemux_triggered()
|
|
|
|
{
|
2015-06-04 11:15:56 -07:00
|
|
|
const char *mode = config_get_string(basicConfig, "Output", "Mode");
|
|
|
|
const char *path = strcmp(mode, "Advanced") ?
|
|
|
|
config_get_string(basicConfig, "SimpleOutput", "FilePath") :
|
|
|
|
config_get_string(basicConfig, "AdvOut", "RecFilePath");
|
2014-09-02 19:11:55 -07:00
|
|
|
OBSRemux remux(path, this);
|
|
|
|
remux.exec();
|
|
|
|
}
|
|
|
|
|
2014-04-15 05:19:59 -07:00
|
|
|
void OBSBasic::on_action_Settings_triggered()
|
|
|
|
{
|
|
|
|
OBSBasicSettings settings(this);
|
|
|
|
settings.exec();
|
|
|
|
}
|
|
|
|
|
2014-12-28 00:38:00 -08:00
|
|
|
void OBSBasic::on_actionAdvAudioProperties_triggered()
|
|
|
|
{
|
2015-02-13 04:06:55 -08:00
|
|
|
if (advAudioWindow != nullptr) {
|
|
|
|
advAudioWindow->raise();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-12-28 00:38:00 -08:00
|
|
|
advAudioWindow = new OBSBasicAdvAudio(this);
|
|
|
|
advAudioWindow->show();
|
|
|
|
advAudioWindow->setAttribute(Qt::WA_DeleteOnClose, true);
|
2015-02-13 04:06:55 -08:00
|
|
|
|
|
|
|
connect(advAudioWindow, SIGNAL(destroyed()),
|
|
|
|
this, SLOT(on_advAudioProps_destroyed()));
|
2014-12-28 00:38:00 -08:00
|
|
|
}
|
|
|
|
|
2015-02-07 02:11:42 -08:00
|
|
|
void OBSBasic::on_advAudioProps_clicked()
|
|
|
|
{
|
|
|
|
on_actionAdvAudioProperties_triggered();
|
|
|
|
}
|
|
|
|
|
2015-02-13 04:06:55 -08:00
|
|
|
void OBSBasic::on_advAudioProps_destroyed()
|
|
|
|
{
|
|
|
|
advAudioWindow = nullptr;
|
|
|
|
}
|
|
|
|
|
2014-02-20 21:04:14 -08:00
|
|
|
void OBSBasic::on_scenes_currentItemChanged(QListWidgetItem *current,
|
|
|
|
QListWidgetItem *prev)
|
2013-12-30 00:17:57 -08:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = NULL;
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
|
2014-02-20 21:04:14 -08:00
|
|
|
if (sceneChanging)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (current) {
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_scene_t *scene;
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
|
2015-06-27 18:21:45 -07:00
|
|
|
scene = GetOBSRef<OBSScene>(current);
|
2014-08-04 08:41:15 -07:00
|
|
|
source = obs_scene_get_source(scene);
|
2013-12-30 00:17:57 -08:00
|
|
|
}
|
|
|
|
|
2014-01-04 12:53:36 -08:00
|
|
|
/* TODO: allow transitions */
|
2013-12-30 00:17:57 -08:00
|
|
|
obs_set_output_source(0, source);
|
2014-02-20 21:04:14 -08:00
|
|
|
|
|
|
|
UNUSED_PARAMETER(prev);
|
2013-12-30 00:17:57 -08:00
|
|
|
}
|
|
|
|
|
2014-06-30 01:13:32 -07:00
|
|
|
void OBSBasic::EditSceneName()
|
|
|
|
{
|
2014-10-15 13:05:21 -07:00
|
|
|
QListWidgetItem *item = ui->scenes->currentItem();
|
|
|
|
Qt::ItemFlags flags = item->flags();
|
|
|
|
|
|
|
|
item->setFlags(flags | Qt::ItemIsEditable);
|
|
|
|
ui->scenes->editItem(item);
|
|
|
|
item->setFlags(flags);
|
2014-06-30 01:13:32 -07:00
|
|
|
}
|
|
|
|
|
2015-04-04 01:40:15 -07:00
|
|
|
static void AddProjectorMenuMonitors(QMenu *parent, QObject *target,
|
|
|
|
const char *slot)
|
|
|
|
{
|
|
|
|
QAction *action;
|
|
|
|
std::vector<MonitorInfo> monitors;
|
|
|
|
GetMonitors(monitors);
|
|
|
|
|
|
|
|
for (int i = 0; (size_t)i < monitors.size(); i++) {
|
|
|
|
const MonitorInfo &monitor = monitors[i];
|
|
|
|
|
|
|
|
QString str = QString("%1 %2: %3x%4 @ %5,%6").
|
|
|
|
arg(QTStr("Display"),
|
|
|
|
QString::number(i),
|
|
|
|
QString::number((int)monitor.cx),
|
|
|
|
QString::number((int)monitor.cy),
|
|
|
|
QString::number((int)monitor.x),
|
|
|
|
QString::number((int)monitor.y));
|
|
|
|
|
|
|
|
action = parent->addAction(str, target, slot);
|
|
|
|
action->setProperty("monitor", i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_scenes_customContextMenuRequested(const QPoint &pos)
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
2014-06-30 16:03:12 -07:00
|
|
|
QListWidgetItem *item = ui->scenes->itemAt(pos);
|
2015-04-04 01:40:15 -07:00
|
|
|
QPointer<QMenu> sceneProjectorMenu;
|
2014-06-30 16:03:12 -07:00
|
|
|
|
2015-01-16 01:21:11 -08:00
|
|
|
QMenu popup(this);
|
2015-06-25 03:53:48 -07:00
|
|
|
QMenu order(QTStr("Basic.MainMenu.Edit.Order"), this);
|
2014-06-30 16:03:12 -07:00
|
|
|
popup.addAction(QTStr("Add"),
|
|
|
|
this, SLOT(on_actionAddScene_triggered()));
|
|
|
|
|
2014-10-15 13:04:31 -07:00
|
|
|
if (item) {
|
|
|
|
popup.addSeparator();
|
|
|
|
popup.addAction(QTStr("Rename"),
|
|
|
|
this, SLOT(EditSceneName()));
|
2014-06-30 16:03:12 -07:00
|
|
|
popup.addAction(QTStr("Remove"),
|
2014-10-15 13:01:49 -07:00
|
|
|
this, SLOT(RemoveSelectedScene()),
|
|
|
|
DeleteKeys.front());
|
2015-03-18 15:09:44 -07:00
|
|
|
popup.addSeparator();
|
2015-06-25 03:53:48 -07:00
|
|
|
|
|
|
|
order.addAction(QTStr("Basic.MainMenu.Edit.Order.MoveUp"),
|
|
|
|
this, SLOT(on_actionSceneUp_triggered()));
|
|
|
|
order.addAction(QTStr("Basic.MainMenu.Edit.Order.MoveDown"),
|
|
|
|
this, SLOT(on_actionSceneDown_triggered()));
|
|
|
|
order.addSeparator();
|
|
|
|
order.addAction(QTStr("Basic.MainMenu.Edit.Order.MoveToTop"),
|
|
|
|
this, SLOT(MoveSceneToTop()));
|
|
|
|
order.addAction(QTStr("Basic.MainMenu.Edit.Order.MoveToBottom"),
|
|
|
|
this, SLOT(MoveSceneToBottom()));
|
|
|
|
popup.addMenu(&order);
|
|
|
|
|
|
|
|
popup.addSeparator();
|
2015-04-04 01:40:15 -07:00
|
|
|
sceneProjectorMenu = new QMenu(QTStr("SceneProjector"));
|
|
|
|
AddProjectorMenuMonitors(sceneProjectorMenu, this,
|
|
|
|
SLOT(OpenSceneProjector()));
|
|
|
|
popup.addMenu(sceneProjectorMenu);
|
|
|
|
popup.addSeparator();
|
2015-03-18 15:09:44 -07:00
|
|
|
popup.addAction(QTStr("Filters"), this,
|
|
|
|
SLOT(OpenSceneFilters()));
|
2014-10-15 13:04:31 -07:00
|
|
|
}
|
2014-06-30 16:03:12 -07:00
|
|
|
|
|
|
|
popup.exec(QCursor::pos());
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_actionAddScene_triggered()
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
2013-12-29 07:54:06 -08:00
|
|
|
string name;
|
2014-05-09 15:09:17 -07:00
|
|
|
QString format{QTStr("Basic.Main.DefaultSceneName.Text")};
|
2014-05-14 11:58:15 -07:00
|
|
|
|
|
|
|
int i = 1;
|
|
|
|
QString placeHolderText = format.arg(i);
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = nullptr;
|
2014-05-14 13:20:08 -07:00
|
|
|
while ((source = obs_get_source_by_name(QT_TO_UTF8(placeHolderText)))) {
|
|
|
|
obs_source_release(source);
|
2014-05-14 11:58:15 -07:00
|
|
|
placeHolderText = format.arg(++i);
|
2014-05-14 13:20:08 -07:00
|
|
|
}
|
2014-05-09 15:09:17 -07:00
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
bool accepted = NameDialog::AskForName(this,
|
2014-05-12 15:30:36 -07:00
|
|
|
QTStr("Basic.Main.AddSceneDlg.Title"),
|
|
|
|
QTStr("Basic.Main.AddSceneDlg.Text"),
|
2014-05-09 15:09:17 -07:00
|
|
|
name,
|
|
|
|
placeHolderText);
|
2013-12-29 07:54:06 -08:00
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
if (accepted) {
|
2014-03-10 13:39:51 -07:00
|
|
|
if (name.empty()) {
|
|
|
|
QMessageBox::information(this,
|
2014-08-12 12:09:19 -07:00
|
|
|
QTStr("NoNameEntered.Title"),
|
|
|
|
QTStr("NoNameEntered.Text"));
|
2014-03-10 13:39:51 -07:00
|
|
|
on_actionAddScene_triggered();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_get_source_by_name(name.c_str());
|
2013-12-29 08:17:00 -08:00
|
|
|
if (source) {
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
QMessageBox::information(this,
|
2014-05-12 15:30:36 -07:00
|
|
|
QTStr("NameExists.Title"),
|
|
|
|
QTStr("NameExists.Text"));
|
2013-12-29 08:17:00 -08:00
|
|
|
|
|
|
|
obs_source_release(source);
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
on_actionAddScene_triggered();
|
2013-12-29 08:17:00 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_scene_t *scene = obs_scene_create(name.c_str());
|
2014-08-04 08:41:15 -07:00
|
|
|
source = obs_scene_get_source(scene);
|
2014-01-05 20:38:28 -08:00
|
|
|
obs_add_source(source);
|
2013-12-29 07:54:06 -08:00
|
|
|
obs_scene_release(scene);
|
2014-01-05 20:38:28 -08:00
|
|
|
|
|
|
|
obs_set_output_source(0, source);
|
2013-12-29 07:54:06 -08:00
|
|
|
}
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_actionRemoveScene_triggered()
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
2014-06-30 13:45:58 -07:00
|
|
|
OBSScene scene = GetCurrentScene();
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_scene_get_source(scene);
|
2014-06-30 13:45:58 -07:00
|
|
|
|
|
|
|
if (source && QueryRemoveSource(source))
|
|
|
|
obs_source_remove(source);
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
|
|
|
|
2015-06-25 03:53:48 -07:00
|
|
|
void OBSBasic::ChangeSceneIndex(bool relative, int offset, int invalidIdx)
|
|
|
|
{
|
|
|
|
int idx = ui->scenes->currentRow();
|
|
|
|
if (idx == -1 || idx == invalidIdx)
|
|
|
|
return;
|
|
|
|
|
|
|
|
sceneChanging = true;
|
|
|
|
|
|
|
|
QListWidgetItem *item = ui->scenes->takeItem(idx);
|
|
|
|
|
|
|
|
if (!relative)
|
|
|
|
idx = 0;
|
|
|
|
|
|
|
|
ui->scenes->insertItem(idx + offset, item);
|
|
|
|
ui->scenes->setCurrentRow(idx + offset);
|
|
|
|
item->setSelected(true);
|
|
|
|
|
|
|
|
sceneChanging = false;
|
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_actionSceneUp_triggered()
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
2015-06-25 03:53:48 -07:00
|
|
|
ChangeSceneIndex(true, -1, 0);
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_actionSceneDown_triggered()
|
2013-12-30 00:17:57 -08:00
|
|
|
{
|
2015-06-25 03:53:48 -07:00
|
|
|
ChangeSceneIndex(true, 1, ui->scenes->count() - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::MoveSceneToTop()
|
|
|
|
{
|
|
|
|
ChangeSceneIndex(false, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::MoveSceneToBottom()
|
|
|
|
{
|
|
|
|
ChangeSceneIndex(false, ui->scenes->count() - 1,
|
|
|
|
ui->scenes->count() - 1);
|
2013-12-30 00:17:57 -08:00
|
|
|
}
|
|
|
|
|
2014-02-20 21:04:14 -08:00
|
|
|
void OBSBasic::on_sources_currentItemChanged(QListWidgetItem *current,
|
|
|
|
QListWidgetItem *prev)
|
2013-12-30 00:17:57 -08:00
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
auto select_one = [] (obs_scene_t *scene, obs_sceneitem_t *item,
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
void *param)
|
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_sceneitem_t *selectedItem =
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
*reinterpret_cast<OBSSceneItem*>(param);
|
|
|
|
obs_sceneitem_select(item, (selectedItem == item));
|
|
|
|
|
|
|
|
UNUSED_PARAMETER(scene);
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!current)
|
|
|
|
return;
|
|
|
|
|
2015-06-27 18:21:45 -07:00
|
|
|
OBSSceneItem item = GetOBSRef<OBSSceneItem>(current);
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_sceneitem_get_source(item);
|
2014-07-04 10:58:03 -07:00
|
|
|
if ((obs_source_get_output_flags(source) & OBS_SOURCE_VIDEO) == 0)
|
|
|
|
return;
|
|
|
|
|
2015-06-26 18:32:33 -07:00
|
|
|
auto IgnoreSelfUpdate = [&](obs_scene_t *scene)
|
|
|
|
{
|
|
|
|
ignoreSelectionUpdate = true;
|
|
|
|
obs_scene_enum_items(scene, select_one, &item);
|
|
|
|
ignoreSelectionUpdate = false;
|
|
|
|
};
|
|
|
|
using IgnoreSelfUpdate_t = decltype(IgnoreSelfUpdate);
|
|
|
|
|
|
|
|
obs_scene_atomic_update(GetCurrentScene(),
|
|
|
|
[](void *data, obs_scene_t *scene)
|
|
|
|
{
|
|
|
|
(*static_cast<IgnoreSelfUpdate_t*>(data))(scene);
|
|
|
|
}, static_cast<void*>(&IgnoreSelfUpdate));
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
2014-02-20 21:04:14 -08:00
|
|
|
UNUSED_PARAMETER(prev);
|
2013-12-30 00:17:57 -08:00
|
|
|
}
|
|
|
|
|
2014-06-30 01:13:32 -07:00
|
|
|
void OBSBasic::EditSceneItemName()
|
|
|
|
{
|
2014-10-15 13:05:21 -07:00
|
|
|
QListWidgetItem *item = ui->sources->currentItem();
|
|
|
|
Qt::ItemFlags flags = item->flags();
|
2015-06-27 18:21:45 -07:00
|
|
|
OBSSceneItem sceneItem= GetOBSRef<OBSSceneItem>(item);
|
2015-03-22 20:51:21 -07:00
|
|
|
obs_source_t *source = obs_sceneitem_get_source(sceneItem);
|
|
|
|
const char *name = obs_source_get_name(source);
|
2014-10-15 13:05:21 -07:00
|
|
|
|
2015-03-22 20:51:21 -07:00
|
|
|
item->setText(QT_UTF8(name));
|
2014-10-15 13:05:21 -07:00
|
|
|
item->setFlags(flags | Qt::ItemIsEditable);
|
2015-03-22 20:51:21 -07:00
|
|
|
ui->sources->removeItemWidget(item);
|
2014-10-15 13:05:21 -07:00
|
|
|
ui->sources->editItem(item);
|
|
|
|
item->setFlags(flags);
|
2014-06-30 01:13:32 -07:00
|
|
|
}
|
|
|
|
|
2015-04-02 21:35:46 -07:00
|
|
|
void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview)
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
2015-01-16 01:21:11 -08:00
|
|
|
QMenu popup(this);
|
2015-04-04 01:40:15 -07:00
|
|
|
QPointer<QMenu> previewProjector;
|
|
|
|
QPointer<QMenu> sourceProjector;
|
2015-04-02 21:35:46 -07:00
|
|
|
|
|
|
|
if (preview) {
|
|
|
|
QAction *action = popup.addAction(
|
|
|
|
QTStr("Basic.Main.PreviewConextMenu.Enable"),
|
|
|
|
this, SLOT(TogglePreview()));
|
|
|
|
action->setCheckable(true);
|
|
|
|
action->setChecked(obs_preview_enabled());
|
|
|
|
|
2015-04-04 01:40:15 -07:00
|
|
|
previewProjector = new QMenu(QTStr("PreviewProjector"));
|
|
|
|
AddProjectorMenuMonitors(previewProjector, this,
|
|
|
|
SLOT(OpenPreviewProjector()));
|
|
|
|
|
|
|
|
popup.addMenu(previewProjector);
|
|
|
|
|
2015-04-02 21:35:46 -07:00
|
|
|
popup.addSeparator();
|
|
|
|
}
|
|
|
|
|
2014-06-30 01:13:32 -07:00
|
|
|
QPointer<QMenu> addSourceMenu = CreateAddSourcePopupMenu();
|
|
|
|
if (addSourceMenu)
|
|
|
|
popup.addMenu(addSourceMenu);
|
|
|
|
|
|
|
|
if (item) {
|
|
|
|
if (addSourceMenu)
|
|
|
|
popup.addSeparator();
|
|
|
|
|
2014-09-15 16:16:16 -07:00
|
|
|
OBSSceneItem sceneItem = GetSceneItem(item);
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_sceneitem_get_source(sceneItem);
|
2014-09-15 16:16:16 -07:00
|
|
|
QAction *action;
|
|
|
|
|
2014-06-30 01:13:32 -07:00
|
|
|
popup.addAction(QTStr("Rename"), this,
|
|
|
|
SLOT(EditSceneItemName()));
|
2014-06-30 18:21:40 -07:00
|
|
|
popup.addAction(QTStr("Remove"), this,
|
|
|
|
SLOT(on_actionRemoveSource_triggered()),
|
2014-10-15 13:00:43 -07:00
|
|
|
DeleteKeys.front());
|
2014-06-30 19:47:06 -07:00
|
|
|
popup.addSeparator();
|
|
|
|
popup.addMenu(ui->orderMenu);
|
2014-06-30 01:13:32 -07:00
|
|
|
popup.addMenu(ui->transformMenu);
|
2015-04-04 01:40:15 -07:00
|
|
|
|
|
|
|
sourceProjector = new QMenu(QTStr("SourceProjector"));
|
|
|
|
AddProjectorMenuMonitors(sourceProjector, this,
|
|
|
|
SLOT(OpenSourceProjector()));
|
|
|
|
|
|
|
|
popup.addSeparator();
|
|
|
|
popup.addMenu(sourceProjector);
|
2014-06-30 01:13:32 -07:00
|
|
|
popup.addSeparator();
|
2014-09-15 16:16:16 -07:00
|
|
|
|
|
|
|
action = popup.addAction(QTStr("Interact"), this,
|
|
|
|
SLOT(on_actionInteract_triggered()));
|
|
|
|
|
|
|
|
action->setEnabled(obs_source_get_output_flags(source) &
|
|
|
|
OBS_SOURCE_INTERACTION);
|
|
|
|
|
2015-02-25 21:23:57 -08:00
|
|
|
popup.addAction(QTStr("Filters"), this,
|
|
|
|
SLOT(OpenFilters()));
|
2014-06-30 01:13:32 -07:00
|
|
|
popup.addAction(QTStr("Properties"), this,
|
|
|
|
SLOT(on_actionSourceProperties_triggered()));
|
|
|
|
}
|
|
|
|
|
|
|
|
popup.exec(QCursor::pos());
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
|
|
|
|
2015-04-02 21:35:46 -07:00
|
|
|
void OBSBasic::on_sources_customContextMenuRequested(const QPoint &pos)
|
|
|
|
{
|
|
|
|
CreateSourcePopupMenu(ui->sources->itemAt(pos), false);
|
|
|
|
}
|
|
|
|
|
2014-10-15 13:05:56 -07:00
|
|
|
void OBSBasic::on_sources_itemDoubleClicked(QListWidgetItem *witem)
|
|
|
|
{
|
|
|
|
if (!witem)
|
|
|
|
return;
|
|
|
|
|
|
|
|
OBSSceneItem item = GetSceneItem(witem);
|
|
|
|
OBSSource source = obs_sceneitem_get_source(item);
|
|
|
|
|
|
|
|
if (source)
|
|
|
|
CreatePropertiesWindow(source);
|
|
|
|
}
|
|
|
|
|
2014-05-10 18:47:48 -07:00
|
|
|
void OBSBasic::AddSource(const char *id)
|
2013-12-30 05:56:39 -08:00
|
|
|
{
|
2014-06-29 17:33:40 -07:00
|
|
|
if (id && *id) {
|
|
|
|
OBSBasicSourceSelect sourceSelect(this, id);
|
|
|
|
sourceSelect.exec();
|
|
|
|
}
|
2013-12-30 05:56:39 -08:00
|
|
|
}
|
|
|
|
|
2014-06-29 17:33:40 -07:00
|
|
|
QMenu *OBSBasic::CreateAddSourcePopupMenu()
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
2013-12-30 05:56:39 -08:00
|
|
|
const char *type;
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
bool foundValues = false;
|
|
|
|
size_t idx = 0;
|
2013-12-30 05:56:39 -08:00
|
|
|
|
2015-01-16 01:21:11 -08:00
|
|
|
QMenu *popup = new QMenu(QTStr("Add"), this);
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
while (obs_enum_input_types(idx++, &type)) {
|
2014-08-04 08:41:15 -07:00
|
|
|
const char *name = obs_source_get_display_name(
|
2014-06-25 00:13:00 -07:00
|
|
|
OBS_SOURCE_TYPE_INPUT, type);
|
2013-12-30 05:56:39 -08:00
|
|
|
|
2014-04-26 23:47:50 -07:00
|
|
|
if (strcmp(type, "scene") == 0)
|
|
|
|
continue;
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
QAction *popupItem = new QAction(QT_UTF8(name), this);
|
|
|
|
popupItem->setData(QT_UTF8(type));
|
2014-06-29 17:33:40 -07:00
|
|
|
connect(popupItem, SIGNAL(triggered(bool)),
|
|
|
|
this, SLOT(AddSourceFromAction()));
|
|
|
|
popup->addAction(popupItem);
|
2013-12-30 05:56:39 -08:00
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
foundValues = true;
|
2013-12-30 05:56:39 -08:00
|
|
|
}
|
|
|
|
|
2014-06-29 17:33:40 -07:00
|
|
|
if (!foundValues) {
|
|
|
|
delete popup;
|
|
|
|
popup = nullptr;
|
2013-12-30 05:56:39 -08:00
|
|
|
}
|
2014-06-29 17:33:40 -07:00
|
|
|
|
|
|
|
return popup;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::AddSourceFromAction()
|
|
|
|
{
|
|
|
|
QAction *action = qobject_cast<QAction*>(sender());
|
|
|
|
if (!action)
|
|
|
|
return;
|
|
|
|
|
|
|
|
AddSource(QT_TO_UTF8(action->data().toString()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::AddSourcePopupMenu(const QPoint &pos)
|
|
|
|
{
|
|
|
|
if (!GetCurrentScene()) {
|
|
|
|
// Tell the user he needs a scene first (help beginners).
|
|
|
|
QMessageBox::information(this,
|
|
|
|
QTStr("Basic.Main.AddSourceHelp.Title"),
|
|
|
|
QTStr("Basic.Main.AddSourceHelp.Text"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QPointer<QMenu> popup = CreateAddSourcePopupMenu();
|
|
|
|
if (popup)
|
|
|
|
popup->exec(pos);
|
2013-12-30 05:56:39 -08:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_actionAddSource_triggered()
|
2013-12-30 05:56:39 -08:00
|
|
|
{
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
AddSourcePopupMenu(QCursor::pos());
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_actionRemoveSource_triggered()
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
2014-06-30 13:45:58 -07:00
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_sceneitem_get_source(item);
|
2014-06-30 13:45:58 -07:00
|
|
|
|
|
|
|
if (source && QueryRemoveSource(source))
|
2014-01-30 00:31:52 -08:00
|
|
|
obs_sceneitem_remove(item);
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
|
|
|
|
2014-09-15 16:16:16 -07:00
|
|
|
void OBSBasic::on_actionInteract_triggered()
|
|
|
|
{
|
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
|
|
|
OBSSource source = obs_sceneitem_get_source(item);
|
|
|
|
|
|
|
|
if (source)
|
|
|
|
CreateInteractionWindow(source);
|
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_actionSourceProperties_triggered()
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
2014-03-23 01:07:54 -07:00
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
2014-08-03 14:39:19 -07:00
|
|
|
OBSSource source = obs_sceneitem_get_source(item);
|
2014-03-23 01:07:54 -07:00
|
|
|
|
2014-07-22 13:16:57 -07:00
|
|
|
if (source)
|
|
|
|
CreatePropertiesWindow(source);
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_actionSourceUp_triggered()
|
2013-11-07 15:45:03 -08:00
|
|
|
{
|
2014-05-15 17:40:53 -07:00
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_set_order(item, OBS_ORDER_MOVE_UP);
|
2013-11-07 15:45:03 -08:00
|
|
|
}
|
2013-12-10 10:22:33 -08:00
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_actionSourceDown_triggered()
|
2013-12-10 20:14:45 -08:00
|
|
|
{
|
2014-05-15 17:40:53 -07:00
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_set_order(item, OBS_ORDER_MOVE_DOWN);
|
2013-12-10 20:14:45 -08:00
|
|
|
}
|
|
|
|
|
2014-06-30 19:47:06 -07:00
|
|
|
void OBSBasic::on_actionMoveUp_triggered()
|
|
|
|
{
|
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_set_order(item, OBS_ORDER_MOVE_UP);
|
2014-06-30 19:47:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionMoveDown_triggered()
|
|
|
|
{
|
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_set_order(item, OBS_ORDER_MOVE_DOWN);
|
2014-06-30 19:47:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionMoveToTop_triggered()
|
|
|
|
{
|
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_set_order(item, OBS_ORDER_MOVE_TOP);
|
2014-06-30 19:47:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionMoveToBottom_triggered()
|
|
|
|
{
|
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_set_order(item, OBS_ORDER_MOVE_BOTTOM);
|
2014-06-30 19:47:06 -07:00
|
|
|
}
|
|
|
|
|
2014-08-23 17:02:45 -07:00
|
|
|
static BPtr<char> ReadLogFile(const char *log)
|
2014-05-18 17:44:10 -07:00
|
|
|
{
|
2015-01-15 23:44:38 -08:00
|
|
|
char logDir[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
if (GetConfigPath(logDir, sizeof(logDir), "obs-studio/logs") <= 0)
|
2015-01-15 23:44:38 -08:00
|
|
|
return nullptr;
|
2014-05-18 17:44:10 -07:00
|
|
|
|
|
|
|
string path = (char*)logDir;
|
|
|
|
path += "/";
|
|
|
|
path += log;
|
|
|
|
|
2014-08-23 17:02:45 -07:00
|
|
|
BPtr<char> file = os_quick_read_utf8_file(path.c_str());
|
2014-05-18 17:44:10 -07:00
|
|
|
if (!file)
|
|
|
|
blog(LOG_WARNING, "Failed to read log file %s", path.c_str());
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::UploadLog(const char *file)
|
|
|
|
{
|
2014-08-23 17:02:45 -07:00
|
|
|
BPtr<char> fileString{ReadLogFile(file)};
|
2014-05-18 17:44:10 -07:00
|
|
|
|
2014-08-23 17:02:45 -07:00
|
|
|
if (!fileString)
|
2014-05-18 17:44:10 -07:00
|
|
|
return;
|
|
|
|
|
2014-08-23 17:02:45 -07:00
|
|
|
if (!*fileString)
|
2014-05-18 17:44:10 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
ui->menuLogFiles->setEnabled(false);
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
auto data_deleter = [](obs_data_t *d) { obs_data_release(d); };
|
2014-08-23 17:02:45 -07:00
|
|
|
using data_t = unique_ptr<struct obs_data, decltype(data_deleter)>;
|
2014-05-18 17:44:10 -07:00
|
|
|
|
2014-08-23 17:02:45 -07:00
|
|
|
data_t content{obs_data_create(), data_deleter};
|
|
|
|
data_t files{obs_data_create(), data_deleter};
|
|
|
|
data_t request{obs_data_create(), data_deleter};
|
2014-05-18 17:44:10 -07:00
|
|
|
|
2014-08-23 17:02:45 -07:00
|
|
|
obs_data_set_string(content.get(), "content", fileString);
|
2014-05-18 17:44:10 -07:00
|
|
|
|
2014-08-23 17:02:45 -07:00
|
|
|
obs_data_set_obj(files.get(), file, content.get());
|
|
|
|
|
|
|
|
stringstream ss;
|
|
|
|
ss << "OBS " << App()->GetVersionString()
|
|
|
|
<< " log file uploaded at " << CurrentDateTimeString();
|
|
|
|
obs_data_set_string(request.get(), "description", ss.str().c_str());
|
|
|
|
obs_data_set_bool(request.get(), "public", false);
|
|
|
|
obs_data_set_obj(request.get(), "files", files.get());
|
|
|
|
|
|
|
|
const char *json = obs_data_get_json(request.get());
|
2014-08-25 13:22:57 -07:00
|
|
|
if (!json) {
|
2014-08-23 17:02:45 -07:00
|
|
|
blog(LOG_ERROR, "Failed to get JSON data for log upload");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-08-25 12:22:58 -07:00
|
|
|
QBuffer *postData = new QBuffer();
|
|
|
|
postData->setData(json, (int) strlen(json));
|
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
if (logUploadThread) {
|
|
|
|
logUploadThread->wait();
|
|
|
|
delete logUploadThread;
|
|
|
|
}
|
2014-08-25 12:22:58 -07:00
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
RemoteTextThread *thread = new RemoteTextThread(
|
|
|
|
"https://api.github.com/gists",
|
|
|
|
"application/json", json);
|
|
|
|
logUploadThread = thread;
|
|
|
|
connect(thread, &RemoteTextThread::Result,
|
|
|
|
this, &OBSBasic::logUploadFinished);
|
|
|
|
logUploadThread->start();
|
2014-05-18 17:44:10 -07:00
|
|
|
}
|
|
|
|
|
2014-08-21 18:19:19 -07:00
|
|
|
void OBSBasic::on_actionShowLogs_triggered()
|
|
|
|
{
|
2015-01-15 23:44:38 -08:00
|
|
|
char logDir[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
if (GetConfigPath(logDir, sizeof(logDir), "obs-studio/logs") <= 0)
|
2015-01-15 23:44:38 -08:00
|
|
|
return;
|
|
|
|
|
2014-08-21 18:19:19 -07:00
|
|
|
QUrl url = QUrl::fromLocalFile(QT_UTF8(logDir));
|
|
|
|
QDesktopServices::openUrl(url);
|
|
|
|
}
|
|
|
|
|
2014-05-18 17:44:10 -07:00
|
|
|
void OBSBasic::on_actionUploadCurrentLog_triggered()
|
|
|
|
{
|
|
|
|
UploadLog(App()->GetCurrentLog());
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionUploadLastLog_triggered()
|
|
|
|
{
|
|
|
|
UploadLog(App()->GetLastLog());
|
|
|
|
}
|
|
|
|
|
2015-02-23 22:04:19 -08:00
|
|
|
void OBSBasic::on_actionViewCurrentLog_triggered()
|
|
|
|
{
|
|
|
|
char logDir[512];
|
2015-06-01 16:11:57 -07:00
|
|
|
if (GetConfigPath(logDir, sizeof(logDir), "obs-studio/logs") <= 0)
|
2015-02-23 22:04:19 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
const char* log = App()->GetCurrentLog();
|
|
|
|
|
|
|
|
string path = (char*)logDir;
|
|
|
|
path += "/";
|
|
|
|
path += log;
|
|
|
|
|
|
|
|
QUrl url = QUrl::fromLocalFile(QT_UTF8(path.c_str()));
|
|
|
|
QDesktopServices::openUrl(url);
|
|
|
|
}
|
|
|
|
|
2014-07-13 23:56:28 -07:00
|
|
|
void OBSBasic::on_actionCheckForUpdates_triggered()
|
|
|
|
{
|
|
|
|
CheckForUpdates();
|
|
|
|
}
|
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
void OBSBasic::logUploadFinished(const QString &text, const QString &error)
|
2014-05-18 17:44:10 -07:00
|
|
|
{
|
|
|
|
ui->menuLogFiles->setEnabled(true);
|
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
if (text.isEmpty()) {
|
2014-05-18 17:44:10 -07:00
|
|
|
QMessageBox::information(this,
|
|
|
|
QTStr("LogReturnDialog.ErrorUploadingLog"),
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
error);
|
2014-05-18 17:44:10 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
UI: Replace Qt5Network classes with libcurl
The Qt5Network classes seem to only support OpenSSL, and because OpenSSL
isn't available on windows, we would have to distribute it with the
program to get SSL access working. The problem with that is that
OpenSSL is not GPL-compatible, so we cannot distribute OpenSSL with the
program, which means we have to find a better (and preferably superior)
library for accessing remote files that can use the windows SSPI for our
SSL needs, which comes with the operating system.
Fortunately, libcurl is probably the best library out there, and can be
compiled with SSPI instead of OpenSSL, so we're just going to switch to
libcurl instead. Originally I thought it didn't support SSPI, otherwise
I would have implemented it sooner.
As a side note, this will make it so we'll able to get files from the
internet via plugins, which will be quite useful.
2015-05-23 23:39:39 -07:00
|
|
|
obs_data_t *returnData = obs_data_create_from_json(QT_TO_UTF8(text));
|
2014-08-25 12:22:58 -07:00
|
|
|
QString logURL = obs_data_get_string(returnData, "html_url");
|
2014-05-18 17:44:10 -07:00
|
|
|
obs_data_release(returnData);
|
|
|
|
|
|
|
|
OBSLogReply logDialog(this, logURL);
|
|
|
|
logDialog.exec();
|
|
|
|
}
|
|
|
|
|
2014-08-25 10:10:58 -07:00
|
|
|
static void RenameListItem(OBSBasic *parent, QListWidget *listWidget,
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source, const string &name)
|
2014-06-30 01:05:33 -07:00
|
|
|
{
|
2014-10-13 09:09:06 -07:00
|
|
|
const char *prevName = obs_source_get_name(source);
|
|
|
|
if (name == prevName)
|
|
|
|
return;
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *foundSource = obs_get_source_by_name(name.c_str());
|
2014-10-13 09:09:06 -07:00
|
|
|
QListWidgetItem *listItem = listWidget->currentItem();
|
2014-06-30 01:05:33 -07:00
|
|
|
|
2014-10-13 09:09:06 -07:00
|
|
|
if (foundSource || name.empty()) {
|
2014-06-30 01:05:33 -07:00
|
|
|
listItem->setText(QT_UTF8(prevName));
|
2014-08-12 12:09:19 -07:00
|
|
|
|
2014-10-13 09:09:06 -07:00
|
|
|
if (foundSource) {
|
2014-08-12 12:09:19 -07:00
|
|
|
QMessageBox::information(parent,
|
|
|
|
QTStr("NameExists.Title"),
|
|
|
|
QTStr("NameExists.Text"));
|
|
|
|
} else if (name.empty()) {
|
|
|
|
QMessageBox::information(parent,
|
|
|
|
QTStr("NoNameEntered.Title"),
|
|
|
|
QTStr("NoNameEntered.Text"));
|
|
|
|
}
|
|
|
|
|
2014-06-30 01:05:33 -07:00
|
|
|
obs_source_release(foundSource);
|
|
|
|
} else {
|
|
|
|
listItem->setText(QT_UTF8(name.c_str()));
|
2014-08-04 08:41:15 -07:00
|
|
|
obs_source_set_name(source, name.c_str());
|
2014-06-30 01:05:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-30 00:06:01 -07:00
|
|
|
void OBSBasic::SceneNameEdited(QWidget *editor,
|
|
|
|
QAbstractItemDelegate::EndEditHint endHint)
|
|
|
|
{
|
|
|
|
OBSScene scene = GetCurrentScene();
|
|
|
|
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
|
2014-06-30 01:05:33 -07:00
|
|
|
string text = QT_TO_UTF8(edit->text().trimmed());
|
2014-06-30 00:06:01 -07:00
|
|
|
|
|
|
|
if (!scene)
|
|
|
|
return;
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_scene_get_source(scene);
|
2014-08-12 12:09:19 -07:00
|
|
|
RenameListItem(this, ui->scenes, source, text);
|
2014-06-30 00:06:01 -07:00
|
|
|
|
|
|
|
UNUSED_PARAMETER(endHint);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::SceneItemNameEdited(QWidget *editor,
|
|
|
|
QAbstractItemDelegate::EndEditHint endHint)
|
|
|
|
{
|
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
|
|
|
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
|
2014-06-30 01:05:33 -07:00
|
|
|
string text = QT_TO_UTF8(edit->text().trimmed());
|
2014-06-30 00:06:01 -07:00
|
|
|
|
|
|
|
if (!item)
|
|
|
|
return;
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_source_t *source = obs_sceneitem_get_source(item);
|
2014-08-12 12:09:19 -07:00
|
|
|
RenameListItem(this, ui->sources, source, text);
|
2014-06-30 00:06:01 -07:00
|
|
|
|
2015-03-22 20:51:21 -07:00
|
|
|
QListWidgetItem *listItem = ui->sources->currentItem();
|
|
|
|
listItem->setText(QString());
|
|
|
|
SetupVisibilityItem(ui->sources, listItem, item);
|
|
|
|
|
2014-06-30 00:06:01 -07:00
|
|
|
UNUSED_PARAMETER(endHint);
|
|
|
|
}
|
|
|
|
|
2015-02-25 21:23:57 -08:00
|
|
|
void OBSBasic::OpenFilters()
|
|
|
|
{
|
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
|
|
|
OBSSource source = obs_sceneitem_get_source(item);
|
|
|
|
|
|
|
|
CreateFiltersWindow(source);
|
|
|
|
}
|
|
|
|
|
2015-03-18 15:09:44 -07:00
|
|
|
void OBSBasic::OpenSceneFilters()
|
|
|
|
{
|
|
|
|
OBSScene scene = GetCurrentScene();
|
|
|
|
OBSSource source = obs_scene_get_source(scene);
|
|
|
|
|
|
|
|
CreateFiltersWindow(source);
|
|
|
|
}
|
|
|
|
|
2014-10-25 17:03:13 -07:00
|
|
|
void OBSBasic::StartStreaming()
|
|
|
|
{
|
|
|
|
SaveProject();
|
|
|
|
|
|
|
|
if (outputHandler->StreamingActive())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (outputHandler->StartStreaming(service)) {
|
|
|
|
ui->streamButton->setEnabled(false);
|
|
|
|
ui->streamButton->setText(QTStr("Basic.Main.Connecting"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::StopStreaming()
|
|
|
|
{
|
|
|
|
SaveProject();
|
|
|
|
|
|
|
|
if (outputHandler->StreamingActive())
|
|
|
|
outputHandler->StopStreaming();
|
|
|
|
}
|
|
|
|
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
void OBSBasic::StreamingStart()
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
{
|
2014-07-12 05:34:23 -07:00
|
|
|
ui->streamButton->setText(QTStr("Basic.Main.StopStreaming"));
|
2014-05-15 14:04:18 -07:00
|
|
|
ui->streamButton->setEnabled(true);
|
2015-02-06 03:17:33 -08:00
|
|
|
ui->statusbar->StreamStarted(outputHandler->streamOutput);
|
2014-03-10 13:10:35 -07:00
|
|
|
}
|
|
|
|
|
2014-05-12 15:30:36 -07:00
|
|
|
void OBSBasic::StreamingStop(int code)
|
2014-03-10 13:10:35 -07:00
|
|
|
{
|
2014-05-12 15:30:36 -07:00
|
|
|
const char *errorMessage;
|
|
|
|
|
|
|
|
switch (code) {
|
|
|
|
case OBS_OUTPUT_BAD_PATH:
|
|
|
|
errorMessage = Str("Output.ConnectFail.BadPath");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OBS_OUTPUT_CONNECT_FAILED:
|
|
|
|
errorMessage = Str("Output.ConnectFail.ConnectFailed");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OBS_OUTPUT_INVALID_STREAM:
|
|
|
|
errorMessage = Str("Output.ConnectFail.InvalidStream");
|
|
|
|
break;
|
|
|
|
|
2014-06-25 02:03:00 -07:00
|
|
|
default:
|
2014-05-12 15:30:36 -07:00
|
|
|
case OBS_OUTPUT_ERROR:
|
|
|
|
errorMessage = Str("Output.ConnectFail.Error");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OBS_OUTPUT_DISCONNECTED:
|
|
|
|
/* doesn't happen if output is set to reconnect. note that
|
|
|
|
* reconnects are handled in the output, not in the UI */
|
|
|
|
errorMessage = Str("Output.ConnectFail.Disconnected");
|
|
|
|
}
|
|
|
|
|
2014-07-06 16:19:27 -07:00
|
|
|
ui->statusbar->StreamStopped();
|
2014-05-20 23:27:27 -07:00
|
|
|
|
2014-05-12 15:30:36 -07:00
|
|
|
ui->streamButton->setText(QTStr("Basic.Main.StartStreaming"));
|
2014-05-15 14:04:18 -07:00
|
|
|
ui->streamButton->setEnabled(true);
|
2014-05-12 15:30:36 -07:00
|
|
|
|
|
|
|
if (code != OBS_OUTPUT_SUCCESS)
|
|
|
|
QMessageBox::information(this,
|
|
|
|
QTStr("Output.ConnectFail.Title"),
|
|
|
|
QT_UTF8(errorMessage));
|
2014-04-14 02:22:09 -07:00
|
|
|
}
|
|
|
|
|
2014-10-25 16:57:29 -07:00
|
|
|
void OBSBasic::StartRecording()
|
|
|
|
{
|
|
|
|
SaveProject();
|
|
|
|
|
|
|
|
if (!outputHandler->RecordingActive())
|
|
|
|
outputHandler->StartRecording();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::StopRecording()
|
|
|
|
{
|
|
|
|
SaveProject();
|
|
|
|
|
|
|
|
if (outputHandler->RecordingActive())
|
|
|
|
outputHandler->StopRecording();
|
|
|
|
}
|
|
|
|
|
2014-08-24 18:10:57 -07:00
|
|
|
void OBSBasic::RecordingStart()
|
|
|
|
{
|
2015-02-06 03:17:33 -08:00
|
|
|
ui->statusbar->RecordingStarted(outputHandler->fileOutput);
|
2015-04-04 15:08:20 -07:00
|
|
|
ui->recordButton->setText(QTStr("Basic.Main.StopRecording"));
|
2014-08-24 18:10:57 -07:00
|
|
|
}
|
|
|
|
|
2015-06-09 21:00:22 -07:00
|
|
|
void OBSBasic::RecordingStop(int code)
|
2014-03-10 13:10:35 -07:00
|
|
|
{
|
2014-08-24 18:10:57 -07:00
|
|
|
ui->statusbar->RecordingStopped();
|
2014-05-20 23:27:27 -07:00
|
|
|
ui->recordButton->setText(QTStr("Basic.Main.StartRecording"));
|
2015-06-09 21:00:22 -07:00
|
|
|
|
|
|
|
if (code == OBS_OUTPUT_UNSUPPORTED)
|
|
|
|
QMessageBox::information(this,
|
|
|
|
QTStr("Output.RecordFail.Title"),
|
|
|
|
QTStr("Output.RecordFail.Unsupported"));
|
2014-05-20 23:27:27 -07:00
|
|
|
}
|
obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and
the output gets data from that service rather than via settings.
This allows the service context to have control over how an output is
used, and makes it so that the URL/key/etc isn't necessarily some
static setting.
Also, if the service is attached to an output, it will stick around
until the output is destroyed.
- The settings interface has been updated so that it can allow the
usage of service plugins. What this means is that now you can create
a service plugin that can control aspects of the stream, and it
allows each service to create their own user interface if they create
a service plugin module.
- Testing out saving of current service information. Saves/loads from
JSON in to obs_data_t, seems to be working quite nicely, and the
service object information is saved/preserved on exit, and loaded
again on startup.
- I agonized over the settings user interface for days, and eventually
I just decided that the only way that users weren't going to be
fumbling over options was to split up the settings in to simple/basic
output, pre-configured, and then advanced for advanced use (such as
multiple outputs or services, which I'll implement later).
This was particularly painful to really design right, I wanted more
features and wanted to include everything in one interface but
ultimately just realized from experience that users are just not
technically knowledgable about it and will end up fumbling with the
settings rather than getting things done.
Basically, what this means is that casual users only have to enter in
about 3 things to configure their stream: Stream key, audio bitrate,
and video bitrate. I am really happy with this interface for those
types of users, but it definitely won't be sufficient for advanced
usage or for custom outputs, so that stuff will have to be separated.
- Improved the JSON usage for the 'common streaming services' context,
I realized that JSON arrays are there to ensure sorting, while
forgetting that general items are optimized for hashing. So
basically I'm just using arrays now to sort items in it.
2014-04-24 01:49:07 -07:00
|
|
|
|
2014-05-20 23:27:27 -07:00
|
|
|
void OBSBasic::on_streamButton_clicked()
|
|
|
|
{
|
2015-02-06 03:17:33 -08:00
|
|
|
if (outputHandler->StreamingActive()) {
|
2014-10-25 17:03:13 -07:00
|
|
|
StopStreaming();
|
2014-05-20 23:27:27 -07:00
|
|
|
} else {
|
2014-10-25 17:03:13 -07:00
|
|
|
StartStreaming();
|
2014-05-20 23:27:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_recordButton_clicked()
|
|
|
|
{
|
2014-10-25 16:57:29 -07:00
|
|
|
if (outputHandler->RecordingActive())
|
|
|
|
StopRecording();
|
|
|
|
else
|
|
|
|
StartRecording();
|
2014-02-10 09:22:35 -08:00
|
|
|
}
|
|
|
|
|
Change the UI to Qt (work in progress)
--------------------------------------------------
Notes and details
--------------------------------------------------
Why was this done? Because wxWidgets was just lacking in many areas. I
know wxWidgets is designed to be used with native controls, and that's
great, but wxWidgets just is not a feature-complete toolkit for
multiplatform applications. It lacks in dialog editors, its code is
archaic and outdated, and I just feel frustrated every time I try to do
things with it.
Qt on the other hand.. I had to actually try Qt to realize how much
better it was as a toolkit. They've got everything from dialog editors,
to an IDE, a debugger, build tools, just everything, and it's all
top-notch and highly maintained. The focus of the toolkit is
application development, and they spend their time trying to help
people do exactly that: make programs. Great support, great tools,
and because of that, great toolkit. I just didn't want to alienate any
developers by being stubborn about native widgets.
There *are* some things that are rather lackluster about it and design
choices I disagree with though. For example, I realize that to have an
easy to use toolkit you have to have some level of code generation.
However, in my personal and humble opinion, moc just feels like a
terrible way to approach the problem. Even now I feel like there are a
variety of ways you could handle code generation and automatic
management of things like that. I don't like the idea of circumventing
the language itself like that. It feels like one giant massive hack.
--------------------------------------------------
Things that aren't working properly:
--------------------------------------------------
- Settings dialog is not implemented. The dialog is complete but the
code to handle the dialog hasn't been constructed yet.
- There is a problem with using Qt widgets as a device target on
windows, with at least OpenGL: if I have the preview widget
automatically resize itself, it seems to cause some sort of video
card failure that I don't understand.
- Because of the above, resizing the preview widget has been disabled
until I can figure out what's going on, so it's currently only a
32x32 area.
- Direct3D doesn't seem to render correctly either, seems that the
viewport is messed up or something. I'm sort of confused about
what's going on with it.
- The new main window seems to be triggering more race conditions than
the wxWidgets main window dialog did. I'm not entirely sure what's
going on here, but this may just be existing race conditions within
libobs itself that I just never spotted before (even though I tend to
be very thorough with race conditions any time I use variables
cross-thread)
2014-01-23 10:53:55 -08:00
|
|
|
void OBSBasic::on_settingsButton_clicked()
|
2013-12-10 10:22:33 -08:00
|
|
|
{
|
2014-01-24 20:19:50 -08:00
|
|
|
OBSBasicSettings settings(this);
|
|
|
|
settings.exec();
|
2013-12-10 10:22:33 -08:00
|
|
|
}
|
2014-03-06 20:08:12 -08:00
|
|
|
|
2015-06-25 01:02:47 -07:00
|
|
|
void OBSBasic::on_actionWebsite_triggered()
|
|
|
|
{
|
|
|
|
QUrl url = QUrl("https://obsproject.com", QUrl::TolerantMode);
|
|
|
|
QDesktopServices::openUrl(url);
|
|
|
|
}
|
|
|
|
|
2015-04-02 21:35:46 -07:00
|
|
|
void OBSBasic::on_preview_customContextMenuRequested(const QPoint &pos)
|
|
|
|
{
|
|
|
|
CreateSourcePopupMenu(ui->sources->currentItem(), true);
|
|
|
|
|
|
|
|
UNUSED_PARAMETER(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_previewDisabledLabel_customContextMenuRequested(
|
|
|
|
const QPoint &pos)
|
|
|
|
{
|
|
|
|
QMenu popup(this);
|
2015-04-04 01:40:15 -07:00
|
|
|
QPointer<QMenu> previewProjector;
|
2015-04-02 21:35:46 -07:00
|
|
|
|
|
|
|
QAction *action = popup.addAction(
|
|
|
|
QTStr("Basic.Main.PreviewConextMenu.Enable"),
|
|
|
|
this, SLOT(TogglePreview()));
|
|
|
|
action->setCheckable(true);
|
|
|
|
action->setChecked(obs_preview_enabled());
|
|
|
|
|
2015-04-04 01:40:15 -07:00
|
|
|
previewProjector = new QMenu(QTStr("PreviewProjector"));
|
|
|
|
AddProjectorMenuMonitors(previewProjector, this,
|
|
|
|
SLOT(OpenPreviewProjector()));
|
|
|
|
|
|
|
|
popup.addMenu(previewProjector);
|
2015-04-02 21:35:46 -07:00
|
|
|
popup.exec(QCursor::pos());
|
|
|
|
|
|
|
|
UNUSED_PARAMETER(pos);
|
|
|
|
}
|
|
|
|
|
2014-03-06 20:08:12 -08:00
|
|
|
void OBSBasic::GetFPSCommon(uint32_t &num, uint32_t &den) const
|
|
|
|
{
|
|
|
|
const char *val = config_get_string(basicConfig, "Video", "FPSCommon");
|
|
|
|
|
|
|
|
if (strcmp(val, "10") == 0) {
|
|
|
|
num = 10;
|
|
|
|
den = 1;
|
|
|
|
} else if (strcmp(val, "20") == 0) {
|
|
|
|
num = 20;
|
|
|
|
den = 1;
|
|
|
|
} else if (strcmp(val, "25") == 0) {
|
|
|
|
num = 25;
|
|
|
|
den = 1;
|
|
|
|
} else if (strcmp(val, "29.97") == 0) {
|
|
|
|
num = 30000;
|
|
|
|
den = 1001;
|
|
|
|
} else if (strcmp(val, "48") == 0) {
|
|
|
|
num = 48;
|
|
|
|
den = 1;
|
|
|
|
} else if (strcmp(val, "59.94") == 0) {
|
|
|
|
num = 60000;
|
|
|
|
den = 1001;
|
|
|
|
} else if (strcmp(val, "60") == 0) {
|
|
|
|
num = 60;
|
|
|
|
den = 1;
|
|
|
|
} else {
|
|
|
|
num = 30;
|
|
|
|
den = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::GetFPSInteger(uint32_t &num, uint32_t &den) const
|
|
|
|
{
|
|
|
|
num = (uint32_t)config_get_uint(basicConfig, "Video", "FPSInt");
|
|
|
|
den = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::GetFPSFraction(uint32_t &num, uint32_t &den) const
|
|
|
|
{
|
|
|
|
num = (uint32_t)config_get_uint(basicConfig, "Video", "FPSNum");
|
|
|
|
den = (uint32_t)config_get_uint(basicConfig, "Video", "FPSDen");
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::GetFPSNanoseconds(uint32_t &num, uint32_t &den) const
|
|
|
|
{
|
|
|
|
num = 1000000000;
|
|
|
|
den = (uint32_t)config_get_uint(basicConfig, "Video", "FPSNS");
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::GetConfigFPS(uint32_t &num, uint32_t &den) const
|
|
|
|
{
|
|
|
|
uint32_t type = config_get_uint(basicConfig, "Video", "FPSType");
|
|
|
|
|
|
|
|
if (type == 1) //"Integer"
|
|
|
|
GetFPSInteger(num, den);
|
|
|
|
else if (type == 2) //"Fraction"
|
|
|
|
GetFPSFraction(num, den);
|
|
|
|
else if (false) //"Nanoseconds", currently not implemented
|
|
|
|
GetFPSNanoseconds(num, den);
|
|
|
|
else
|
|
|
|
GetFPSCommon(num, den);
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
config_t *OBSBasic::Config() const
|
2014-03-06 20:08:12 -08:00
|
|
|
{
|
|
|
|
return basicConfig;
|
|
|
|
}
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
|
|
|
void OBSBasic::on_actionEditTransform_triggered()
|
|
|
|
{
|
2014-07-22 13:16:57 -07:00
|
|
|
if (transformWindow)
|
|
|
|
transformWindow->close();
|
|
|
|
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
transformWindow = new OBSBasicTransform(this);
|
|
|
|
transformWindow->show();
|
2014-07-22 13:16:57 -07:00
|
|
|
transformWindow->setAttribute(Qt::WA_DeleteOnClose, true);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionResetTransform_triggered()
|
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
auto func = [] (obs_scene_t *scene, obs_sceneitem_t *item, void *param)
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
{
|
|
|
|
if (!obs_sceneitem_selected(item))
|
|
|
|
return true;
|
|
|
|
|
2014-08-01 23:33:45 -07:00
|
|
|
obs_transform_info info;
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
vec2_set(&info.pos, 0.0f, 0.0f);
|
|
|
|
vec2_set(&info.scale, 1.0f, 1.0f);
|
|
|
|
info.rot = 0.0f;
|
|
|
|
info.alignment = OBS_ALIGN_TOP | OBS_ALIGN_LEFT;
|
|
|
|
info.bounds_type = OBS_BOUNDS_NONE;
|
|
|
|
info.bounds_alignment = OBS_ALIGN_CENTER;
|
|
|
|
vec2_set(&info.bounds, 0.0f, 0.0f);
|
|
|
|
obs_sceneitem_set_info(item, &info);
|
|
|
|
|
|
|
|
UNUSED_PARAMETER(scene);
|
|
|
|
UNUSED_PARAMETER(param);
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
obs_scene_enum_items(GetCurrentScene(), func, nullptr);
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
static void GetItemBox(obs_sceneitem_t *item, vec3 &tl, vec3 &br)
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
{
|
|
|
|
matrix4 boxTransform;
|
|
|
|
obs_sceneitem_get_box_transform(item, &boxTransform);
|
|
|
|
|
|
|
|
vec3_set(&tl, M_INFINITE, M_INFINITE, 0.0f);
|
2014-06-22 23:49:57 -07:00
|
|
|
vec3_set(&br, -M_INFINITE, -M_INFINITE, 0.0f);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
2014-06-22 23:49:57 -07:00
|
|
|
auto GetMinPos = [&] (float x, float y)
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
{
|
|
|
|
vec3 pos;
|
|
|
|
vec3_set(&pos, x, y, 0.0f);
|
|
|
|
vec3_transform(&pos, &pos, &boxTransform);
|
2014-06-22 23:49:57 -07:00
|
|
|
vec3_min(&tl, &tl, &pos);
|
|
|
|
vec3_max(&br, &br, &pos);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
};
|
|
|
|
|
2014-06-22 23:49:57 -07:00
|
|
|
GetMinPos(0.0f, 0.0f);
|
|
|
|
GetMinPos(1.0f, 0.0f);
|
|
|
|
GetMinPos(0.0f, 1.0f);
|
|
|
|
GetMinPos(1.0f, 1.0f);
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
static vec3 GetItemTL(obs_sceneitem_t *item)
|
2014-06-22 23:49:57 -07:00
|
|
|
{
|
|
|
|
vec3 tl, br;
|
|
|
|
GetItemBox(item, tl, br);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
return tl;
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
static void SetItemTL(obs_sceneitem_t *item, const vec3 &tl)
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
{
|
|
|
|
vec3 newTL;
|
|
|
|
vec2 pos;
|
|
|
|
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_get_pos(item, &pos);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
newTL = GetItemTL(item);
|
|
|
|
pos.x += tl.x - newTL.x;
|
|
|
|
pos.y += tl.y - newTL.y;
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_set_pos(item, &pos);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
static bool RotateSelectedSources(obs_scene_t *scene, obs_sceneitem_t *item,
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
void *param)
|
|
|
|
{
|
|
|
|
if (!obs_sceneitem_selected(item))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
float rot = *reinterpret_cast<float*>(param);
|
|
|
|
|
|
|
|
vec3 tl = GetItemTL(item);
|
|
|
|
|
2014-08-03 14:39:19 -07:00
|
|
|
rot += obs_sceneitem_get_rot(item);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
if (rot >= 360.0f) rot -= 360.0f;
|
|
|
|
else if (rot <= -360.0f) rot += 360.0f;
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_set_rot(item, rot);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
|
|
|
SetItemTL(item, tl);
|
|
|
|
|
|
|
|
UNUSED_PARAMETER(scene);
|
|
|
|
UNUSED_PARAMETER(param);
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
void OBSBasic::on_actionRotate90CW_triggered()
|
|
|
|
{
|
|
|
|
float f90CW = 90.0f;
|
|
|
|
obs_scene_enum_items(GetCurrentScene(), RotateSelectedSources, &f90CW);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionRotate90CCW_triggered()
|
|
|
|
{
|
|
|
|
float f90CCW = -90.0f;
|
|
|
|
obs_scene_enum_items(GetCurrentScene(), RotateSelectedSources, &f90CCW);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionRotate180_triggered()
|
|
|
|
{
|
|
|
|
float f180 = 180.0f;
|
|
|
|
obs_scene_enum_items(GetCurrentScene(), RotateSelectedSources, &f180);
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
static bool MultiplySelectedItemScale(obs_scene_t *scene, obs_sceneitem_t *item,
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
void *param)
|
|
|
|
{
|
|
|
|
vec2 &mul = *reinterpret_cast<vec2*>(param);
|
|
|
|
|
|
|
|
if (!obs_sceneitem_selected(item))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
vec3 tl = GetItemTL(item);
|
|
|
|
|
|
|
|
vec2 scale;
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_get_scale(item, &scale);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
vec2_mul(&scale, &scale, &mul);
|
2014-08-03 14:39:19 -07:00
|
|
|
obs_sceneitem_set_scale(item, &scale);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
|
|
|
|
SetItemTL(item, tl);
|
2014-06-16 17:55:48 -07:00
|
|
|
|
|
|
|
UNUSED_PARAMETER(scene);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionFlipHorizontal_triggered()
|
|
|
|
{
|
2014-06-16 17:55:48 -07:00
|
|
|
vec2 scale;
|
|
|
|
vec2_set(&scale, -1.0f, 1.0f);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
obs_scene_enum_items(GetCurrentScene(), MultiplySelectedItemScale,
|
|
|
|
&scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionFlipVertical_triggered()
|
|
|
|
{
|
2014-06-16 17:55:48 -07:00
|
|
|
vec2 scale;
|
|
|
|
vec2_set(&scale, 1.0f, -1.0f);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
obs_scene_enum_items(GetCurrentScene(), MultiplySelectedItemScale,
|
|
|
|
&scale);
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
static bool CenterAlignSelectedItems(obs_scene_t *scene, obs_sceneitem_t *item,
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
void *param)
|
|
|
|
{
|
|
|
|
obs_bounds_type boundsType = *reinterpret_cast<obs_bounds_type*>(param);
|
|
|
|
|
|
|
|
if (!obs_sceneitem_selected(item))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
obs_video_info ovi;
|
|
|
|
obs_get_video_info(&ovi);
|
|
|
|
|
2014-08-01 23:33:45 -07:00
|
|
|
obs_transform_info itemInfo;
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
vec2_set(&itemInfo.pos, 0.0f, 0.0f);
|
|
|
|
vec2_set(&itemInfo.scale, 1.0f, 1.0f);
|
|
|
|
itemInfo.alignment = OBS_ALIGN_LEFT | OBS_ALIGN_TOP;
|
|
|
|
itemInfo.rot = 0.0f;
|
|
|
|
|
|
|
|
vec2_set(&itemInfo.bounds,
|
|
|
|
float(ovi.base_width), float(ovi.base_height));
|
|
|
|
itemInfo.bounds_type = boundsType;
|
|
|
|
itemInfo.bounds_alignment = OBS_ALIGN_CENTER;
|
|
|
|
|
|
|
|
obs_sceneitem_set_info(item, &itemInfo);
|
|
|
|
|
|
|
|
UNUSED_PARAMETER(scene);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionFitToScreen_triggered()
|
|
|
|
{
|
|
|
|
obs_bounds_type boundsType = OBS_BOUNDS_SCALE_INNER;
|
|
|
|
obs_scene_enum_items(GetCurrentScene(), CenterAlignSelectedItems,
|
|
|
|
&boundsType);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionStretchToScreen_triggered()
|
|
|
|
{
|
|
|
|
obs_bounds_type boundsType = OBS_BOUNDS_STRETCH;
|
|
|
|
obs_scene_enum_items(GetCurrentScene(), CenterAlignSelectedItems,
|
|
|
|
&boundsType);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::on_actionCenterToScreen_triggered()
|
|
|
|
{
|
2014-09-25 17:44:05 -07:00
|
|
|
auto func = [] (obs_scene_t *scene, obs_sceneitem_t *item, void *param)
|
2014-06-22 23:49:57 -07:00
|
|
|
{
|
|
|
|
vec3 tl, br, itemCenter, screenCenter, offset;
|
|
|
|
obs_video_info ovi;
|
|
|
|
|
|
|
|
if (!obs_sceneitem_selected(item))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
obs_get_video_info(&ovi);
|
|
|
|
|
|
|
|
vec3_set(&screenCenter, float(ovi.base_width),
|
|
|
|
float(ovi.base_height), 0.0f);
|
|
|
|
vec3_mulf(&screenCenter, &screenCenter, 0.5f);
|
|
|
|
|
|
|
|
GetItemBox(item, tl, br);
|
|
|
|
|
|
|
|
vec3_sub(&itemCenter, &br, &tl);
|
|
|
|
vec3_mulf(&itemCenter, &itemCenter, 0.5f);
|
|
|
|
vec3_add(&itemCenter, &itemCenter, &tl);
|
|
|
|
|
|
|
|
vec3_sub(&offset, &screenCenter, &itemCenter);
|
|
|
|
vec3_add(&tl, &tl, &offset);
|
|
|
|
|
|
|
|
SetItemTL(item, tl);
|
|
|
|
|
|
|
|
UNUSED_PARAMETER(scene);
|
2014-06-25 01:40:39 -07:00
|
|
|
UNUSED_PARAMETER(param);
|
2014-06-22 23:49:57 -07:00
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
obs_scene_enum_items(GetCurrentScene(), func, nullptr);
|
UI: Add scene editing
So, scene editing was interesting (and by interesting I mean
excruciating). I almost implemented 'manipulator' visuals (ala 3dsmax
for example), and used 3 modes for controlling position/rotation/size,
but in a 2D editing, it felt clunky, so I defaulted back to simply
click-and-drag for movement, and then took a similar though slightly
different looking approach for handling scaling and reszing.
I also added a number of menu item helpers related to positioning,
scaling, rotating, flipping, and resetting the transform back to
default.
There is also a new 'transform' dialog (accessible via menu) which will
allow you to manually edit every single transform variable of a scene
item directly if desired.
If a scene item does not have bounds active, pulling on the sides of a
source will cause it to resize it via base scale rather than by the
bounding box system (if the source resizes that scale will apply). If
bounds are active, it will modify the bounding box only instead.
How a source scales when a bounding box is active depends on the type of
bounds being used. You can set it to scale to the inner bounds, the
outer bounds, scale to bounds width only, scale to bounds height only,
and a setting to stretch to bounds (which forces a source to always draw
at the bounding box size rather than be affected by its internal size).
You can also set it to be used as a 'maximum' size, so that the source
doesn't necessarily get scaled unless it extends beyond the bounds.
Like in OBS1, objects will snap to the edges unless the control key is
pressed. However, this will now happen even if the object is rotated or
oriented in any strange way. Snapping will also occur when stretching
or changing the bounding box size.
2014-06-15 00:54:48 -07:00
|
|
|
}
|
2015-04-02 21:35:46 -07:00
|
|
|
|
|
|
|
void OBSBasic::TogglePreview()
|
|
|
|
{
|
|
|
|
bool enabled = !obs_preview_enabled();
|
|
|
|
obs_preview_set_enabled(enabled);
|
|
|
|
ui->preview->setVisible(enabled);
|
|
|
|
ui->previewDisabledLabel->setVisible(!enabled);
|
|
|
|
}
|
2015-04-02 23:09:13 -07:00
|
|
|
|
|
|
|
void OBSBasic::Nudge(int dist, MoveDir dir)
|
|
|
|
{
|
|
|
|
struct MoveInfo {
|
|
|
|
float dist;
|
|
|
|
MoveDir dir;
|
|
|
|
} info = {(float)dist, dir};
|
|
|
|
|
|
|
|
auto func = [] (obs_scene_t*, obs_sceneitem_t *item, void *param)
|
|
|
|
{
|
|
|
|
MoveInfo *info = reinterpret_cast<MoveInfo*>(param);
|
2015-04-10 10:07:56 -07:00
|
|
|
struct vec2 dir;
|
2015-04-02 23:09:13 -07:00
|
|
|
struct vec2 pos;
|
|
|
|
|
2015-04-10 10:07:56 -07:00
|
|
|
vec2_set(&dir, 0.0f, 0.0f);
|
|
|
|
|
2015-04-02 23:09:13 -07:00
|
|
|
if (!obs_sceneitem_selected(item))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
switch (info->dir) {
|
|
|
|
case MoveDir::Up: dir.y = -info->dist; break;
|
|
|
|
case MoveDir::Down: dir.y = info->dist; break;
|
|
|
|
case MoveDir::Left: dir.x = -info->dist; break;
|
|
|
|
case MoveDir::Right: dir.x = info->dist; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
obs_sceneitem_get_pos(item, &pos);
|
|
|
|
vec2_add(&pos, &pos, &dir);
|
|
|
|
obs_sceneitem_set_pos(item, &pos);
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
obs_scene_enum_items(GetCurrentScene(), func, &info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::NudgeUp() {Nudge(1, MoveDir::Up);}
|
|
|
|
void OBSBasic::NudgeDown() {Nudge(1, MoveDir::Down);}
|
|
|
|
void OBSBasic::NudgeLeft() {Nudge(1, MoveDir::Left);}
|
|
|
|
void OBSBasic::NudgeRight() {Nudge(1, MoveDir::Right);}
|
2015-04-04 01:40:15 -07:00
|
|
|
|
|
|
|
void OBSBasic::OpenProjector(obs_source_t *source, int monitor)
|
|
|
|
{
|
|
|
|
/* seriously? 10 monitors? */
|
|
|
|
if (monitor > 9)
|
|
|
|
return;
|
|
|
|
|
|
|
|
delete projectors[monitor];
|
|
|
|
projectors[monitor].clear();
|
|
|
|
|
|
|
|
OBSProjector *projector = new OBSProjector(this, source);
|
|
|
|
projector->Init(monitor);
|
|
|
|
|
|
|
|
projectors[monitor] = projector;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::OpenPreviewProjector()
|
|
|
|
{
|
|
|
|
int monitor = sender()->property("monitor").toInt();
|
|
|
|
OpenProjector(nullptr, monitor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::OpenSourceProjector()
|
|
|
|
{
|
|
|
|
int monitor = sender()->property("monitor").toInt();
|
|
|
|
OBSSceneItem item = GetCurrentSceneItem();
|
|
|
|
if (!item)
|
|
|
|
return;
|
|
|
|
|
|
|
|
OpenProjector(obs_sceneitem_get_source(item), monitor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSBasic::OpenSceneProjector()
|
|
|
|
{
|
|
|
|
int monitor = sender()->property("monitor").toInt();
|
|
|
|
OBSScene scene = GetCurrentScene();
|
|
|
|
if (!scene)
|
|
|
|
return;
|
|
|
|
|
|
|
|
OpenProjector(obs_scene_get_source(scene), monitor);
|
|
|
|
}
|