2013-11-07 15:45:03 -08:00
|
|
|
/******************************************************************************
|
2014-02-13 07:58:31 -08:00
|
|
|
Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@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,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2014-05-18 17:44:10 -07:00
|
|
|
#include <QBuffer>
|
2014-06-30 01:13:32 -07:00
|
|
|
#include <QAction>
|
2016-08-13 07:36:17 -07:00
|
|
|
#include <QSystemTrayIcon>
|
2013-12-22 22:40:07 -08:00
|
|
|
#include <obs.hpp>
|
2014-05-03 22:54:38 -07:00
|
|
|
#include <vector>
|
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 <memory>
|
2014-01-25 08:08:56 -08:00
|
|
|
#include "window-main.hpp"
|
2014-09-15 16:16:16 -07:00
|
|
|
#include "window-basic-interaction.hpp"
|
2014-03-23 01:07:54 -07:00
|
|
|
#include "window-basic-properties.hpp"
|
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 "window-basic-transform.hpp"
|
2014-12-28 00:38:00 -08:00
|
|
|
#include "window-basic-adv-audio.hpp"
|
2015-02-25 21:23:57 -08:00
|
|
|
#include "window-basic-filters.hpp"
|
2014-01-06 19:20:18 -08:00
|
|
|
|
2016-08-28 14:24:14 -07:00
|
|
|
#include <obs-frontend-internal.hpp>
|
|
|
|
|
2014-07-06 16:18:16 -07:00
|
|
|
#include <util/platform.h>
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
#include <util/threading.h>
|
2014-03-06 20:08:12 -08:00
|
|
|
#include <util/util.hpp>
|
|
|
|
|
2014-04-16 08:18:11 -07:00
|
|
|
#include <QPointer>
|
|
|
|
|
2017-01-25 00:39:18 -08:00
|
|
|
class QMessageBox;
|
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
|
|
|
class QListWidgetItem;
|
2014-05-03 22:54:38 -07:00
|
|
|
class VolControl;
|
2014-05-18 17:44:10 -07:00
|
|
|
class QNetworkReply;
|
2017-05-10 19:37:45 -07:00
|
|
|
class OBSBasicStats;
|
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-01-23 22:58:48 -08:00
|
|
|
#include "ui_OBSBasic.h"
|
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-05-03 22:54:38 -07:00
|
|
|
#define DESKTOP_AUDIO_1 Str("DesktopAudioDevice1")
|
|
|
|
#define DESKTOP_AUDIO_2 Str("DesktopAudioDevice2")
|
|
|
|
#define AUX_AUDIO_1 Str("AuxAudioDevice1")
|
|
|
|
#define AUX_AUDIO_2 Str("AuxAudioDevice2")
|
|
|
|
#define AUX_AUDIO_3 Str("AuxAudioDevice3")
|
|
|
|
|
UI: Add recording presets to simple output
So certain high-profile individuals were complaining that it was
difficult to configure recording settings for quality in OBS. So, I
decided to add a very easy-to-use auto-configuration for high quality
encoding -- including lossless encoding. This feature will
automatically configure ideal recording settings based upon a specified
quality level.
Recording quality presets added to simple output:
- Same as stream: Copies the encoded streaming data with no extra usage
hit.
- High quality: uses a higher CRF value (starting at 23) if using x264.
- Indistinguishable quality: uses a low CRF value (starting at 16) if
using x264.
- Lossless will spawn an FFmpeg output that uses huffyuv encoding. If a
user tries to select lossless, they will be warned both via a dialog
prompt and a warning message in the settings window to ensure they
understand that it requires tremendous amounts of free space. It will
always use the AVI file format.
Extra Notes:
- When High/Indistinguishable quality is set, it will allow you to
select the recording encoder. Currently, it just allows you to select
x264 (at either veryfast or ultrafast). Later on, it'll be useful to
be able to set up pre-configured presets for hardware encoders once
more are implemented and tested.
- I decided to allow the use of x264 at both veryfast or ultrafast
presets. The reasoning is two-fold:
1.) ultrafast is perfectly viable even for near indistinguishable
quality as long as it has the appropriate CRF value. It's nice if you
want to record but would like to or need to reduce the impact of
encoding on the CPU. It will automatically compensate for the preset at
the cost of larger file size.
2.) It was suggested to just always use ultrafast, but ultrafast
requires 2-4x as much disk space for the same CRF (most likely due to
x264 compensating for the preset). Providing veryfast is important if
you really want to reduce file size and/or reduce blocking at lower
quality levels.
- When a recording preset is used, a secondary audio encoder is also
spawned at 192 bitrate to ensure high quality audio. I chose 192
because that's the limit of the media foundation aac encoder on
windows, which I want to make sure is used if available due to its
high performance.
- The CRF calculation is based upon resolution, quality, and whether
it's set to ultrafast. First, quality sets the base CRF, 23 for
"good" quality, 16 for "very high" quality. If set to ultrafast,
it'll subtract 2 points from the CRF value to help compensate. Lower
resolutions will also lower the CRF value to help improve higher
details with a smaller pixel ratio.
2015-09-18 22:29:36 -07:00
|
|
|
#define SIMPLE_ENCODER_X264 "x264"
|
|
|
|
#define SIMPLE_ENCODER_X264_LOWCPU "x264_lowcpu"
|
2016-04-18 00:56:51 -07:00
|
|
|
#define SIMPLE_ENCODER_QSV "qsv"
|
2016-04-18 16:12:59 -07:00
|
|
|
#define SIMPLE_ENCODER_NVENC "nvenc"
|
2016-09-26 16:29:33 -07:00
|
|
|
#define SIMPLE_ENCODER_AMD "amd"
|
UI: Add recording presets to simple output
So certain high-profile individuals were complaining that it was
difficult to configure recording settings for quality in OBS. So, I
decided to add a very easy-to-use auto-configuration for high quality
encoding -- including lossless encoding. This feature will
automatically configure ideal recording settings based upon a specified
quality level.
Recording quality presets added to simple output:
- Same as stream: Copies the encoded streaming data with no extra usage
hit.
- High quality: uses a higher CRF value (starting at 23) if using x264.
- Indistinguishable quality: uses a low CRF value (starting at 16) if
using x264.
- Lossless will spawn an FFmpeg output that uses huffyuv encoding. If a
user tries to select lossless, they will be warned both via a dialog
prompt and a warning message in the settings window to ensure they
understand that it requires tremendous amounts of free space. It will
always use the AVI file format.
Extra Notes:
- When High/Indistinguishable quality is set, it will allow you to
select the recording encoder. Currently, it just allows you to select
x264 (at either veryfast or ultrafast). Later on, it'll be useful to
be able to set up pre-configured presets for hardware encoders once
more are implemented and tested.
- I decided to allow the use of x264 at both veryfast or ultrafast
presets. The reasoning is two-fold:
1.) ultrafast is perfectly viable even for near indistinguishable
quality as long as it has the appropriate CRF value. It's nice if you
want to record but would like to or need to reduce the impact of
encoding on the CPU. It will automatically compensate for the preset at
the cost of larger file size.
2.) It was suggested to just always use ultrafast, but ultrafast
requires 2-4x as much disk space for the same CRF (most likely due to
x264 compensating for the preset). Providing veryfast is important if
you really want to reduce file size and/or reduce blocking at lower
quality levels.
- When a recording preset is used, a secondary audio encoder is also
spawned at 192 bitrate to ensure high quality audio. I chose 192
because that's the limit of the media foundation aac encoder on
windows, which I want to make sure is used if available due to its
high performance.
- The CRF calculation is based upon resolution, quality, and whether
it's set to ultrafast. First, quality sets the base CRF, 23 for
"good" quality, 16 for "very high" quality. If set to ultrafast,
it'll subtract 2 points from the CRF value to help compensate. Lower
resolutions will also lower the CRF value to help improve higher
details with a smaller pixel ratio.
2015-09-18 22:29:36 -07:00
|
|
|
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
#define PREVIEW_EDGE_SIZE 10
|
|
|
|
|
2015-02-06 03:17:33 -08:00
|
|
|
struct BasicOutputHandler;
|
|
|
|
|
2015-06-27 18:21:45 -07:00
|
|
|
enum class QtDataRole {
|
|
|
|
OBSRef = Qt::UserRole,
|
|
|
|
OBSSignals,
|
|
|
|
};
|
|
|
|
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
struct QuickTransition {
|
|
|
|
QPushButton *button = nullptr;
|
|
|
|
OBSSource source;
|
|
|
|
obs_hotkey_id hotkey = 0;
|
|
|
|
int duration = 0;
|
|
|
|
int id = 0;
|
|
|
|
|
|
|
|
inline QuickTransition() {}
|
|
|
|
inline QuickTransition(OBSSource source_, int duration_, int id_)
|
|
|
|
: source (source_),
|
|
|
|
duration (duration_),
|
|
|
|
id (id_)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2014-01-25 08:08:56 -08:00
|
|
|
class OBSBasic : public OBSMainWindow {
|
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
|
|
|
Q_OBJECT
|
|
|
|
|
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
|
|
|
friend class OBSBasicPreview;
|
2015-09-06 16:19:53 -07:00
|
|
|
friend class OBSBasicStatusBar;
|
2016-07-01 15:23:06 -07:00
|
|
|
friend class OBSBasicSourceSelect;
|
2016-12-07 05:21:44 -08:00
|
|
|
friend class OBSBasicSettings;
|
2016-08-28 14:24:14 -07:00
|
|
|
friend struct OBSStudioAPI;
|
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 23:09:13 -07:00
|
|
|
enum class MoveDir {
|
|
|
|
Up,
|
|
|
|
Down,
|
|
|
|
Left,
|
|
|
|
Right
|
|
|
|
};
|
|
|
|
|
2016-10-02 16:12:53 -07:00
|
|
|
enum DropType {
|
|
|
|
DropType_RawText,
|
|
|
|
DropType_Text,
|
|
|
|
DropType_Image,
|
|
|
|
DropType_Media
|
|
|
|
};
|
|
|
|
|
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
|
|
|
private:
|
2016-08-28 14:24:14 -07:00
|
|
|
obs_frontend_callbacks *api = nullptr;
|
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
std::vector<VolControl*> volumes;
|
|
|
|
|
2015-06-27 00:29:17 -07:00
|
|
|
std::vector<OBSSignal> signalHandlers;
|
|
|
|
|
2016-12-29 07:21:53 -08:00
|
|
|
std::vector<std::string> projectorArray;
|
|
|
|
std::vector<int> previewProjectorArray;
|
|
|
|
|
2014-06-16 19:41:36 -07:00
|
|
|
bool loaded = false;
|
2015-06-30 05:49:31 -07:00
|
|
|
long disableSaving = 1;
|
2015-07-06 09:02:13 -07:00
|
|
|
bool projectChanged = false;
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
bool previewEnabled = true;
|
2014-06-16 19:41:36 -07:00
|
|
|
|
2017-03-25 04:19:29 -07:00
|
|
|
const char *copyString;
|
|
|
|
const char *copyFiltersString;
|
|
|
|
bool copyVisible = 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
|
|
|
QPointer<QThread> updateCheckThread;
|
|
|
|
QPointer<QThread> logUploadThread;
|
|
|
|
|
2014-09-15 16:16:16 -07:00
|
|
|
QPointer<OBSBasicInteraction> interaction;
|
2014-05-03 22:54:38 -07:00
|
|
|
QPointer<OBSBasicProperties> properties;
|
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
|
|
|
QPointer<OBSBasicTransform> transformWindow;
|
2014-12-28 00:38:00 -08:00
|
|
|
QPointer<OBSBasicAdvAudio> advAudioWindow;
|
2015-02-25 21:23:57 -08:00
|
|
|
QPointer<OBSBasicFilters> filters;
|
2014-05-03 22:54:38 -07:00
|
|
|
|
2014-07-06 16:19:27 -07:00
|
|
|
QPointer<QTimer> cpuUsageTimer;
|
2014-09-25 17:44:05 -07:00
|
|
|
os_cpu_usage_info_t *cpuUsageInfo = nullptr;
|
2014-07-06 16:18:16 -07:00
|
|
|
|
2015-05-03 17:07:43 -07:00
|
|
|
OBSService service;
|
2015-02-06 03:17:33 -08:00
|
|
|
std::unique_ptr<BasicOutputHandler> outputHandler;
|
2016-09-09 07:37:54 -07:00
|
|
|
bool streamingStopping = false;
|
|
|
|
bool recordingStopping = false;
|
2016-12-09 14:40:04 -08:00
|
|
|
bool replayBufferStopping = false;
|
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
|
|
|
gs_vertbuffer_t *box = nullptr;
|
2016-03-30 18:44:49 -07:00
|
|
|
gs_vertbuffer_t *boxLeft = nullptr;
|
|
|
|
gs_vertbuffer_t *boxTop = nullptr;
|
|
|
|
gs_vertbuffer_t *boxRight = nullptr;
|
|
|
|
gs_vertbuffer_t *boxBottom = nullptr;
|
2014-09-25 17:44:05 -07:00
|
|
|
gs_vertbuffer_t *circle = nullptr;
|
2014-01-06 19:20:18 -08: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
|
|
|
bool sceneChanging = false;
|
2015-06-26 18:32:33 -07:00
|
|
|
bool ignoreSelectionUpdate = false;
|
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
|
|
|
|
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
|
|
|
int previewX = 0, previewY = 0;
|
|
|
|
int previewCX = 0, previewCY = 0;
|
|
|
|
float previewScale = 0.0f;
|
2014-03-07 09:19:03 -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
|
|
|
ConfigFile basicConfig;
|
2014-03-06 20:08:12 -08:00
|
|
|
|
2015-04-04 01:40:15 -07:00
|
|
|
QPointer<QWidget> projectors[10];
|
2017-03-01 20:08:49 -08:00
|
|
|
QList<QPointer<QWidget>> windowProjectors;
|
2015-04-04 01:40:15 -07:00
|
|
|
|
2017-05-10 19:37:45 -07:00
|
|
|
QPointer<QWidget> stats;
|
|
|
|
|
2015-09-06 16:19:53 -07:00
|
|
|
QPointer<QMenu> startStreamMenu;
|
|
|
|
|
2016-12-09 14:40:04 -08:00
|
|
|
QPointer<QPushButton> replayBufferButton;
|
|
|
|
|
2016-10-19 06:44:02 -07:00
|
|
|
QPointer<QSystemTrayIcon> trayIcon;
|
|
|
|
QPointer<QAction> sysTrayStream;
|
|
|
|
QPointer<QAction> sysTrayRecord;
|
2016-12-09 14:40:04 -08:00
|
|
|
QPointer<QAction> sysTrayReplayBuffer;
|
2016-10-19 06:44:02 -07:00
|
|
|
QPointer<QAction> showHide;
|
|
|
|
QPointer<QAction> exit;
|
|
|
|
QPointer<QMenu> trayMenu;
|
2016-08-13 07:36:17 -07:00
|
|
|
|
2014-06-15 19:48:02 -07:00
|
|
|
void DrawBackdrop(float cx, float cy);
|
|
|
|
|
2014-05-20 23:27:27 -07:00
|
|
|
void SetupEncoders();
|
|
|
|
|
2015-09-23 08:41:00 -07:00
|
|
|
void CreateFirstRunSources();
|
2015-09-11 21:51:09 -07:00
|
|
|
void CreateDefaultScene(bool firstStart);
|
2014-05-03 22:54:38 -07:00
|
|
|
|
|
|
|
void ClearVolumeControls();
|
2014-03-23 01:07:54 -07:00
|
|
|
|
2014-05-18 17:44:10 -07:00
|
|
|
void UploadLog(const char *file);
|
|
|
|
|
2014-04-26 23:47:50 -07:00
|
|
|
void Save(const char *file);
|
|
|
|
void Load(const char *file);
|
|
|
|
|
2014-11-01 13:48:58 -07:00
|
|
|
void InitHotkeys();
|
2014-11-01 13:53:25 -07:00
|
|
|
void CreateHotkeys();
|
2015-06-29 00:47:07 -07:00
|
|
|
void ClearHotkeys();
|
2014-11-01 13:48:58 -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
|
|
|
bool InitService();
|
|
|
|
|
|
|
|
bool InitBasicConfigDefaults();
|
|
|
|
bool InitBasicConfig();
|
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
void InitOBSCallbacks();
|
|
|
|
|
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 InitPrimitives();
|
|
|
|
|
2014-09-15 16:04:22 -07:00
|
|
|
OBSSceneItem GetSceneItem(QListWidgetItem *item);
|
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
|
|
|
OBSSceneItem GetCurrentSceneItem();
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
bool QueryRemoveSource(obs_source_t *source);
|
2014-06-30 13:45:58 -07:00
|
|
|
|
2014-07-13 23:56:28 -07:00
|
|
|
void TimedCheckForUpdates();
|
2017-02-20 04:46:29 -08:00
|
|
|
void CheckForUpdates(bool manualUpdate);
|
2014-07-13 23:56:28 -07:00
|
|
|
|
2014-03-06 20:08:12 -08:00
|
|
|
void GetFPSCommon(uint32_t &num, uint32_t &den) const;
|
|
|
|
void GetFPSInteger(uint32_t &num, uint32_t &den) const;
|
|
|
|
void GetFPSFraction(uint32_t &num, uint32_t &den) const;
|
|
|
|
void GetFPSNanoseconds(uint32_t &num, uint32_t &den) const;
|
|
|
|
void GetConfigFPS(uint32_t &num, uint32_t &den) const;
|
|
|
|
|
2016-11-05 09:48:46 -07:00
|
|
|
void UpdatePreviewScalingMenu();
|
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
void UpdateSources(OBSScene scene);
|
2014-09-25 17:44:05 -07:00
|
|
|
void InsertSceneItem(obs_sceneitem_t *item);
|
2014-02-02 16:03:55 -08:00
|
|
|
|
2015-06-25 03:53:48 -07:00
|
|
|
void LoadSceneListOrder(obs_data_array_t *array);
|
|
|
|
obs_data_array_t *SaveSceneListOrder();
|
|
|
|
void ChangeSceneIndex(bool relative, int idx, int invalidIdx);
|
|
|
|
|
2014-04-14 02:22:09 -07:00
|
|
|
void TempFileOutput(const char *path, int vBitrate, int aBitrate);
|
|
|
|
void TempStreamOutput(const char *url, const char *key,
|
|
|
|
int vBitrate, int aBitrate);
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void CreateInteractionWindow(obs_source_t *source);
|
|
|
|
void CreatePropertiesWindow(obs_source_t *source);
|
2015-02-25 21:23:57 -08:00
|
|
|
void CreateFiltersWindow(obs_source_t *source);
|
2014-07-22 13:16:57 -07:00
|
|
|
|
2015-07-02 16:12:47 -07:00
|
|
|
void CloseDialogs();
|
|
|
|
void ClearSceneData();
|
|
|
|
|
2015-04-02 23:09:13 -07:00
|
|
|
void Nudge(int dist, MoveDir dir);
|
2017-03-01 20:08:49 -08:00
|
|
|
void OpenProjector(obs_source_t *source, int monitor, bool window,
|
|
|
|
QString title = nullptr);
|
2015-04-02 23:09:13 -07:00
|
|
|
|
2015-06-20 18:57:06 -07:00
|
|
|
void GetAudioSourceFilters();
|
|
|
|
void GetAudioSourceProperties();
|
|
|
|
void VolControlContextMenu();
|
|
|
|
|
2015-06-23 19:29:07 -07:00
|
|
|
void AddSceneCollection(bool create_new);
|
|
|
|
void RefreshSceneCollections();
|
|
|
|
void ChangeSceneCollection();
|
2016-08-05 17:43:30 -07:00
|
|
|
void LogScenes();
|
2015-06-23 19:29:07 -07:00
|
|
|
|
2015-06-23 19:38:01 -07:00
|
|
|
void LoadProfile();
|
|
|
|
void ResetProfileData();
|
|
|
|
bool AddProfile(bool create_new, const char *title, const char *text,
|
|
|
|
const char *init_text = nullptr);
|
|
|
|
void DeleteProfile(const char *profile_name, const char *profile_dir);
|
|
|
|
void RefreshProfiles();
|
|
|
|
void ChangeProfile();
|
|
|
|
|
2015-07-09 10:51:22 -07:00
|
|
|
void SaveProjectNow();
|
|
|
|
|
2016-01-23 11:02:22 -08:00
|
|
|
QListWidgetItem *GetTopSelectedSourceItem();
|
|
|
|
|
2016-12-09 14:40:04 -08:00
|
|
|
obs_hotkey_pair_id streamingHotkeys, recordingHotkeys,
|
|
|
|
replayBufHotkeys;
|
2015-09-06 16:19:53 -07:00
|
|
|
obs_hotkey_id forceStreamingStopHotkey;
|
2014-11-01 13:53:25 -07:00
|
|
|
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
void InitDefaultTransitions();
|
|
|
|
void InitTransition(obs_source_t *transition);
|
|
|
|
obs_source_t *FindTransition(const char *name);
|
|
|
|
OBSSource GetCurrentTransition();
|
2016-02-27 02:50:04 -08:00
|
|
|
obs_data_array_t *SaveTransitions();
|
|
|
|
void LoadTransitions(obs_data_array_t *transitions);
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
|
|
|
|
obs_source_t *fadeTransition;
|
|
|
|
|
|
|
|
void CreateProgramDisplay();
|
|
|
|
void CreateProgramOptions();
|
|
|
|
void AddQuickTransitionId(int id);
|
|
|
|
void AddQuickTransition();
|
|
|
|
void AddQuickTransitionHotkey(QuickTransition *qt);
|
|
|
|
void RemoveQuickTransitionHotkey(QuickTransition *qt);
|
|
|
|
void LoadQuickTransitions(obs_data_array_t *array);
|
|
|
|
obs_data_array_t *SaveQuickTransitions();
|
2017-05-14 23:06:11 -07:00
|
|
|
void ClearQuickTransitionWidgets();
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
void RefreshQuickTransitions();
|
|
|
|
void CreateDefaultQuickTransitions();
|
|
|
|
|
|
|
|
QuickTransition *GetQuickTransition(int id);
|
|
|
|
int GetQuickTransitionIdx(int id);
|
|
|
|
QMenu *CreateTransitionMenu(QWidget *parent, QuickTransition *qt);
|
|
|
|
void ClearQuickTransitions();
|
|
|
|
void QuickTransitionClicked();
|
|
|
|
void QuickTransitionChange();
|
|
|
|
void QuickTransitionChangeDuration(int value);
|
|
|
|
void QuickTransitionRemoveClicked();
|
|
|
|
|
|
|
|
void SetPreviewProgramMode(bool enabled);
|
|
|
|
void ResizeProgram(uint32_t cx, uint32_t cy);
|
|
|
|
void SetCurrentScene(obs_scene_t *scene, bool force = false);
|
|
|
|
static void RenderProgram(void *data, uint32_t cx, uint32_t cy);
|
|
|
|
|
|
|
|
std::vector<QuickTransition> quickTransitions;
|
|
|
|
QPointer<QWidget> programOptions;
|
|
|
|
QPointer<OBSQTDisplay> program;
|
|
|
|
OBSWeakSource lastScene;
|
|
|
|
OBSWeakSource swapScene;
|
|
|
|
OBSWeakSource programScene;
|
|
|
|
bool editPropertiesMode = false;
|
|
|
|
bool sceneDuplicationMode = true;
|
|
|
|
bool swapScenesMode = true;
|
|
|
|
volatile bool previewProgramMode = false;
|
|
|
|
obs_hotkey_id togglePreviewProgramHotkey = 0;
|
|
|
|
obs_hotkey_id transitionHotkey = 0;
|
|
|
|
int quickTransitionIdCounter = 1;
|
|
|
|
|
|
|
|
int programX = 0, programY = 0;
|
|
|
|
int programCX = 0, programCY = 0;
|
|
|
|
float programScale = 0.0f;
|
|
|
|
|
2017-05-15 14:15:25 -07:00
|
|
|
int disableOutputsRef = 0;
|
2017-04-28 03:58:53 -07:00
|
|
|
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
inline bool IsPreviewProgramMode() const
|
|
|
|
{
|
|
|
|
return os_atomic_load_bool(&previewProgramMode);
|
|
|
|
}
|
|
|
|
|
2016-08-21 12:05:25 -07:00
|
|
|
inline void OnActivate();
|
|
|
|
inline void OnDeactivate();
|
|
|
|
|
2016-10-02 16:12:53 -07:00
|
|
|
void AddDropSource(const char *file, DropType image);
|
2016-09-26 12:40:23 -07:00
|
|
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
|
|
|
void dragLeaveEvent(QDragLeaveEvent *event) override;
|
|
|
|
void dragMoveEvent(QDragMoveEvent *event) override;
|
|
|
|
void dropEvent(QDropEvent *event) override;
|
|
|
|
|
2016-12-09 14:40:04 -08:00
|
|
|
void ReplayBufferClicked();
|
|
|
|
|
2017-01-24 23:01:24 -08:00
|
|
|
bool sysTrayMinimizeToTray();
|
|
|
|
|
2017-01-25 00:39:18 -08:00
|
|
|
void EnumDialogs();
|
|
|
|
|
|
|
|
QList<QDialog*> visDialogs;
|
|
|
|
QList<QDialog*> modalDialogs;
|
|
|
|
QList<QMessageBox*> visMsgBoxes;
|
|
|
|
|
|
|
|
QList<QPoint> visDlgPositions;
|
|
|
|
|
2016-12-29 07:21:53 -08:00
|
|
|
obs_data_array_t *SaveProjectors();
|
|
|
|
void LoadSavedProjectors(obs_data_array_t *savedProjectors);
|
|
|
|
|
|
|
|
obs_data_array_t *SavePreviewProjectors();
|
|
|
|
void LoadSavedPreviewProjectors(
|
|
|
|
obs_data_array_t *savedPreviewProjectors);
|
|
|
|
|
2014-03-10 13:10:35 -07:00
|
|
|
public slots:
|
2014-10-25 17:03:13 -07:00
|
|
|
void StartStreaming();
|
|
|
|
void StopStreaming();
|
2015-09-06 16:19:53 -07:00
|
|
|
void ForceStopStreaming();
|
|
|
|
|
|
|
|
void StreamDelayStarting(int sec);
|
|
|
|
void StreamDelayStopping(int sec);
|
2014-10-25 17:03:13 -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
|
|
|
void StreamingStart();
|
2016-06-22 01:47:08 -07:00
|
|
|
void StreamStopping();
|
2017-05-15 03:03:00 -07:00
|
|
|
void StreamingStop(int errorcode, QString last_error);
|
2014-03-10 13:10:35 -07:00
|
|
|
|
2014-10-25 16:57:29 -07:00
|
|
|
void StartRecording();
|
|
|
|
void StopRecording();
|
|
|
|
|
2014-08-24 18:10:57 -07:00
|
|
|
void RecordingStart();
|
2016-06-22 01:47:08 -07:00
|
|
|
void RecordStopping();
|
2015-06-09 21:00:22 -07:00
|
|
|
void RecordingStop(int code);
|
2014-05-20 23:27:27 -07:00
|
|
|
|
2016-12-09 14:40:04 -08:00
|
|
|
void StartReplayBuffer();
|
|
|
|
void StopReplayBuffer();
|
|
|
|
|
|
|
|
void ReplayBufferStart();
|
|
|
|
void ReplayBufferStopping();
|
|
|
|
void ReplayBufferStop(int code);
|
|
|
|
|
2015-07-06 09:02:13 -07:00
|
|
|
void SaveProjectDeferred();
|
2015-01-04 08:20:15 -08:00
|
|
|
void SaveProject();
|
|
|
|
|
2016-09-06 04:52:30 -07:00
|
|
|
void SetTransition(OBSSource transition);
|
|
|
|
void TransitionToScene(OBSScene scene, bool force = false);
|
|
|
|
void TransitionToScene(OBSSource scene, bool force = false);
|
|
|
|
void SetCurrentScene(OBSSource scene, bool force = false);
|
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
private slots:
|
|
|
|
void AddSceneItem(OBSSceneItem item);
|
|
|
|
void RemoveSceneItem(OBSSceneItem item);
|
|
|
|
void AddScene(OBSSource source);
|
|
|
|
void RemoveScene(OBSSource source);
|
2014-06-30 00:06:01 -07:00
|
|
|
void RenameSources(QString newName, QString prevName);
|
2014-02-02 16:03:55 -08:00
|
|
|
|
2014-10-13 13:14:06 -07:00
|
|
|
void SelectSceneItem(OBSScene scene, OBSSceneItem item, bool select);
|
2014-05-15 17:40:53 -07:00
|
|
|
|
2014-05-03 22:54:38 -07:00
|
|
|
void ActivateAudioSource(OBSSource source);
|
|
|
|
void DeactivateAudioSource(OBSSource source);
|
|
|
|
|
2015-08-28 15:01:39 -07:00
|
|
|
void DuplicateSelectedScene();
|
2014-06-30 13:45:58 -07:00
|
|
|
void RemoveSelectedScene();
|
|
|
|
void RemoveSelectedSceneItem();
|
2014-06-30 01:13:32 -07:00
|
|
|
|
2016-01-22 07:33:29 -08:00
|
|
|
void ToggleAlwaysOnTop();
|
|
|
|
|
2015-02-19 11:02:54 -08:00
|
|
|
void ReorderSources(OBSScene scene);
|
|
|
|
|
2014-11-01 13:48:58 -07:00
|
|
|
void ProcessHotkey(obs_hotkey_id id, bool pressed);
|
|
|
|
|
2016-02-27 02:50:04 -08:00
|
|
|
void AddTransition();
|
|
|
|
void RenameTransition();
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
void TransitionClicked();
|
|
|
|
void TransitionStopped();
|
|
|
|
void TriggerQuickTransition(int id);
|
|
|
|
|
2016-03-15 20:55:40 -07:00
|
|
|
void SetDeinterlacingMode();
|
|
|
|
void SetDeinterlacingOrder();
|
|
|
|
|
2016-06-29 07:08:02 -07:00
|
|
|
void SetScaleFilter();
|
|
|
|
|
2016-08-13 07:36:17 -07:00
|
|
|
void IconActivated(QSystemTrayIcon::ActivationReason reason);
|
|
|
|
void SetShowing(bool showing);
|
|
|
|
|
2017-01-25 00:39:18 -08:00
|
|
|
void ToggleShowHide();
|
2016-08-13 07:36:17 -07:00
|
|
|
|
2017-03-25 04:19:29 -07:00
|
|
|
void on_actionCopySource_triggered();
|
|
|
|
void on_actionPasteRef_triggered();
|
|
|
|
void on_actionPasteDup_triggered();
|
|
|
|
|
|
|
|
void on_actionCopyFilters_triggered();
|
|
|
|
void on_actionPasteFilters_triggered();
|
|
|
|
|
2014-02-02 16:03:55 -08:00
|
|
|
private:
|
2014-01-04 12:53:36 -08:00
|
|
|
/* OBS Callbacks */
|
2015-02-19 11:02:54 -08:00
|
|
|
static void SceneReordered(void *data, calldata_t *params);
|
2014-09-25 17:44:05 -07:00
|
|
|
static void SceneItemAdded(void *data, calldata_t *params);
|
|
|
|
static void SceneItemRemoved(void *data, calldata_t *params);
|
2014-10-13 13:14:06 -07:00
|
|
|
static void SceneItemSelected(void *data, calldata_t *params);
|
|
|
|
static void SceneItemDeselected(void *data, calldata_t *params);
|
2016-03-04 12:56:09 -08:00
|
|
|
static void SourceLoaded(void *data, obs_source_t *source);
|
2014-09-25 17:44:05 -07:00
|
|
|
static void SourceRemoved(void *data, calldata_t *params);
|
|
|
|
static void SourceActivated(void *data, calldata_t *params);
|
|
|
|
static void SourceDeactivated(void *data, calldata_t *params);
|
|
|
|
static void SourceRenamed(void *data, calldata_t *params);
|
2014-02-13 07:58:31 -08:00
|
|
|
static void RenderMain(void *data, uint32_t cx, uint32_t cy);
|
2013-12-28 04:33:16 -08:00
|
|
|
|
2013-12-31 03:02:07 -08:00
|
|
|
void ResizePreview(uint32_t cx, uint32_t cy);
|
|
|
|
|
2014-05-10 18:47:48 -07:00
|
|
|
void AddSource(const char *id);
|
2014-06-29 17:33:40 -07:00
|
|
|
QMenu *CreateAddSourcePopupMenu();
|
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 AddSourcePopupMenu(const QPoint &pos);
|
2015-02-16 23:45:34 -08:00
|
|
|
void copyActionsDynamicProperties();
|
2013-12-30 05:56:39 -08:00
|
|
|
|
2014-11-01 13:48:58 -07:00
|
|
|
static void HotkeyTriggered(void *data, obs_hotkey_id id, bool pressed);
|
|
|
|
|
2014-02-22 19:14:19 -08:00
|
|
|
public:
|
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
|
|
|
OBSScene GetCurrentScene();
|
|
|
|
|
2016-08-13 07:36:17 -07:00
|
|
|
void SysTrayNotify(const QString &text, QSystemTrayIcon::MessageIcon n);
|
|
|
|
|
2016-01-18 12:59:28 -08:00
|
|
|
inline OBSSource GetCurrentSceneSource()
|
|
|
|
{
|
|
|
|
OBSScene curScene = GetCurrentScene();
|
|
|
|
return OBSSource(obs_scene_get_source(curScene));
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
obs_service_t *GetService();
|
|
|
|
void SetService(obs_service_t *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
|
|
|
|
2016-07-01 10:27:27 -07:00
|
|
|
bool StreamingActive() const;
|
|
|
|
bool Active() const;
|
2015-02-07 08:09:57 -08:00
|
|
|
|
2014-07-20 17:40:57 -07:00
|
|
|
int ResetVideo();
|
2014-02-22 19:14:19 -08:00
|
|
|
bool ResetAudio();
|
2015-02-06 03:17:33 -08:00
|
|
|
|
|
|
|
void ResetOutputs();
|
2013-12-22 22:40:07 -08:00
|
|
|
|
2015-06-23 18:47:22 -07:00
|
|
|
void ResetAudioDevice(const char *sourceId, const char *deviceId,
|
2014-05-12 15:30:36 -07:00
|
|
|
const char *deviceDesc, int channel);
|
2014-03-07 11:56:31 -08:00
|
|
|
|
2013-12-20 10:56:01 -08:00
|
|
|
void NewProject();
|
|
|
|
void LoadProject();
|
|
|
|
|
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
|
|
|
inline void GetDisplayRect(int &x, int &y, int &cx, int &cy)
|
|
|
|
{
|
|
|
|
x = previewX;
|
|
|
|
y = previewY;
|
|
|
|
cx = previewCX;
|
|
|
|
cy = previewCY;
|
|
|
|
}
|
|
|
|
|
2014-07-06 16:18:16 -07:00
|
|
|
inline double GetCPUUsage() const
|
|
|
|
{
|
|
|
|
return os_cpu_usage_info_query(cpuUsageInfo);
|
|
|
|
}
|
|
|
|
|
2015-02-07 08:09:57 -08:00
|
|
|
void SaveService();
|
|
|
|
bool LoadService();
|
|
|
|
|
2017-04-28 03:58:53 -07:00
|
|
|
inline void EnableOutputs(bool enable)
|
|
|
|
{
|
2017-05-15 14:15:25 -07:00
|
|
|
if (enable) {
|
|
|
|
if (--disableOutputsRef < 0)
|
|
|
|
disableOutputsRef = 0;
|
|
|
|
} else {
|
|
|
|
disableOutputsRef++;
|
|
|
|
}
|
2017-04-28 03:58:53 -07:00
|
|
|
}
|
|
|
|
|
2015-02-19 11:02:54 -08:00
|
|
|
void ReorderSceneItem(obs_sceneitem_t *item, size_t idx);
|
|
|
|
|
2016-03-15 20:55:40 -07:00
|
|
|
QMenu *AddDeinterlacingMenu(obs_source_t *source);
|
2016-06-29 07:08:02 -07:00
|
|
|
QMenu *AddScaleFilteringMenu(obs_sceneitem_t *item);
|
2015-04-02 21:35:46 -07:00
|
|
|
void CreateSourcePopupMenu(QListWidgetItem *item, bool preview);
|
|
|
|
|
2015-07-03 17:55:55 -07:00
|
|
|
void UpdateTitleBar();
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
void UpdateSceneSelection(OBSSource source);
|
2015-07-03 17:55:55 -07:00
|
|
|
|
2016-08-13 07:36:17 -07:00
|
|
|
void SystemTrayInit();
|
|
|
|
void SystemTray(bool firstStarted);
|
|
|
|
|
2016-12-29 07:21:53 -08:00
|
|
|
void OpenSavedProjectors();
|
|
|
|
void RemoveSavedProjectors(int monitor);
|
|
|
|
|
2013-11-07 15:45:03 -08:00
|
|
|
protected:
|
2014-01-25 08:08:56 -08:00
|
|
|
virtual void closeEvent(QCloseEvent *event) override;
|
|
|
|
virtual void changeEvent(QEvent *event) override;
|
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
|
|
|
|
|
|
|
private slots:
|
2014-08-21 18:18:42 -07:00
|
|
|
void on_actionShow_Recordings_triggered();
|
2014-09-02 19:11:55 -07:00
|
|
|
void on_actionRemux_triggered();
|
2014-04-15 05:19:59 -07:00
|
|
|
void on_action_Settings_triggered();
|
2014-12-28 00:38:00 -08:00
|
|
|
void on_actionAdvAudioProperties_triggered();
|
2015-02-07 02:11:42 -08:00
|
|
|
void on_advAudioProps_clicked();
|
2015-02-13 04:06:55 -08:00
|
|
|
void on_advAudioProps_destroyed();
|
2014-08-21 18:19:19 -07:00
|
|
|
void on_actionShowLogs_triggered();
|
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 on_actionUploadCurrentLog_triggered();
|
|
|
|
void on_actionUploadLastLog_triggered();
|
2015-02-23 22:04:19 -08:00
|
|
|
void on_actionViewCurrentLog_triggered();
|
2014-07-13 23:56:28 -07:00
|
|
|
void on_actionCheckForUpdates_triggered();
|
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 on_actionEditTransform_triggered();
|
2016-12-06 23:43:23 -08:00
|
|
|
void on_actionCopyTransform_triggered();
|
|
|
|
void on_actionPasteTransform_triggered();
|
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 on_actionRotate90CW_triggered();
|
|
|
|
void on_actionRotate90CCW_triggered();
|
|
|
|
void on_actionRotate180_triggered();
|
|
|
|
void on_actionFlipHorizontal_triggered();
|
|
|
|
void on_actionFlipVertical_triggered();
|
|
|
|
void on_actionFitToScreen_triggered();
|
|
|
|
void on_actionStretchToScreen_triggered();
|
|
|
|
void on_actionCenterToScreen_triggered();
|
|
|
|
|
2014-02-20 21:04:14 -08:00
|
|
|
void on_scenes_currentItemChanged(QListWidgetItem *current,
|
|
|
|
QListWidgetItem *prev);
|
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 on_scenes_customContextMenuRequested(const QPoint &pos);
|
|
|
|
void on_actionAddScene_triggered();
|
|
|
|
void on_actionRemoveScene_triggered();
|
|
|
|
void on_actionSceneUp_triggered();
|
|
|
|
void on_actionSceneDown_triggered();
|
2015-11-15 08:39:50 -08:00
|
|
|
void on_sources_itemSelectionChanged();
|
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 on_sources_customContextMenuRequested(const QPoint &pos);
|
2014-10-15 13:05:56 -07:00
|
|
|
void on_sources_itemDoubleClicked(QListWidgetItem *item);
|
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 on_actionAddSource_triggered();
|
|
|
|
void on_actionRemoveSource_triggered();
|
2014-09-15 16:16:16 -07:00
|
|
|
void on_actionInteract_triggered();
|
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 on_actionSourceProperties_triggered();
|
|
|
|
void on_actionSourceUp_triggered();
|
|
|
|
void on_actionSourceDown_triggered();
|
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-30 19:47:06 -07:00
|
|
|
void on_actionMoveUp_triggered();
|
|
|
|
void on_actionMoveDown_triggered();
|
|
|
|
void on_actionMoveToTop_triggered();
|
|
|
|
void on_actionMoveToBottom_triggered();
|
|
|
|
|
2016-07-26 01:32:43 -07:00
|
|
|
void on_actionLockPreview_triggered();
|
|
|
|
|
2016-11-05 09:48:46 -07:00
|
|
|
void on_scalingMenu_aboutToShow();
|
|
|
|
void on_actionScaleWindow_triggered();
|
|
|
|
void on_actionScaleCanvas_triggered();
|
|
|
|
void on_actionScaleOutput_triggered();
|
|
|
|
|
2014-03-10 13:10:35 -07:00
|
|
|
void on_streamButton_clicked();
|
2014-05-20 23:27:27 -07:00
|
|
|
void on_recordButton_clicked();
|
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 on_settingsButton_clicked();
|
2013-11-07 15:45:03 -08:00
|
|
|
|
2015-06-25 01:02:47 -07:00
|
|
|
void on_actionWebsite_triggered();
|
|
|
|
|
2015-04-02 21:35:46 -07:00
|
|
|
void on_preview_customContextMenuRequested(const QPoint &pos);
|
|
|
|
void on_previewDisabledLabel_customContextMenuRequested(
|
|
|
|
const QPoint &pos);
|
|
|
|
|
2015-06-23 19:29:07 -07:00
|
|
|
void on_actionNewSceneCollection_triggered();
|
|
|
|
void on_actionDupSceneCollection_triggered();
|
|
|
|
void on_actionRenameSceneCollection_triggered();
|
|
|
|
void on_actionRemoveSceneCollection_triggered();
|
2016-12-08 15:09:22 -08:00
|
|
|
void on_actionImportSceneCollection_triggered();
|
|
|
|
void on_actionExportSceneCollection_triggered();
|
2015-06-23 19:29:07 -07:00
|
|
|
|
2015-06-23 19:38:01 -07:00
|
|
|
void on_actionNewProfile_triggered();
|
|
|
|
void on_actionDupProfile_triggered();
|
|
|
|
void on_actionRenameProfile_triggered();
|
|
|
|
void on_actionRemoveProfile_triggered();
|
2016-12-08 15:09:22 -08:00
|
|
|
void on_actionImportProfile_triggered();
|
|
|
|
void on_actionExportProfile_triggered();
|
2015-06-23 19:38:01 -07:00
|
|
|
|
2015-07-02 20:41:19 -07:00
|
|
|
void on_actionShowSettingsFolder_triggered();
|
|
|
|
void on_actionShowProfileFolder_triggered();
|
|
|
|
|
2016-01-22 07:33:29 -08:00
|
|
|
void on_actionAlwaysOnTop_triggered();
|
|
|
|
|
2016-06-30 14:52:56 -07:00
|
|
|
void on_toggleSceneTransitions_toggled(bool visible);
|
|
|
|
void on_toggleListboxToolbars_toggled(bool visible);
|
|
|
|
void on_toggleStatusBar_toggled(bool visible);
|
|
|
|
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
void on_transitions_currentIndexChanged(int index);
|
2016-02-27 02:50:04 -08:00
|
|
|
void on_transitionAdd_clicked();
|
|
|
|
void on_transitionRemove_clicked();
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
void on_transitionProps_clicked();
|
|
|
|
|
|
|
|
void on_modeSwitch_clicked();
|
|
|
|
|
2017-05-06 12:13:56 -07:00
|
|
|
void on_autoConfigure_triggered();
|
2017-05-10 19:37:45 -07:00
|
|
|
void on_stats_triggered();
|
2017-05-06 12:13:56 -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
|
|
|
void logUploadFinished(const QString &text, const QString &error);
|
2014-05-18 17:44:10 -07:00
|
|
|
|
2017-02-20 04:46:29 -08:00
|
|
|
void updateCheckFinished();
|
2014-07-13 23:56:28 -07:00
|
|
|
|
2014-06-30 00:06:01 -07:00
|
|
|
void AddSourceFromAction();
|
|
|
|
|
2015-06-25 03:53:48 -07:00
|
|
|
void MoveSceneToTop();
|
|
|
|
void MoveSceneToBottom();
|
|
|
|
|
2014-06-30 01:13:32 -07:00
|
|
|
void EditSceneName();
|
|
|
|
void EditSceneItemName();
|
|
|
|
|
2014-06-30 00:06:01 -07:00
|
|
|
void SceneNameEdited(QWidget *editor,
|
|
|
|
QAbstractItemDelegate::EndEditHint endHint);
|
|
|
|
void SceneItemNameEdited(QWidget *editor,
|
|
|
|
QAbstractItemDelegate::EndEditHint endHint);
|
|
|
|
|
2015-03-18 15:09:44 -07:00
|
|
|
void OpenSceneFilters();
|
2015-02-25 21:23:57 -08:00
|
|
|
void OpenFilters();
|
|
|
|
|
UI: Implement transitions and preview/program mode
Implements transitions, and introduces "Studio Mode" which allows live
editing of the same or different scenes while preserving what's
currently being displayed.
Studio Mode offers a number of new features:
- The ability to edit different scenes or the same scene without
modifying what's currently being displayed (of course)
- The ability to set up "quick transitions" with a desired transition
and duration that can be assigned hotkeys
- The option to create full copies of all sources in the program scene
to allow editing of source properties of the same scene live without
modifying the output, or (by default) just use references. (Note
however that certain sources cannot be duplicated, such as capture
sources, media sources, and device sources)
- Swap Mode (enabled by default) which swaps the program scene with
the preview scene when a transition completes
Currently, only non-configurable transitions (transitions without
properties) are listed, and the only transitions available as of this
writing are fade and cut. In future versions more transitions will be
added, such as swipe, stingers, and many other various sort of
transitions, and the UI will support being able to add/configure/remove
those sort of configurable transitions.
2016-01-23 11:19:29 -08:00
|
|
|
void EnablePreviewDisplay(bool enable);
|
2015-04-02 21:35:46 -07:00
|
|
|
void TogglePreview();
|
|
|
|
|
2015-04-02 23:09:13 -07:00
|
|
|
void NudgeUp();
|
|
|
|
void NudgeDown();
|
|
|
|
void NudgeLeft();
|
|
|
|
void NudgeRight();
|
|
|
|
|
2015-04-04 01:40:15 -07:00
|
|
|
void OpenPreviewProjector();
|
|
|
|
void OpenSourceProjector();
|
|
|
|
void OpenSceneProjector();
|
|
|
|
|
2017-03-01 20:08:49 -08:00
|
|
|
void OpenPreviewWindow();
|
|
|
|
void OpenSourceWindow();
|
|
|
|
void OpenSceneWindow();
|
|
|
|
|
2016-09-05 20:42:17 -07:00
|
|
|
public slots:
|
|
|
|
void on_actionResetTransform_triggered();
|
|
|
|
|
2013-11-07 15:45:03 -08:00
|
|
|
public:
|
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
|
|
|
explicit OBSBasic(QWidget *parent = 0);
|
2014-02-02 13:26:23 -08:00
|
|
|
virtual ~OBSBasic();
|
2013-11-22 19:43:48 -08:00
|
|
|
|
2014-01-25 08:08:56 -08:00
|
|
|
virtual void OBSInit() override;
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
virtual config_t *Config() const override;
|
2014-03-06 20:08:12 -08:00
|
|
|
|
2015-06-23 19:38:01 -07:00
|
|
|
virtual int GetProfilePath(char *path, size_t size, const char *file)
|
2015-07-10 03:03:53 -07:00
|
|
|
const override;
|
2015-06-23 19:38:01 -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
|
|
|
private:
|
|
|
|
std::unique_ptr<Ui::OBSBasic> ui;
|
2013-11-07 15:45:03 -08:00
|
|
|
};
|