Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ target_sources(
src/ptz-controls.cpp
src/ptz-device.cpp
src/ptz-list-model.cpp
src/ptz-preset-model.cpp
src/settings.cpp
src/ptz-visca.cpp
src/ptz-visca-udp.cpp
Expand All @@ -110,7 +109,6 @@ target_sources(
src/ptz-controls.hpp
src/ptz-device.hpp
src/ptz-list-model.hpp
src/ptz-preset-model.hpp
src/settings.hpp
src/ptz-visca.hpp
src/ptz-visca-udp.hpp
Expand Down
92 changes: 41 additions & 51 deletions src/ptz-controls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,19 @@ PTZControls::PTZControls(QWidget *parent) : QFrame(parent), ui(new Ui::PTZContro

ui->cameraList->setModel(&ptzDeviceList);
ui->cameraList->setItemDelegate(new PTZDeviceListDelegate(ui->cameraList));
connect(&ptzDeviceList, &PTZListModel::dataChanged, this, &PTZControls::updateMoveControls);
connect(&ptzDeviceList, &PTZListModel::dataChanged, this, &PTZControls::settingsChanged);

copyActionsDynamicProperties();

QItemSelectionModel *selectionModel = ui->cameraList->selectionModel();
connect(selectionModel, &QItemSelectionModel::currentChanged, this, &PTZControls::currentChanged);
connect(&accel_timer, &QTimer::timeout, this, &PTZControls::accelTimerHandler);

ui->presetListView->setModel(&ptzDeviceList);
ui->presetListView->setRootIndex(ptzDeviceList.index(0, 0));
selectionModel = ui->presetListView->selectionModel();
connect(selectionModel, &QItemSelectionModel::currentChanged, this, &PTZControls::presetUpdateActions);

connect(ui->panTiltTouch, &TouchControl::positionChanged, [this](double p, double t) { setPanTilt(p, t); });

/* Right-click on the dock's Home button → "Save current position as
Expand Down Expand Up @@ -921,14 +926,17 @@ void PTZControls::updateMoveControls()
ui->presetListView->setEnabled(!is_locked);

RefreshToolBarStyling(ui->ptzToolbar);

calldata cd = {};
calldata_set_string(&cd, "property", "focus_af_enabled");
callCurrentDevice("ptz_get", &cd);
setAutofocusEnabled(calldata_bool(&cd, "focus_af_enabled"));
calldata_free(&cd);
}

void PTZControls::currentChanged(QModelIndex current, QModelIndex previous)
{
PTZDevice *ptz = ptzDeviceList.getDevice(previous);
accel_timer.stop();
if (ptz)
disconnect(ptz, nullptr, this, nullptr);
if (pantiltingFlag || zoomingFlag || focusingFlag)
ptzDeviceList.callDevice(previous, "ptz_stop");
pantiltingFlag = false;
Expand All @@ -939,29 +947,16 @@ void PTZControls::currentChanged(QModelIndex current, QModelIndex previous)
zoom_speed = zoom_accel = 0.0;
focus_speed = focus_accel = 0.0;

ptz = ptzDeviceList.getDevice(current);
if (ptz) {
ui->presetListView->setModel(ptz->presetModel());
presetUpdateActions();
auto *selectionModel = ui->presetListView->selectionModel();
if (selectionModel)
connect(selectionModel, &QItemSelectionModel::currentChanged, this,
&PTZControls::presetUpdateActions);
connect(ptz, &PTZDevice::settingsChanged, this, &PTZControls::settingsChanged);
settingsChanged();
}

ui->presetListView->setRootIndex(current);
updateMoveControls();
}

void PTZControls::settingsChanged()
void PTZControls::settingsChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
auto index = ui->cameraList->currentIndex();
calldata cd = {};
calldata_set_string(&cd, "property", "focus_af_enabled");
ptzDeviceList.callDevice(index, "ptz_get", &cd);
setAutofocusEnabled(calldata_bool(&cd, "focus_af_enabled"));
calldata_free(&cd);
QItemSelectionRange range(topLeft, bottomRight);
if (range.contains(index))
updateMoveControls();
}

void PTZControls::presetSet(long long preset_id)
Expand All @@ -988,13 +983,14 @@ int PTZControls::presetIndexToId(QModelIndex index)

void PTZControls::presetUpdateActions()
{
auto index = ui->presetListView->currentIndex();
auto model = ui->presetListView->model();
int count = model ? model->rowCount() : 0;
ui->actionPresetAdd->setEnabled(model != nullptr);
ui->actionPresetRemove->setEnabled(index.isValid());
ui->actionPresetMoveUp->setEnabled(index.isValid() && count > 1 && index.row() > 0);
ui->actionPresetMoveDown->setEnabled(index.isValid() && count > 1 && index.row() < count - 1);
auto presetIndex = ui->presetListView->currentIndex();
auto deviceIndex = ui->cameraList->currentIndex();
int count = ptzDeviceList.rowCount(deviceIndex);
bool isValid = presetIndex.isValid() && deviceIndex.isValid();
ui->actionPresetAdd->setEnabled(deviceIndex.isValid());
ui->actionPresetRemove->setEnabled(isValid);
ui->actionPresetMoveUp->setEnabled(isValid && count > 1 && presetIndex.row() > 0);
ui->actionPresetMoveDown->setEnabled(isValid && count > 1 && presetIndex.row() < count - 1);
RefreshToolBarStyling(ui->ptzToolbar);
}

Expand Down Expand Up @@ -1096,12 +1092,10 @@ void PTZControls::on_actionProperties_triggered()

void PTZControls::on_actionPresetAdd_triggered()
{
auto model = ui->presetListView->model();
if (!model)
return;
auto row = model->rowCount();
model->insertRows(row, 1);
QModelIndex index = model->index(row, 0);
auto parent = ui->cameraList->currentIndex();
auto row = ptzDeviceList.rowCount(parent);
ptzDeviceList.insertRows(row, 1, parent);
QModelIndex index = ptzDeviceList.index(row, 0, parent);
if (index.isValid()) {
ui->presetListView->setCurrentIndex(index);
ui->presetListView->edit(index);
Expand All @@ -1111,60 +1105,56 @@ void PTZControls::on_actionPresetAdd_triggered()

void PTZControls::on_actionPresetRemove_triggered()
{
auto model = ui->presetListView->model();
auto index = ui->presetListView->currentIndex();
if (!model || !index.isValid())
if (!index.isValid())
return;
model->removeRows(index.row(), 1);
ptzDeviceList.removeRows(index.row(), 1, ui->cameraList->currentIndex());
presetUpdateActions();
}

void PTZControls::on_actionPresetMoveUp_triggered()
{
auto model = ui->presetListView->model();
auto index = ui->presetListView->currentIndex();
if (!model || !index.isValid())
auto parent = ui->cameraList->currentIndex();
if (!index.isValid())
return;
model->moveRow(QModelIndex(), index.row(), QModelIndex(), index.row() - 1);
ptzDeviceList.moveRow(parent, index.row(), parent, index.row() - 1);
presetUpdateActions();
}

void PTZControls::on_actionPresetMoveDown_triggered()
{
auto model = ui->presetListView->model();
auto index = ui->presetListView->currentIndex();
if (!model || !index.isValid())
auto parent = ui->cameraList->currentIndex();
if (!index.isValid())
return;
model->moveRow(QModelIndex(), index.row(), QModelIndex(), index.row() + 2);
ptzDeviceList.moveRow(parent, index.row(), parent, index.row() + 2);
presetUpdateActions();
}

void PTZControls::on_actionPresetRename_triggered()
{
auto model = ui->presetListView->model();
auto index = ui->presetListView->currentIndex();
if (!model || !index.isValid())
if (!index.isValid())
return;
ui->presetListView->edit(index);
}

void PTZControls::on_actionPresetSave_triggered()
{
auto model = ui->presetListView->model();
auto index = ui->presetListView->currentIndex();
if (!model || !index.isValid())
if (!index.isValid())
return;
presetSet(presetIndexToId(index));
}

void PTZControls::on_actionPresetClear_triggered()
{
auto model = ui->presetListView->model();
auto index = ui->presetListView->currentIndex();
if (!model || !index.isValid())
if (!index.isValid())
return;
presetReset(presetIndexToId(index));
ui->presetListView->model()->setData(index, "");
ptzDeviceList.setData(index, "");
}

PTZDeviceListDelegate::PTZDeviceListDelegate(QObject *parent) : QStyledItemDelegate(parent)
Expand Down
2 changes: 1 addition & 1 deletion src/ptz-controls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ private slots:
void on_focusButton_onetouch_clicked();

void currentChanged(QModelIndex current, QModelIndex previous);
void settingsChanged();
void settingsChanged(const QModelIndex &topleft, const QModelIndex &bottomRight);

void presetUpdateActions();
void on_presetListView_activated(QModelIndex index);
Expand Down
110 changes: 105 additions & 5 deletions src/ptz-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <obs.hpp>
#include "ptz-device.hpp"
#include "ptz-list-model.hpp"
#include "ptz-preset-model.hpp"
#include "ptz.h"
#include "protocol-helpers.hpp"

Expand Down Expand Up @@ -258,9 +257,19 @@ void PTZDevice::update(OBSData config)
getDefaults(config);

/* Update the list of preset names */
m_presetsModel.setMaxPresets((size_t)obs_data_get_int(config, "preset_max"));
m_maxPresets = (size_t)obs_data_get_int(config, "preset_max");
OBSDataArrayAutoRelease preset_array = obs_data_get_array(config, "presets");
m_presetsModel.loadPresets(preset_array.Get());
m_presets.clear();
m_presetsDisplayOrder.clear();
for (size_t i = 0; i < obs_data_array_count(preset_array); i++) {
OBSDataAutoRelease item = obs_data_array_item(preset_array, i);
auto id = obs_data_get_int(item, "id");
if (m_presetsDisplayOrder.contains(id))
continue;
QVariantMap preset = OBSDataToVariantMap(item.Get());
m_presets[id] = preset;
sanitizePreset(id);
}

setObjectName(obs_data_get_string(config, "name"));
pantilt_speed_max = obs_data_get_double(config, "pantilt_speed_max");
Expand All @@ -284,9 +293,14 @@ void PTZDevice::save(OBSData config) const
obs_data_set_bool(config, "tilt_invert", tilt_invert);
obs_data_set_bool(config, "zoom_invert", zoom_invert);
obs_data_set_bool(config, "focus_invert", focus_invert);
obs_data_set_int(config, "preset_max", m_presetsModel.maxPresets());
obs_data_set_int(config, "preset_max", m_maxPresets);

OBSDataArrayAutoRelease preset_array = m_presetsModel.savePresets();
OBSDataArrayAutoRelease preset_array = obs_data_array_create();
for (auto id : m_presetsDisplayOrder) {
OBSDataAutoRelease data = variantMapToOBSData(m_presets[id]);
obs_data_set_int(data, "id", id);
obs_data_array_push_back(preset_array, data);
}
obs_data_set_array(config, "presets", preset_array);
}

Expand Down Expand Up @@ -416,6 +430,92 @@ void ptz_unload_devices(void)
ptz_ph = nullptr;
}

void PTZDevice::sanitizePreset(size_t id)
{
if (!m_presets.contains(id))
return;
if (!m_presetsDisplayOrder.contains(id))
m_presetsDisplayOrder.append(id);
QVariantMap &preset = m_presets[id];
QString name = preset["name"].toString();
if (name == "" || name == QString(obs_module_text("PTZ.PresetNum")).arg(id))
preset.remove("name");
}

void PTZDevice::setPresetName(size_t id, QString name)
{
if (!m_presets.contains(id))
return;
QVariantMap &preset = m_presets[id];
preset["name"] = name;
sanitizePreset(id);
}

/* Insert a new preset and return the ID */
int PTZDevice::newPreset(int row)
{
if ((row < 0) || (row > m_presetsDisplayOrder.size()))
row = m_presetsDisplayOrder.size();
int id = 0;
while (m_presets.contains(id))
id++;
if (id >= (int)m_maxPresets)
return -1;

QVariantMap map;
map["id"] = (uint)id;
m_presets[id] = map;
m_presetsDisplayOrder.insert(row, id);
return id;
}

void PTZDevice::removePresetAtDisplayRow(int row)
{
m_presets.remove(m_presetsDisplayOrder[row]);
m_presetsDisplayOrder.removeAt(row);
}

void PTZDevice::movePreset(int srcRow, int destRow)
{
if (srcRow < destRow)
destRow--;
m_presetsDisplayOrder.move(srcRow, destRow);
}

int PTZDevice::presetAtDisplayRow(int row) const
{
if (row < 0 || row >= presetCount())
return -1;
return (int)m_presetsDisplayOrder[row];
}

QVariant PTZDevice::presetProperty(size_t id, QString key) const
{
/* Safe to dereference unconditionally here. Both levels will return
* default empty values without segfaulting */
return m_presets[id][key];
}

bool PTZDevice::updatePreset(size_t id, const QVariantMap &map)
{
if (!m_presets.contains(id))
return false;
m_presets[id].insert(map);
return true;
}

int PTZDevice::findPreset(QString key, QVariant value) const
{
/* Search for the matching key/value pair in all presets.
* This is an O(N) operation */
auto end = m_presets.cend();
for (auto i = m_presets.cbegin(); i != end; i++) {
if (i.value()[key] == value)
return (int)i.key();
}
return -1;
}

void PTZDevice::incrementStatistic(const char *name)
{
obs_data_set_int(statistics, name, obs_data_get_int(statistics, name) + 1);
Expand Down
Loading
Loading