Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Obs Studio
提交
ddfe6483
O
Obs Studio
项目概览
小白菜888
/
Obs Studio
通知
4
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
Obs Studio
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ddfe6483
编写于
8月 18, 2015
作者:
P
Palana
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
UI: Add OBS_PROPERTY_FRAME_RATE implementation
上级
1b078f57
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
802 addition
and
0 deletion
+802
-0
obs/CMakeLists.txt
obs/CMakeLists.txt
+1
-0
obs/data/locale/en-US.ini
obs/data/locale/en-US.ini
+5
-0
obs/properties-view.cpp
obs/properties-view.cpp
+736
-0
obs/properties-view.hpp
obs/properties-view.hpp
+2
-0
obs/properties-view.moc.hpp
obs/properties-view.moc.hpp
+58
-0
未找到文件。
obs/CMakeLists.txt
浏览文件 @
ddfe6483
...
@@ -155,6 +155,7 @@ set(obs_HEADERS
...
@@ -155,6 +155,7 @@ set(obs_HEADERS
window-projector.hpp
window-projector.hpp
window-remux.hpp
window-remux.hpp
properties-view.hpp
properties-view.hpp
properties-view.moc.hpp
display-helpers.hpp
display-helpers.hpp
double-slider.hpp
double-slider.hpp
focus-list.hpp
focus-list.hpp
...
...
obs/data/locale/en-US.ini
浏览文件 @
ddfe6483
...
@@ -173,6 +173,11 @@ Basic.PropertiesWindow.AddEditableListFiles="Add files to '%1'"
...
@@ -173,6 +173,11 @@ Basic.PropertiesWindow.AddEditableListFiles="Add files to '%1'"
Basic.PropertiesWindow.AddEditableListEntry
=
"Add entry to '%1'"
Basic.PropertiesWindow.AddEditableListEntry
=
"Add entry to '%1'"
Basic.PropertiesWindow.EditEditableListEntry
=
"Edit entry from '%1'"
Basic.PropertiesWindow.EditEditableListEntry
=
"Edit entry from '%1'"
# properties view
Basic.PropertiesView.FPS.Simple
=
"Simple FPS Values"
Basic.PropertiesView.FPS.Rational
=
"Rational FPS Values"
Basic.PropertiesView.FPS.ValidFPSRanges
=
"Valid FPS Ranges:"
# interaction window
# interaction window
Basic.InteractionWindow
=
"Interacting with '%1'"
Basic.InteractionWindow
=
"Interacting with '%1'"
...
...
obs/properties-view.cpp
浏览文件 @
ddfe6483
...
@@ -17,10 +17,15 @@
...
@@ -17,10 +17,15 @@
#include <QPlainTextEdit>
#include <QPlainTextEdit>
#include <QDialogButtonBox>
#include <QDialogButtonBox>
#include <QMenu>
#include <QMenu>
#include <QStackedWidget>
#include "double-slider.hpp"
#include "double-slider.hpp"
#include "qt-wrappers.hpp"
#include "qt-wrappers.hpp"
#include "properties-view.hpp"
#include "properties-view.hpp"
#include "properties-view.moc.hpp"
#include "obs-app.hpp"
#include "obs-app.hpp"
#include <cstdlib>
#include <initializer_list>
#include <string>
#include <string>
using
namespace
std
;
using
namespace
std
;
...
@@ -46,6 +51,41 @@ static inline long long color_to_int(QColor color)
...
@@ -46,6 +51,41 @@ static inline long long color_to_int(QColor color)
shift
(
color
.
alpha
(),
24
);
shift
(
color
.
alpha
(),
24
);
}
}
namespace
{
struct
frame_rate_tag
{
enum
tag_type
{
SIMPLE
,
RATIONAL
,
USER
,
}
type
=
SIMPLE
;
const
char
*
val
=
nullptr
;
frame_rate_tag
()
=
default
;
explicit
frame_rate_tag
(
tag_type
type
)
:
type
(
type
)
{}
explicit
frame_rate_tag
(
const
char
*
val
)
:
type
(
USER
),
val
(
val
)
{}
static
frame_rate_tag
simple
()
{
return
frame_rate_tag
{
SIMPLE
};
}
static
frame_rate_tag
rational
()
{
return
frame_rate_tag
{
RATIONAL
};
}
};
struct
common_frame_rate
{
const
char
*
fps_name
;
media_frames_per_second
fps
;
};
}
Q_DECLARE_METATYPE
(
frame_rate_tag
);
Q_DECLARE_METATYPE
(
media_frames_per_second
);
void
OBSPropertiesView
::
ReloadProperties
()
void
OBSPropertiesView
::
ReloadProperties
()
{
{
if
(
obj
)
{
if
(
obj
)
{
...
@@ -634,6 +674,589 @@ void OBSPropertiesView::AddFont(obs_property_t *prop, QFormLayout *layout,
...
@@ -634,6 +674,589 @@ void OBSPropertiesView::AddFont(obs_property_t *prop, QFormLayout *layout,
obs_data_release
(
font_obj
);
obs_data_release
(
font_obj
);
}
}
namespace
std
{
template
<
>
struct
default_delete
<
obs_data_t
>
{
void
operator
()(
obs_data_t
*
data
)
{
obs_data_release
(
data
);
}
};
template
<
>
struct
default_delete
<
obs_data_item_t
>
{
void
operator
()(
obs_data_item_t
*
item
)
{
obs_data_item_release
(
&
item
);
}
};
}
template
<
typename
T
>
static
double
make_epsilon
(
T
val
)
{
return
val
*
0.00001
;
}
static
bool
matches_range
(
media_frames_per_second
&
match
,
media_frames_per_second
fps
,
const
frame_rate_range_t
&
pair
)
{
auto
val
=
media_frames_per_second_to_frame_interval
(
fps
);
auto
max_
=
media_frames_per_second_to_frame_interval
(
pair
.
first
);
auto
min_
=
media_frames_per_second_to_frame_interval
(
pair
.
second
);
if
(
min_
<=
val
&&
val
<=
max_
)
{
match
=
fps
;
return
true
;
}
return
false
;
}
static
bool
matches_ranges
(
media_frames_per_second
&
best_match
,
media_frames_per_second
fps
,
const
frame_rate_ranges_t
&
fps_ranges
,
bool
exact
=
false
)
{
auto
convert_fn
=
media_frames_per_second_to_frame_interval
;
auto
val
=
convert_fn
(
fps
);
auto
epsilon
=
make_epsilon
(
val
);
bool
match
=
false
;
auto
best_dist
=
numeric_limits
<
double
>::
max
();
for
(
auto
&
pair
:
fps_ranges
)
{
auto
max_
=
convert_fn
(
pair
.
first
);
auto
min_
=
convert_fn
(
pair
.
second
);
/*blog(LOG_INFO, "%lg ≤ %lg ≤ %lg? %s %s %s",
min_, val, max_,
fabsl(min_ - val) < epsilon ? "true" : "false",
min_ <= val && val <= max_ ? "true" : "false",
fabsl(min_ - val) < epsilon ? "true" :
"false");*/
if
(
matches_range
(
best_match
,
fps
,
pair
))
return
true
;
if
(
exact
)
continue
;
auto
min_dist
=
fabsl
(
min_
-
val
);
auto
max_dist
=
fabsl
(
max_
-
val
);
if
(
min_dist
<
epsilon
&&
min_dist
<
best_dist
)
{
best_match
=
pair
.
first
;
match
=
true
;
continue
;
}
if
(
max_dist
<
epsilon
&&
max_dist
<
best_dist
)
{
best_match
=
pair
.
second
;
match
=
true
;
continue
;
}
}
return
match
;
}
static
media_frames_per_second
make_fps
(
uint32_t
num
,
uint32_t
den
)
{
media_frames_per_second
fps
{};
fps
.
numerator
=
num
;
fps
.
denominator
=
den
;
return
fps
;
}
static
const
common_frame_rate
common_fps
[]
=
{
{
"60"
,
{
60
,
1
}},
{
"59.94"
,
{
60000
,
1001
}},
{
"50"
,
{
50
,
1
}},
{
"48"
,
{
48
,
1
}},
{
"30"
,
{
30
,
1
}},
{
"29.97"
,
{
30000
,
1001
}},
{
"25"
,
{
25
,
1
}},
{
"24"
,
{
24
,
1
}},
{
"23.976"
,
{
24000
,
1001
}},
};
static
void
UpdateSimpleFPSSelection
(
OBSFrameRatePropertyWidget
*
fpsProps
,
const
media_frames_per_second
*
current_fps
)
{
if
(
!
current_fps
||
!
media_frames_per_second_is_valid
(
*
current_fps
))
{
fpsProps
->
simpleFPS
->
setCurrentIndex
(
0
);
return
;
}
auto
combo
=
fpsProps
->
simpleFPS
;
auto
num
=
combo
->
count
();
for
(
int
i
=
0
;
i
<
num
;
i
++
)
{
auto
variant
=
combo
->
itemData
(
i
);
if
(
!
variant
.
canConvert
<
media_frames_per_second
>
())
continue
;
auto
fps
=
variant
.
value
<
media_frames_per_second
>
();
if
(
fps
!=
*
current_fps
)
continue
;
combo
->
setCurrentIndex
(
i
);
return
;
}
combo
->
setCurrentIndex
(
0
);
}
static
void
AddFPSRanges
(
vector
<
common_frame_rate
>
&
items
,
const
frame_rate_ranges_t
&
ranges
)
{
auto
InsertFPS
=
[
&
](
media_frames_per_second
fps
)
{
auto
fps_val
=
media_frames_per_second_to_fps
(
fps
);
auto
end_
=
end
(
items
);
auto
i
=
begin
(
items
);
for
(;
i
!=
end_
;
i
++
)
{
auto
i_fps_val
=
media_frames_per_second_to_fps
(
i
->
fps
);
if
(
fabsl
(
i_fps_val
-
fps_val
)
<
0.01
)
return
;
if
(
i_fps_val
>
fps_val
)
continue
;
break
;
}
items
.
insert
(
i
,
{
nullptr
,
fps
});
};
for
(
auto
&
range
:
ranges
)
{
InsertFPS
(
range
.
first
);
InsertFPS
(
range
.
second
);
}
}
static
QWidget
*
CreateSimpleFPSValues
(
OBSFrameRatePropertyWidget
*
fpsProps
,
bool
&
selected
,
const
media_frames_per_second
*
current_fps
)
{
auto
widget
=
new
QWidget
{};
widget
->
setSizePolicy
(
QSizePolicy
::
Expanding
,
QSizePolicy
::
Expanding
);
auto
layout
=
new
QVBoxLayout
{};
layout
->
setContentsMargins
(
0
,
0
,
0
,
0
);
auto
items
=
vector
<
common_frame_rate
>
{};
items
.
reserve
(
sizeof
(
common_fps
)
/
sizeof
(
common_frame_rate
));
auto
combo
=
fpsProps
->
simpleFPS
=
new
QComboBox
{};
combo
->
addItem
(
""
,
QVariant
::
fromValue
(
make_fps
(
0
,
0
)));
for
(
const
auto
&
fps
:
common_fps
)
{
media_frames_per_second
best_match
{};
if
(
!
matches_ranges
(
best_match
,
fps
.
fps
,
fpsProps
->
fps_ranges
))
continue
;
items
.
push_back
({
fps
.
fps_name
,
best_match
});
}
AddFPSRanges
(
items
,
fpsProps
->
fps_ranges
);
for
(
const
auto
&
item
:
items
)
{
auto
var
=
QVariant
::
fromValue
(
item
.
fps
);
auto
name
=
item
.
fps_name
?
QString
(
item
.
fps_name
)
:
QString
(
"%1"
)
.
arg
(
media_frames_per_second_to_fps
(
item
.
fps
));
combo
->
addItem
(
name
,
var
);
bool
select
=
current_fps
&&
*
current_fps
==
item
.
fps
;
if
(
select
)
{
combo
->
setCurrentIndex
(
combo
->
count
()
-
1
);
selected
=
true
;
}
}
layout
->
addWidget
(
combo
,
0
,
Qt
::
AlignTop
);
widget
->
setLayout
(
layout
);
return
widget
;
}
static
void
UpdateRationalFPSWidgets
(
OBSFrameRatePropertyWidget
*
fpsProps
,
const
media_frames_per_second
*
current_fps
)
{
if
(
!
current_fps
||
!
media_frames_per_second_is_valid
(
*
current_fps
))
{
fpsProps
->
numEdit
->
setValue
(
0
);
fpsProps
->
denEdit
->
setValue
(
0
);
return
;
}
auto
combo
=
fpsProps
->
fpsRange
;
auto
num
=
combo
->
count
();
for
(
int
i
=
0
;
i
<
num
;
i
++
)
{
auto
variant
=
combo
->
itemData
(
i
);
if
(
!
variant
.
canConvert
<
size_t
>
())
continue
;
auto
idx
=
variant
.
value
<
size_t
>
();
if
(
fpsProps
->
fps_ranges
.
size
()
<
idx
)
continue
;
media_frames_per_second
match
{};
if
(
!
matches_range
(
match
,
*
current_fps
,
fpsProps
->
fps_ranges
[
idx
]))
continue
;
combo
->
setCurrentIndex
(
i
);
break
;
}
fpsProps
->
numEdit
->
setValue
(
current_fps
->
numerator
);
fpsProps
->
denEdit
->
setValue
(
current_fps
->
denominator
);
}
static
QWidget
*
CreateRationalFPS
(
OBSFrameRatePropertyWidget
*
fpsProps
,
bool
&
selected
,
const
media_frames_per_second
*
current_fps
)
{
auto
widget
=
new
QWidget
{};
widget
->
setSizePolicy
(
QSizePolicy
::
Expanding
,
QSizePolicy
::
Expanding
);
auto
layout
=
new
QFormLayout
{};
layout
->
setContentsMargins
(
0
,
0
,
0
,
0
);
layout
->
setSpacing
(
4
);
auto
str
=
QTStr
(
"Basic.PropertiesView.FPS.ValidFPSRanges"
);
auto
rlabel
=
new
QLabel
{
str
};
auto
combo
=
fpsProps
->
fpsRange
=
new
QComboBox
{};
auto
convert_fps
=
media_frames_per_second_to_fps
;
//auto convert_fi = media_frames_per_second_to_frame_interval;
for
(
size_t
i
=
0
;
i
<
fpsProps
->
fps_ranges
.
size
();
i
++
)
{
auto
&
pair
=
fpsProps
->
fps_ranges
[
i
];
combo
->
addItem
(
QString
{
"%1 - %2"
}
.
arg
(
convert_fps
(
pair
.
first
))
.
arg
(
convert_fps
(
pair
.
second
)),
QVariant
::
fromValue
(
i
));
media_frames_per_second
match
;
if
(
!
current_fps
||
!
matches_range
(
match
,
*
current_fps
,
pair
))
continue
;
combo
->
setCurrentIndex
(
combo
->
count
()
-
1
);
selected
=
true
;
}
layout
->
addRow
(
rlabel
,
combo
);
auto
num_edit
=
fpsProps
->
numEdit
=
new
QSpinBox
{};
auto
den_edit
=
fpsProps
->
denEdit
=
new
QSpinBox
{};
num_edit
->
setRange
(
0
,
INT_MAX
);
den_edit
->
setRange
(
0
,
INT_MAX
);
if
(
current_fps
)
{
num_edit
->
setValue
(
current_fps
->
numerator
);
den_edit
->
setValue
(
current_fps
->
denominator
);
}
layout
->
addRow
(
QTStr
(
"Basic.Settings.Video.Numerator"
),
num_edit
);
layout
->
addRow
(
QTStr
(
"Basic.Settings.Video.Denominator"
),
den_edit
);
widget
->
setLayout
(
layout
);
return
widget
;
}
static
OBSFrameRatePropertyWidget
*
CreateFrameRateWidget
(
obs_property_t
*
prop
,
bool
&
warning
,
const
char
*
option
,
media_frames_per_second
*
current_fps
,
frame_rate_ranges_t
&
fps_ranges
)
{
auto
widget
=
new
OBSFrameRatePropertyWidget
{};
auto
hlayout
=
new
QHBoxLayout
{};
hlayout
->
setContentsMargins
(
0
,
0
,
0
,
0
);
swap
(
widget
->
fps_ranges
,
fps_ranges
);
auto
combo
=
widget
->
modeSelect
=
new
QComboBox
{};
combo
->
addItem
(
QTStr
(
"Basic.PropertiesView.FPS.Simple"
),
QVariant
::
fromValue
(
frame_rate_tag
::
simple
()));
combo
->
addItem
(
QTStr
(
"Basic.PropertiesView.FPS.Rational"
),
QVariant
::
fromValue
(
frame_rate_tag
::
rational
()));
auto
num
=
obs_property_frame_rate_options_count
(
prop
);
if
(
num
)
combo
->
insertSeparator
(
combo
->
count
());
bool
option_found
=
false
;
for
(
size_t
i
=
0
;
i
<
num
;
i
++
)
{
auto
name
=
obs_property_frame_rate_option_name
(
prop
,
i
);
auto
desc
=
obs_property_frame_rate_option_description
(
prop
,
i
);
combo
->
addItem
(
desc
,
QVariant
::
fromValue
(
frame_rate_tag
{
name
}));
if
(
!
name
||
!
option
||
string
(
name
)
!=
option
)
continue
;
option_found
=
true
;
combo
->
setCurrentIndex
(
combo
->
count
()
-
1
);
}
hlayout
->
addWidget
(
combo
,
0
,
Qt
::
AlignTop
);
auto
stack
=
widget
->
modeDisplay
=
new
QStackedWidget
{};
bool
match_found
=
option_found
;
auto
AddWidget
=
[
&
](
decltype
(
CreateRationalFPS
)
func
)
{
bool
selected
=
false
;
stack
->
addWidget
(
func
(
widget
,
selected
,
current_fps
));
if
(
match_found
||
!
selected
)
return
;
match_found
=
true
;
stack
->
setCurrentIndex
(
stack
->
count
()
-
1
);
combo
->
setCurrentIndex
(
stack
->
count
()
-
1
);
};
AddWidget
(
CreateSimpleFPSValues
);
AddWidget
(
CreateRationalFPS
);
stack
->
addWidget
(
new
QWidget
{});
if
(
option_found
)
stack
->
setCurrentIndex
(
stack
->
count
()
-
1
);
else
if
(
!
match_found
)
{
int
idx
=
current_fps
?
1
:
0
;
// Rational for "unsupported"
// Simple as default
stack
->
setCurrentIndex
(
idx
);
combo
->
setCurrentIndex
(
idx
);
warning
=
true
;
}
hlayout
->
addWidget
(
stack
,
0
,
Qt
::
AlignTop
);
auto
label_area
=
widget
->
labels
=
new
QWidget
{};
label_area
->
setSizePolicy
(
QSizePolicy
::
Expanding
,
QSizePolicy
::
Expanding
);
auto
vlayout
=
new
QVBoxLayout
{};
vlayout
->
setContentsMargins
(
0
,
0
,
0
,
0
);
auto
fps_label
=
widget
->
currentFPS
=
new
QLabel
{
"FPS: 22"
};
auto
time_label
=
widget
->
timePerFrame
=
new
QLabel
{
"Frame Interval: 0.123 ms"
};
auto
min_label
=
widget
->
minLabel
=
new
QLabel
{
"Min FPS: 1/1"
};
auto
max_label
=
widget
->
maxLabel
=
new
QLabel
{
"Max FPS: 2/1"
};
min_label
->
setHidden
(
true
);
max_label
->
setHidden
(
true
);
auto
flags
=
Qt
::
TextSelectableByMouse
|
Qt
::
TextSelectableByKeyboard
;
min_label
->
setTextInteractionFlags
(
flags
);
max_label
->
setTextInteractionFlags
(
flags
);
vlayout
->
addWidget
(
fps_label
);
vlayout
->
addWidget
(
time_label
);
vlayout
->
addWidget
(
min_label
);
vlayout
->
addWidget
(
max_label
);
label_area
->
setLayout
(
vlayout
);
hlayout
->
addWidget
(
label_area
,
0
,
Qt
::
AlignTop
);
widget
->
setLayout
(
hlayout
);
return
widget
;
}
static
void
UpdateMinMaxLabels
(
OBSFrameRatePropertyWidget
*
w
)
{
auto
Hide
=
[
&
](
bool
hide
)
{
w
->
minLabel
->
setHidden
(
hide
);
w
->
maxLabel
->
setHidden
(
hide
);
};
auto
variant
=
w
->
modeSelect
->
currentData
();
if
(
!
variant
.
canConvert
<
frame_rate_tag
>
()
||
variant
.
value
<
frame_rate_tag
>
().
type
!=
frame_rate_tag
::
RATIONAL
)
{
Hide
(
true
);
return
;
}
variant
=
w
->
fpsRange
->
currentData
();
if
(
!
variant
.
canConvert
<
size_t
>
())
{
Hide
(
true
);
return
;
}
auto
idx
=
variant
.
value
<
size_t
>
();
if
(
idx
>=
w
->
fps_ranges
.
size
())
{
Hide
(
true
);
return
;
}
Hide
(
false
);
auto
min
=
w
->
fps_ranges
[
idx
].
first
;
auto
max
=
w
->
fps_ranges
[
idx
].
second
;
w
->
minLabel
->
setText
(
QString
(
"Min FPS: %1/%2"
)
.
arg
(
min
.
numerator
)
.
arg
(
min
.
denominator
));
w
->
maxLabel
->
setText
(
QString
(
"Max FPS: %1/%2"
)
.
arg
(
max
.
numerator
)
.
arg
(
max
.
denominator
));
}
static
void
UpdateFPSLabels
(
OBSFrameRatePropertyWidget
*
w
)
{
UpdateMinMaxLabels
(
w
);
unique_ptr
<
obs_data_item_t
>
obj
{
obs_data_item_byname
(
w
->
settings
,
w
->
name
)};
media_frames_per_second
fps
{};
media_frames_per_second
*
valid_fps
=
nullptr
;
if
(
obs_data_item_get_autoselect_frames_per_second
(
obj
.
get
(),
&
fps
,
nullptr
)
||
obs_data_item_get_frames_per_second
(
obj
.
get
(),
&
fps
,
nullptr
))
valid_fps
=
&
fps
;
const
char
*
option
=
nullptr
;
obs_data_item_get_frames_per_second
(
obj
.
get
(),
nullptr
,
&
option
);
if
(
!
valid_fps
)
{
w
->
currentFPS
->
setHidden
(
true
);
w
->
timePerFrame
->
setHidden
(
true
);
if
(
!
option
)
w
->
warningLabel
->
setStyleSheet
(
"QLabel { color: red; }"
);
return
;
}
w
->
currentFPS
->
setHidden
(
false
);
w
->
timePerFrame
->
setHidden
(
false
);
media_frames_per_second
match
{};
if
(
!
option
&&
!
matches_ranges
(
match
,
*
valid_fps
,
w
->
fps_ranges
,
true
))
w
->
warningLabel
->
setStyleSheet
(
"QLabel { color: red; }"
);
else
w
->
warningLabel
->
setStyleSheet
(
""
);
auto
convert_to_fps
=
media_frames_per_second_to_fps
;
auto
convert_to_frame_interval
=
media_frames_per_second_to_frame_interval
;
w
->
currentFPS
->
setText
(
QString
(
"FPS: %1"
)
.
arg
(
convert_to_fps
(
*
valid_fps
)));
w
->
timePerFrame
->
setText
(
QString
(
"Frame Interval: %1 ms"
)
.
arg
(
convert_to_frame_interval
(
*
valid_fps
)
*
1000
));
}
void
OBSPropertiesView
::
AddFrameRate
(
obs_property_t
*
prop
,
bool
&
warning
,
QFormLayout
*
layout
,
QLabel
*&
label
)
{
const
char
*
name
=
obs_property_name
(
prop
);
bool
enabled
=
obs_property_enabled
(
prop
);
unique_ptr
<
obs_data_item_t
>
obj
{
obs_data_item_byname
(
settings
,
name
)};
const
char
*
option
=
nullptr
;
obs_data_item_get_frames_per_second
(
obj
.
get
(),
nullptr
,
&
option
);
media_frames_per_second
fps
{};
media_frames_per_second
*
valid_fps
=
nullptr
;
if
(
obs_data_item_get_frames_per_second
(
obj
.
get
(),
&
fps
,
nullptr
))
valid_fps
=
&
fps
;
frame_rate_ranges_t
fps_ranges
;
size_t
num
=
obs_property_frame_rate_fps_ranges_count
(
prop
);
fps_ranges
.
reserve
(
num
);
for
(
size_t
i
=
0
;
i
<
num
;
i
++
)
fps_ranges
.
emplace_back
(
obs_property_frame_rate_fps_range_min
(
prop
,
i
),
obs_property_frame_rate_fps_range_max
(
prop
,
i
));
auto
widget
=
CreateFrameRateWidget
(
prop
,
warning
,
option
,
valid_fps
,
fps_ranges
);
auto
info
=
new
WidgetInfo
(
this
,
prop
,
widget
);
widget
->
name
=
name
;
widget
->
settings
=
settings
;
widget
->
modeSelect
->
setEnabled
(
enabled
);
widget
->
simpleFPS
->
setEnabled
(
enabled
);
widget
->
fpsRange
->
setEnabled
(
enabled
);
widget
->
numEdit
->
setEnabled
(
enabled
);
widget
->
denEdit
->
setEnabled
(
enabled
);
label
=
widget
->
warningLabel
=
new
QLabel
{
obs_property_description
(
prop
)};
layout
->
addRow
(
label
,
widget
);
children
.
emplace_back
(
info
);
UpdateFPSLabels
(
widget
);
auto
stack
=
widget
->
modeDisplay
;
auto
combo
=
widget
->
modeSelect
;
auto
comboIndexChanged
=
static_cast
<
void
(
QComboBox
::*
)(
int
)
>
(
&
QComboBox
::
currentIndexChanged
);
connect
(
combo
,
comboIndexChanged
,
stack
,
[
=
](
int
index
)
{
bool
out_of_bounds
=
index
>=
stack
->
count
();
auto
idx
=
out_of_bounds
?
stack
->
count
()
-
1
:
index
;
stack
->
setCurrentIndex
(
idx
);
if
(
widget
->
updating
)
return
;
UpdateFPSLabels
(
widget
);
emit
info
->
ControlChanged
();
});
connect
(
widget
->
simpleFPS
,
comboIndexChanged
,
[
=
](
int
)
{
if
(
widget
->
updating
)
return
;
emit
info
->
ControlChanged
();
});
connect
(
widget
->
fpsRange
,
comboIndexChanged
,
[
=
](
int
)
{
if
(
widget
->
updating
)
return
;
UpdateFPSLabels
(
widget
);
});
auto
sbValueChanged
=
static_cast
<
void
(
QSpinBox
::*
)(
int
)
>
(
&
QSpinBox
::
valueChanged
);
connect
(
widget
->
numEdit
,
sbValueChanged
,
[
=
](
int
)
{
if
(
widget
->
updating
)
return
;
emit
info
->
ControlChanged
();
});
connect
(
widget
->
denEdit
,
sbValueChanged
,
[
=
](
int
)
{
if
(
widget
->
updating
)
return
;
emit
info
->
ControlChanged
();
});
}
void
OBSPropertiesView
::
AddProperty
(
obs_property_t
*
property
,
void
OBSPropertiesView
::
AddProperty
(
obs_property_t
*
property
,
QFormLayout
*
layout
)
QFormLayout
*
layout
)
{
{
...
@@ -680,6 +1303,9 @@ void OBSPropertiesView::AddProperty(obs_property_t *property,
...
@@ -680,6 +1303,9 @@ void OBSPropertiesView::AddProperty(obs_property_t *property,
case
OBS_PROPERTY_EDITABLE_LIST
:
case
OBS_PROPERTY_EDITABLE_LIST
:
AddEditableList
(
property
,
layout
,
label
);
AddEditableList
(
property
,
layout
,
label
);
break
;
break
;
case
OBS_PROPERTY_FRAME_RATE
:
AddFrameRate
(
property
,
warning
,
layout
,
label
);
break
;
}
}
if
(
widget
&&
!
obs_property_enabled
(
property
))
if
(
widget
&&
!
obs_property_enabled
(
property
))
...
@@ -713,6 +1339,112 @@ void OBSPropertiesView::SignalChanged()
...
@@ -713,6 +1339,112 @@ void OBSPropertiesView::SignalChanged()
emit
Changed
();
emit
Changed
();
}
}
static
bool
FrameRateChangedVariant
(
const
QVariant
&
variant
,
media_frames_per_second
&
fps
,
obs_data_item_t
*&
obj
,
const
media_frames_per_second
*
valid_fps
)
{
if
(
!
variant
.
canConvert
<
media_frames_per_second
>
())
return
false
;
fps
=
variant
.
value
<
media_frames_per_second
>
();
if
(
valid_fps
&&
fps
==
*
valid_fps
)
return
false
;
obs_data_item_set_frames_per_second
(
&
obj
,
fps
,
nullptr
);
return
true
;
}
static
bool
FrameRateChangedCommon
(
OBSFrameRatePropertyWidget
*
w
,
obs_data_item_t
*&
obj
,
const
media_frames_per_second
*
valid_fps
)
{
media_frames_per_second
fps
{};
if
(
!
FrameRateChangedVariant
(
w
->
simpleFPS
->
currentData
(),
fps
,
obj
,
valid_fps
))
return
false
;
UpdateRationalFPSWidgets
(
w
,
&
fps
);
return
true
;
}
static
bool
FrameRateChangedRational
(
OBSFrameRatePropertyWidget
*
w
,
obs_data_item_t
*&
obj
,
const
media_frames_per_second
*
valid_fps
)
{
auto
num
=
w
->
numEdit
->
value
();
auto
den
=
w
->
denEdit
->
value
();
auto
fps
=
make_fps
(
num
,
den
);
if
(
valid_fps
&&
media_frames_per_second_is_valid
(
fps
)
&&
fps
==
*
valid_fps
)
return
false
;
obs_data_item_set_frames_per_second
(
&
obj
,
fps
,
nullptr
);
UpdateSimpleFPSSelection
(
w
,
&
fps
);
return
true
;
}
static
bool
FrameRateChanged
(
QWidget
*
widget
,
const
char
*
name
,
OBSData
&
settings
)
{
auto
w
=
qobject_cast
<
OBSFrameRatePropertyWidget
*>
(
widget
);
if
(
!
w
)
return
false
;
auto
variant
=
w
->
modeSelect
->
currentData
();
if
(
!
variant
.
canConvert
<
frame_rate_tag
>
())
return
false
;
auto
StopUpdating
=
[
&
](
void
*
)
{
w
->
updating
=
false
;
};
unique_ptr
<
void
,
decltype
(
StopUpdating
)
>
signalGuard
(
static_cast
<
void
*>
(
w
),
StopUpdating
);
w
->
updating
=
true
;
if
(
!
obs_data_has_user_value
(
settings
,
name
))
obs_data_set_obj
(
settings
,
name
,
nullptr
);
unique_ptr
<
obs_data_item_t
>
obj
{
obs_data_item_byname
(
settings
,
name
)};
auto
obj_ptr
=
obj
.
get
();
auto
CheckObj
=
[
&
]()
{
if
(
!
obj_ptr
)
obj
.
release
();
};
const
char
*
option
=
nullptr
;
obs_data_item_get_frames_per_second
(
obj
.
get
(),
nullptr
,
&
option
);
media_frames_per_second
fps
{};
media_frames_per_second
*
valid_fps
=
nullptr
;
if
(
obs_data_item_get_frames_per_second
(
obj
.
get
(),
&
fps
,
nullptr
))
valid_fps
=
&
fps
;
auto
tag
=
variant
.
value
<
frame_rate_tag
>
();
switch
(
tag
.
type
)
{
case
frame_rate_tag
::
SIMPLE
:
if
(
!
FrameRateChangedCommon
(
w
,
obj_ptr
,
valid_fps
))
return
false
;
break
;
case
frame_rate_tag
::
RATIONAL
:
if
(
!
FrameRateChangedRational
(
w
,
obj_ptr
,
valid_fps
))
return
false
;
break
;
case
frame_rate_tag
::
USER
:
if
(
tag
.
val
&&
option
&&
strcmp
(
tag
.
val
,
option
)
==
0
)
return
false
;
obs_data_item_set_frames_per_second
(
&
obj_ptr
,
{},
tag
.
val
);
break
;
}
UpdateFPSLabels
(
w
);
CheckObj
();
return
true
;
}
void
WidgetInfo
::
BoolChanged
(
const
char
*
setting
)
void
WidgetInfo
::
BoolChanged
(
const
char
*
setting
)
{
{
QCheckBox
*
checkbox
=
static_cast
<
QCheckBox
*>
(
widget
);
QCheckBox
*
checkbox
=
static_cast
<
QCheckBox
*>
(
widget
);
...
@@ -938,6 +1670,10 @@ void WidgetInfo::ControlChanged()
...
@@ -938,6 +1670,10 @@ void WidgetInfo::ControlChanged()
return
;
return
;
break
;
break
;
case
OBS_PROPERTY_EDITABLE_LIST
:
return
;
case
OBS_PROPERTY_EDITABLE_LIST
:
return
;
case
OBS_PROPERTY_FRAME_RATE
:
if
(
!
FrameRateChanged
(
widget
,
setting
,
view
->
settings
))
return
;
break
;
}
}
if
(
view
->
callback
&&
!
view
->
deferUpdate
)
if
(
view
->
callback
&&
!
view
->
deferUpdate
)
...
...
obs/properties-view.hpp
浏览文件 @
ddfe6483
...
@@ -99,6 +99,8 @@ private:
...
@@ -99,6 +99,8 @@ private:
QWidget
*
AddButton
(
obs_property_t
*
prop
);
QWidget
*
AddButton
(
obs_property_t
*
prop
);
void
AddColor
(
obs_property_t
*
prop
,
QFormLayout
*
layout
,
QLabel
*&
label
);
void
AddColor
(
obs_property_t
*
prop
,
QFormLayout
*
layout
,
QLabel
*&
label
);
void
AddFont
(
obs_property_t
*
prop
,
QFormLayout
*
layout
,
QLabel
*&
label
);
void
AddFont
(
obs_property_t
*
prop
,
QFormLayout
*
layout
,
QLabel
*&
label
);
void
AddFrameRate
(
obs_property_t
*
prop
,
bool
&
warning
,
QFormLayout
*
layout
,
QLabel
*&
label
);
void
AddProperty
(
obs_property_t
*
property
,
QFormLayout
*
layout
);
void
AddProperty
(
obs_property_t
*
property
,
QFormLayout
*
layout
);
...
...
obs/properties-view.moc.hpp
0 → 100644
浏览文件 @
ddfe6483
#pragma once
#include <QComboBox>
#include <QLabel>
#include <QSpinBox>
#include <QStackedWidget>
#include <QWidget>
#include <media-io/frame-rate.h>
#include <vector>
static
bool
operator
!=
(
const
media_frames_per_second
&
a
,
const
media_frames_per_second
&
b
)
{
return
a
.
numerator
!=
b
.
numerator
||
a
.
denominator
!=
b
.
denominator
;
}
static
bool
operator
==
(
const
media_frames_per_second
&
a
,
const
media_frames_per_second
&
b
)
{
return
!
(
a
!=
b
);
}
using
frame_rate_range_t
=
std
::
pair
<
media_frames_per_second
,
media_frames_per_second
>
;
using
frame_rate_ranges_t
=
std
::
vector
<
frame_rate_range_t
>
;
class
OBSFrameRatePropertyWidget
:
public
QWidget
{
Q_OBJECT
public:
frame_rate_ranges_t
fps_ranges
;
QComboBox
*
modeSelect
=
nullptr
;
QStackedWidget
*
modeDisplay
=
nullptr
;
QWidget
*
labels
=
nullptr
;
QLabel
*
currentFPS
=
nullptr
;
QLabel
*
timePerFrame
=
nullptr
;
QLabel
*
minLabel
=
nullptr
;
QLabel
*
maxLabel
=
nullptr
;
QComboBox
*
simpleFPS
=
nullptr
;
QComboBox
*
fpsRange
=
nullptr
;
QSpinBox
*
numEdit
=
nullptr
;
QSpinBox
*
denEdit
=
nullptr
;
bool
updating
=
false
;
const
char
*
name
=
nullptr
;
obs_data_t
*
settings
=
nullptr
;
QLabel
*
warningLabel
=
nullptr
;
OBSFrameRatePropertyWidget
()
=
default
;
};
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录