kdenlivesettingsdialog.cpp 68.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/***************************************************************************
 *   Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
 *                                                                         *
 *   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  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
 ***************************************************************************/

20
#include "kdenlivesettingsdialog.h"
Nicolas Carion's avatar
Nicolas Carion committed
21
#include "clipcreationdialog.h"
Nicolas Carion's avatar
linting  
Nicolas Carion committed
22
#include "core.h"
23
#include "dialogs/profilesdialog.h"
Nicolas Carion's avatar
Nicolas Carion committed
24
#include "encodingprofilesdialog.h"
25
#include "kdenlivesettings.h"
Nicolas Carion's avatar
linting  
Nicolas Carion committed
26
#include "profiles/profilemodel.hpp"
27
#include "profiles/profilerepository.hpp"
Nicolas Carion's avatar
Nicolas Carion committed
28 29
#include "profilesdialog.h"
#include "project/dialogs/profilewidget.h"
30

Vincent Pinon's avatar
Vincent Pinon committed
31 32 33
#ifdef USE_V4L
#include "capture/v4lcapture.h"
#endif
34

Nicolas Carion's avatar
Nicolas Carion committed
35
#include "kdenlive_debug.h"
36
#include "klocalizedstring.h"
37
#include <KLineEdit>
Nicolas Carion's avatar
Nicolas Carion committed
38
#include <KMessageBox>
39
#include <KOpenWithDialog>
Nicolas Carion's avatar
Nicolas Carion committed
40 41
#include <KRun>
#include <KService>
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
42
#include <QAction>
43
#include <QDir>
Akhil K Gangadharan's avatar
Akhil K Gangadharan committed
44 45
#include <QGuiApplication>
#include <QScreen>
46 47 48
#include <QSize>
#include <QThread>
#include <QTimer>
Nicolas Carion's avatar
Nicolas Carion committed
49
#include <fcntl.h>
50
#include <stdio.h>
Nicolas Carion's avatar
Nicolas Carion committed
51
#include <stdlib.h>
52
#include <unistd.h>
53

54
#ifdef USE_JOGSHUTTLE
55 56
#include "jogshuttle/jogaction.h"
#include "jogshuttle/jogshuttleconfig.h"
57
#include <QStandardPaths>
Nicolas Carion's avatar
Nicolas Carion committed
58
#include <linux/input.h>
59
#endif
60

Nicolas Carion's avatar
Nicolas Carion committed
61
KdenliveSettingsDialog::KdenliveSettingsDialog(const QMap<QString, QString> &mappable_actions, bool gpuAllowed, QWidget *parent)
62 63 64 65
    : KConfigDialog(parent, QStringLiteral("settings"), KdenliveSettings::self())
    , m_modified(false)
    , m_shuttleModified(false)
    , m_mappable_actions(mappable_actions)
66
{
67
    KdenliveSettings::setV4l_format(0);
68
    QWidget *p1 = new QWidget;
69
    QFontInfo ftInfo(font());
70
    m_configMisc.setupUi(p1);
71
    m_page1 = addPage(p1, i18n("Misc"));
72
    m_page1->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
73

74
    m_configMisc.kcfg_use_exiftool->setEnabled(!QStandardPaths::findExecutable(QStringLiteral("exiftool")).isEmpty());
75

76 77
    QWidget *p8 = new QWidget;
    m_configProject.setupUi(p8);
78
    m_page8 = addPage(p8, i18n("Project Defaults"));
Nicolas Carion's avatar
Nicolas Carion committed
79
    auto *vbox = new QVBoxLayout;
80 81 82
    m_pw = new ProfileWidget(this);
    vbox->addWidget(m_pw);
    m_configProject.profile_box->setLayout(vbox);
83
    m_configProject.profile_box->setTitle(i18n("Select the default profile (preset)"));
84
    // Select profile
85
    m_pw->loadProfile(KdenliveSettings::default_profile().isEmpty() ? pCore->getCurrentProfile()->path() : KdenliveSettings::default_profile());
86
    connect(m_pw, &ProfileWidget::profileChanged, this, &KdenliveSettingsDialog::slotDialogModified);
87
    m_page8->setIcon(QIcon::fromTheme(QStringLiteral("project-defaults")));
88 89
    m_configProject.projecturl->setMode(KFile::Directory);
    m_configProject.projecturl->setUrl(QUrl::fromLocalFile(KdenliveSettings::defaultprojectfolder()));
90 91 92

    QWidget *p9 = new QWidget;
    m_configProxy.setupUi(p9);
93
    KPageWidgetItem *page9 = addPage(p9, i18n("Proxy Clips"));
94 95 96 97 98 99
    page9->setIcon(QIcon::fromTheme(QStringLiteral("zoom-out")));
    connect(m_configProxy.kcfg_generateproxy, &QAbstractButton::toggled, m_configProxy.kcfg_proxyminsize, &QWidget::setEnabled);
    m_configProxy.kcfg_proxyminsize->setEnabled(KdenliveSettings::generateproxy());
    connect(m_configProxy.kcfg_generateimageproxy, &QAbstractButton::toggled, m_configProxy.kcfg_proxyimageminsize, &QWidget::setEnabled);
    m_configProxy.kcfg_proxyimageminsize->setEnabled(KdenliveSettings::generateimageproxy());
    loadExternalProxyProfiles();
100

101
    QWidget *p3 = new QWidget;
102
    m_configTimeline.setupUi(p3);
103
    m_page3 = addPage(p3, i18n("Timeline"));
104
    m_page3->setIcon(QIcon::fromTheme(QStringLiteral("video-display")));
105
    m_configTimeline.kcfg_trackheight->setMinimum(ftInfo.pixelSize() * 1.5);
106 107 108 109

    QWidget *p2 = new QWidget;
    m_configEnv.setupUi(p2);
    m_configEnv.mltpathurl->setMode(KFile::Directory);
110 111 112 113 114
    m_configEnv.mltpathurl->lineEdit()->setObjectName(QStringLiteral("kcfg_mltpath"));
    m_configEnv.rendererpathurl->lineEdit()->setObjectName(QStringLiteral("kcfg_rendererpath"));
    m_configEnv.ffmpegurl->lineEdit()->setObjectName(QStringLiteral("kcfg_ffmpegpath"));
    m_configEnv.ffplayurl->lineEdit()->setObjectName(QStringLiteral("kcfg_ffplaypath"));
    m_configEnv.ffprobeurl->lineEdit()->setObjectName(QStringLiteral("kcfg_ffprobepath"));
115 116
    int maxThreads = QThread::idealThreadCount();
    m_configEnv.kcfg_mltthreads->setMaximum(maxThreads > 2 ? maxThreads : 8);
117
    m_configEnv.tmppathurl->setMode(KFile::Directory);
118
    m_configEnv.tmppathurl->lineEdit()->setObjectName(QStringLiteral("kcfg_currenttmpfolder"));
119
    m_configEnv.capturefolderurl->setMode(KFile::Directory);
120
    m_configEnv.capturefolderurl->lineEdit()->setObjectName(QStringLiteral("kcfg_capturefolder"));
121
    m_configEnv.capturefolderurl->setEnabled(!KdenliveSettings::capturetoprojectfolder());
Laurent Montel's avatar
Laurent Montel committed
122
    connect(m_configEnv.kcfg_capturetoprojectfolder, &QAbstractButton::clicked, this, &KdenliveSettingsDialog::slotEnableCaptureFolder);
123 124 125 126
    // Library folder
    m_configEnv.libraryfolderurl->setMode(KFile::Directory);
    m_configEnv.libraryfolderurl->lineEdit()->setObjectName(QStringLiteral("kcfg_libraryfolder"));
    m_configEnv.libraryfolderurl->setEnabled(!KdenliveSettings::librarytodefaultfolder());
127
    m_configEnv.kcfg_librarytodefaultfolder->setToolTip(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/library"));
Laurent Montel's avatar
Laurent Montel committed
128
    connect(m_configEnv.kcfg_librarytodefaultfolder, &QAbstractButton::clicked, this, &KdenliveSettingsDialog::slotEnableLibraryFolder);
129

130 131 132
    // Mime types
    QStringList mimes = ClipCreationDialog::getExtensions();
    qSort(mimes);
Laurent Montel's avatar
Laurent Montel committed
133
    m_configEnv.supportedmimes->setPlainText(mimes.join(QLatin1Char(' ')));
134

135
    m_page2 = addPage(p2, i18n("Environment"));
136
    m_page2->setIcon(QIcon::fromTheme(QStringLiteral("application-x-executable-script")));
137 138 139

    QWidget *p4 = new QWidget;
    m_configCapture.setupUi(p4);
140 141
    m_configCapture.tabWidget->removeTab(0);
    m_configCapture.tabWidget->removeTab(2);
142
#ifdef USE_V4L
143

144
    // Video 4 Linux device detection
Laurent Montel's avatar
Laurent Montel committed
145
    for (int i = 0; i < 10; ++i) {
Laurent Montel's avatar
Laurent Montel committed
146
        QString path = QStringLiteral("/dev/video") + QString::number(i);
147
        if (QFile::exists(path)) {
148
            QStringList deviceInfo = V4lCaptureHandler::getDeviceName(path);
149 150 151 152
            if (!deviceInfo.isEmpty()) {
                m_configCapture.kcfg_detectedv4ldevices->addItem(deviceInfo.at(0), path);
                m_configCapture.kcfg_detectedv4ldevices->setItemData(m_configCapture.kcfg_detectedv4ldevices->count() - 1, deviceInfo.at(1), Qt::UserRole + 1);
            }
153 154
        }
    }
Nicolas Carion's avatar
Nicolas Carion committed
155 156 157 158
    connect(m_configCapture.kcfg_detectedv4ldevices, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
            &KdenliveSettingsDialog::slotUpdatev4lDevice);
    connect(m_configCapture.kcfg_v4l_format, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
            &KdenliveSettingsDialog::slotUpdatev4lCaptureProfile);
Laurent Montel's avatar
Laurent Montel committed
159
    connect(m_configCapture.config_v4l, &QAbstractButton::clicked, this, &KdenliveSettingsDialog::slotEditVideo4LinuxProfile);
160 161

    slotUpdatev4lDevice();
162
#endif
163

164
    m_page4 = addPage(p4, i18n("Capture"));
165
    m_page4->setIcon(QIcon::fromTheme(QStringLiteral("media-record")));
166
    m_configCapture.tabWidget->setCurrentIndex(KdenliveSettings::defaultcapture());
Alberto Villa's avatar
Alberto Villa committed
167
#ifdef Q_WS_MAC
168 169
    m_configCapture.tabWidget->setEnabled(false);
    m_configCapture.kcfg_defaultcapture->setEnabled(false);
Alberto Villa's avatar
Alberto Villa committed
170
    m_configCapture.label->setText(i18n("Capture is not yet available on Mac OS X."));
171
#endif
172

173 174
    QWidget *p5 = new QWidget;
    m_configShuttle.setupUi(p5);
175
#ifdef USE_JOGSHUTTLE
176
    m_configShuttle.toolBtnReload->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
Laurent Montel's avatar
Laurent Montel committed
177
    connect(m_configShuttle.kcfg_enableshuttle, &QCheckBox::stateChanged, this, &KdenliveSettingsDialog::slotCheckShuttle);
178
    connect(m_configShuttle.shuttledevicelist, SIGNAL(activated(int)), this, SLOT(slotUpdateShuttleDevice(int)));
Laurent Montel's avatar
Laurent Montel committed
179
    connect(m_configShuttle.toolBtnReload, &QAbstractButton::clicked, this, &KdenliveSettingsDialog::slotReloadShuttleDevices);
180

Nicolas Carion's avatar
Nicolas Carion committed
181
    slotCheckShuttle(static_cast<int>(KdenliveSettings::enableshuttle()));
182
    m_configShuttle.shuttledisabled->hide();
183 184

    // Store the button pointers into an array for easier handling them in the other functions.
185
    // TODO: impl enumerator or live with cut and paste :-)))
186 187
    setupJogshuttleBtns(KdenliveSettings::shuttledevice());
#if 0
188 189 190 191 192
    m_shuttle_buttons.push_back(m_configShuttle.shuttle1);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle2);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle3);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle4);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle5);
193 194 195 196 197
    m_shuttle_buttons.push_back(m_configShuttle.shuttle6);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle7);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle8);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle9);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle10);
198 199 200 201 202
    m_shuttle_buttons.push_back(m_configShuttle.shuttle11);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle12);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle13);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle14);
    m_shuttle_buttons.push_back(m_configShuttle.shuttle15);
203
#endif
204

Nicolas Carion's avatar
Nicolas Carion committed
205
#else  /* ! USE_JOGSHUTTLE */
206 207 208
    m_configShuttle.kcfg_enableshuttle->hide();
    m_configShuttle.kcfg_enableshuttle->setDisabled(true);
#endif /* USE_JOGSHUTTLE */
209
    m_page5 = addPage(p5, i18n("JogShuttle"));
210
    m_page5->setIcon(QIcon::fromTheme(QStringLiteral("jog-dial")));
211

212 213
    QWidget *p6 = new QWidget;
    m_configSdl.setupUi(p6);
214
    m_configSdl.reload_blackmagic->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
Laurent Montel's avatar
Laurent Montel committed
215
    connect(m_configSdl.reload_blackmagic, &QAbstractButton::clicked, this, &KdenliveSettingsDialog::slotReloadBlackMagic);
216

Nicolas Carion's avatar
Nicolas Carion committed
217
    // m_configSdl.kcfg_openglmonitors->setHidden(true);
218

219
    m_page6 = addPage(p6, i18n("Playback"));
220
    m_page6->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
221

222 223
    QWidget *p7 = new QWidget;
    m_configTranscode.setupUi(p7);
224
    m_page7 = addPage(p7, i18n("Transcode"));
225
    m_page7->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy")));
226

Laurent Montel's avatar
Laurent Montel committed
227 228 229 230
    connect(m_configTranscode.button_add, &QAbstractButton::clicked, this, &KdenliveSettingsDialog::slotAddTranscode);
    connect(m_configTranscode.button_delete, &QAbstractButton::clicked, this, &KdenliveSettingsDialog::slotDeleteTranscode);
    connect(m_configTranscode.profiles_list, &QListWidget::itemChanged, this, &KdenliveSettingsDialog::slotDialogModified);
    connect(m_configTranscode.profiles_list, &QListWidget::currentRowChanged, this, &KdenliveSettingsDialog::slotSetTranscodeProfile);
231

Laurent Montel's avatar
Laurent Montel committed
232 233 234 235 236
    connect(m_configTranscode.profile_name, &QLineEdit::textChanged, this, &KdenliveSettingsDialog::slotEnableTranscodeUpdate);
    connect(m_configTranscode.profile_description, &QLineEdit::textChanged, this, &KdenliveSettingsDialog::slotEnableTranscodeUpdate);
    connect(m_configTranscode.profile_extension, &QLineEdit::textChanged, this, &KdenliveSettingsDialog::slotEnableTranscodeUpdate);
    connect(m_configTranscode.profile_parameters, &QPlainTextEdit::textChanged, this, &KdenliveSettingsDialog::slotEnableTranscodeUpdate);
    connect(m_configTranscode.profile_audioonly, &QCheckBox::stateChanged, this, &KdenliveSettingsDialog::slotEnableTranscodeUpdate);
237

Laurent Montel's avatar
Laurent Montel committed
238
    connect(m_configTranscode.button_update, &QAbstractButton::pressed, this, &KdenliveSettingsDialog::slotUpdateTranscodingProfile);
239

240
    m_configTranscode.profile_parameters->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 5);
Alberto Villa's avatar
Alberto Villa committed
241

Laurent Montel's avatar
Laurent Montel committed
242 243
    connect(m_configEnv.kp_image, &QAbstractButton::clicked, this, &KdenliveSettingsDialog::slotEditImageApplication);
    connect(m_configEnv.kp_audio, &QAbstractButton::clicked, this, &KdenliveSettingsDialog::slotEditAudioApplication);
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
244

245
    loadEncodingProfiles();
246

Nicolas Carion's avatar
Nicolas Carion committed
247 248 249 250
    connect(m_configSdl.kcfg_audio_driver, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
            &KdenliveSettingsDialog::slotCheckAlsaDriver);
    connect(m_configSdl.kcfg_audio_backend, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
            &KdenliveSettingsDialog::slotCheckAudioBackend);
251
    initDevices();
Nicolas Carion's avatar
Nicolas Carion committed
252 253
    connect(m_configCapture.kcfg_grab_capture_type, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
            &KdenliveSettingsDialog::slotUpdateGrabRegionStatus);
254

255
    slotUpdateGrabRegionStatus();
256
    loadTranscodeProfiles();
257

258
    // decklink profile
259
    QAction *act = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure profiles"), this);
260
    act->setData(4);
Laurent Montel's avatar
Laurent Montel committed
261
    connect(act, &QAction::triggered, this, &KdenliveSettingsDialog::slotManageEncodingProfile);
262
    m_configCapture.decklink_manageprofile->setDefaultAction(act);
263
    m_configCapture.decklink_showprofileinfo->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
264 265 266
    m_configCapture.decklink_parameters->setVisible(false);
    m_configCapture.decklink_parameters->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 4);
    m_configCapture.decklink_parameters->setPlainText(KdenliveSettings::decklink_parameters());
Nicolas Carion's avatar
Nicolas Carion committed
267 268
    connect(m_configCapture.kcfg_decklink_profile, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
            &KdenliveSettingsDialog::slotUpdateDecklinkProfile);
Laurent Montel's avatar
Laurent Montel committed
269
    connect(m_configCapture.decklink_showprofileinfo, &QAbstractButton::clicked, m_configCapture.decklink_parameters, &QWidget::setVisible);
270

271
    // ffmpeg profile
272
    m_configCapture.v4l_showprofileinfo->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
273 274 275
    m_configCapture.v4l_parameters->setVisible(false);
    m_configCapture.v4l_parameters->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 4);
    m_configCapture.v4l_parameters->setPlainText(KdenliveSettings::v4l_parameters());
276

277
    act = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure profiles"), this);
278
    act->setData(2);
Laurent Montel's avatar
Laurent Montel committed
279
    connect(act, &QAction::triggered, this, &KdenliveSettingsDialog::slotManageEncodingProfile);
280
    m_configCapture.v4l_manageprofile->setDefaultAction(act);
Nicolas Carion's avatar
Nicolas Carion committed
281 282
    connect(m_configCapture.kcfg_v4l_profile, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
            &KdenliveSettingsDialog::slotUpdateV4lProfile);
Laurent Montel's avatar
Laurent Montel committed
283
    connect(m_configCapture.v4l_showprofileinfo, &QAbstractButton::clicked, m_configCapture.v4l_parameters, &QWidget::setVisible);
284

285
    // screen grab profile
286
    m_configCapture.grab_showprofileinfo->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
287 288 289
    m_configCapture.grab_parameters->setVisible(false);
    m_configCapture.grab_parameters->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 4);
    m_configCapture.grab_parameters->setPlainText(KdenliveSettings::grab_parameters());
290
    act = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure profiles"), this);
291
    act->setData(3);
Laurent Montel's avatar
Laurent Montel committed
292
    connect(act, &QAction::triggered, this, &KdenliveSettingsDialog::slotManageEncodingProfile);
293
    m_configCapture.grab_manageprofile->setDefaultAction(act);
Nicolas Carion's avatar
Nicolas Carion committed
294 295
    connect(m_configCapture.kcfg_grab_profile, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
            &KdenliveSettingsDialog::slotUpdateGrabProfile);
Laurent Montel's avatar
Laurent Montel committed
296
    connect(m_configCapture.grab_showprofileinfo, &QAbstractButton::clicked, m_configCapture.grab_parameters, &QWidget::setVisible);
Alberto Villa's avatar
Alberto Villa committed
297

298
    // Timeline preview
299
    act = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure profiles"), this);
300
    act->setData(1);
Laurent Montel's avatar
Laurent Montel committed
301
    connect(act, &QAction::triggered, this, &KdenliveSettingsDialog::slotManageEncodingProfile);
302
    m_configProject.preview_manageprofile->setDefaultAction(act);
Nicolas Carion's avatar
Nicolas Carion committed
303 304
    connect(m_configProject.kcfg_preview_profile, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
            &KdenliveSettingsDialog::slotUpdatePreviewProfile);
Laurent Montel's avatar
Laurent Montel committed
305
    connect(m_configProject.preview_showprofileinfo, &QAbstractButton::clicked, m_configProject.previewparams, &QWidget::setVisible);
306 307 308
    m_configProject.previewparams->setVisible(false);
    m_configProject.previewparams->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 3);
    m_configProject.previewparams->setPlainText(KdenliveSettings::previewparams());
309
    m_configProject.preview_showprofileinfo->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
310
    m_configProject.preview_showprofileinfo->setToolTip(i18n("Show default timeline preview parameters"));
311
    m_configProject.preview_manageprofile->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
312 313
    m_configProject.preview_manageprofile->setToolTip(i18n("Manage timeline preview profiles"));
    m_configProject.kcfg_preview_profile->setToolTip(i18n("Select default timeline preview profile"));
314

315
    // proxy profile stuff
316 317 318 319 320 321 322 323
    m_configProxy.proxy_showprofileinfo->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
    m_configProxy.proxy_showprofileinfo->setToolTip(i18n("Show default profile parameters"));
    m_configProxy.proxy_manageprofile->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
    m_configProxy.proxy_manageprofile->setToolTip(i18n("Manage proxy profiles"));
    m_configProxy.kcfg_proxy_profile->setToolTip(i18n("Select default proxy profile"));
    m_configProxy.proxyparams->setVisible(false);
    m_configProxy.proxyparams->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 3);
    m_configProxy.proxyparams->setPlainText(KdenliveSettings::proxyparams());
324

325
    act = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure profiles"), this);
326
    act->setData(0);
Laurent Montel's avatar
Laurent Montel committed
327
    connect(act, &QAction::triggered, this, &KdenliveSettingsDialog::slotManageEncodingProfile);
328
    m_configProxy.proxy_manageprofile->setDefaultAction(act);
329

330 331
    connect(m_configProxy.proxy_showprofileinfo, &QAbstractButton::clicked, m_configProxy.proxyparams, &QWidget::setVisible);
    connect(m_configProxy.kcfg_proxy_profile, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this,
Nicolas Carion's avatar
Nicolas Carion committed
332
            &KdenliveSettingsDialog::slotUpdateProxyProfile);
333 334 335

    slotUpdateProxyProfile(-1);
    slotUpdateV4lProfile(-1);
336
    slotUpdateGrabProfile(-1);
337
    slotUpdateDecklinkProfile(-1);
338

339 340
    // enable GPU accel only if Movit is found
    m_configSdl.kcfg_gpu_accel->setEnabled(gpuAllowed);
341
    m_configSdl.kcfg_gpu_accel->setToolTip(i18n("GPU processing needs MLT compiled with Movit and Rtaudio modules"));
Alberto Villa's avatar
Alberto Villa committed
342

343 344
    getBlackMagicDeviceList(m_configCapture.kcfg_decklink_capturedevice);
    if (!getBlackMagicOutputDeviceList(m_configSdl.kcfg_blackmagic_output_device)) {
345
        // No blackmagic card found
346
        m_configSdl.kcfg_external_display->setEnabled(false);
347
    }
Akhil K Gangadharan's avatar
Akhil K Gangadharan committed
348

349
    // Config dialog size
Akhil K Gangadharan's avatar
Akhil K Gangadharan committed
350 351 352 353
    KSharedConfigPtr config = KSharedConfig::openConfig();
    KConfigGroup settingsGroup(config, "settings");
    QSize optimalSize;

354 355
    if (!settingsGroup.exists() || !settingsGroup.hasKey("dialogSize")) {
        const QSize screenSize = (QGuiApplication::primaryScreen()->availableSize() * 0.9);
Akhil K Gangadharan's avatar
Akhil K Gangadharan committed
356 357
        const QSize targetSize = QSize(1024, 700);
        optimalSize = targetSize.boundedTo(screenSize);
358 359
    } else {
        optimalSize = settingsGroup.readEntry("dialogSize", QVariant(size())).toSize();
Akhil K Gangadharan's avatar
Akhil K Gangadharan committed
360 361
    }
    resize(optimalSize);
362 363
}

364
// static
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
bool KdenliveSettingsDialog::getBlackMagicDeviceList(KComboBox *devicelist, bool force)
{
    if (!force && !KdenliveSettings::decklink_device_found()) {
        return false;
    }
    Mlt::Profile profile;
    Mlt::Producer bm(profile, "decklink");
    int found_devices = 0;
    if (bm.is_valid()) {
        bm.set("list_devices", 1);
        found_devices = bm.get_int("devices");
    } else {
        KdenliveSettings::setDecklink_device_found(false);
    }
    if (found_devices <= 0) {
        devicelist->setEnabled(false);
        return false;
    }
    KdenliveSettings::setDecklink_device_found(true);
    for (int i = 0; i < found_devices; ++i) {
        char *tmp = qstrdup(QStringLiteral("device.%1").arg(i).toUtf8().constData());
        devicelist->addItem(bm.get(tmp));
        delete[] tmp;
    }
    return true;
}

bool KdenliveSettingsDialog::getBlackMagicOutputDeviceList(KComboBox *devicelist, bool force)
{
    if (!force && !KdenliveSettings::decklink_device_found()) {
        return false;
    }
    Mlt::Profile profile;
    Mlt::Consumer bm(profile, "decklink");
    int found_devices = 0;
    if (bm.is_valid()) {
        bm.set("list_devices", 1);
        found_devices = bm.get_int("devices");
    } else {
        KdenliveSettings::setDecklink_device_found(false);
    }
    if (found_devices <= 0) {
        devicelist->setEnabled(false);
        return false;
    }
    KdenliveSettings::setDecklink_device_found(true);
    for (int i = 0; i < found_devices; ++i) {
        char *tmp = qstrdup(QStringLiteral("device.%1").arg(i).toUtf8().constData());
        devicelist->addItem(bm.get(tmp));
        delete[] tmp;
    }
    devicelist->addItem(QStringLiteral("test"));
    return true;
}

Laurent Montel's avatar
Laurent Montel committed
420
void KdenliveSettingsDialog::setupJogshuttleBtns(const QString &device)
421
{
422 423
    QList<KComboBox *> list;
    QList<QLabel *> list1;
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440

    list << m_configShuttle.shuttle1;
    list << m_configShuttle.shuttle2;
    list << m_configShuttle.shuttle3;
    list << m_configShuttle.shuttle4;
    list << m_configShuttle.shuttle5;
    list << m_configShuttle.shuttle6;
    list << m_configShuttle.shuttle7;
    list << m_configShuttle.shuttle8;
    list << m_configShuttle.shuttle9;
    list << m_configShuttle.shuttle10;
    list << m_configShuttle.shuttle11;
    list << m_configShuttle.shuttle12;
    list << m_configShuttle.shuttle13;
    list << m_configShuttle.shuttle14;
    list << m_configShuttle.shuttle15;

Nicolas Carion's avatar
Nicolas Carion committed
441 442 443 444 445 446 447 448
    list1 << m_configShuttle.label_2;  // #1
    list1 << m_configShuttle.label_4;  // #2
    list1 << m_configShuttle.label_3;  // #3
    list1 << m_configShuttle.label_7;  // #4
    list1 << m_configShuttle.label_5;  // #5
    list1 << m_configShuttle.label_6;  // #6
    list1 << m_configShuttle.label_8;  // #7
    list1 << m_configShuttle.label_9;  // #8
449 450 451 452 453 454 455 456
    list1 << m_configShuttle.label_10; // #9
    list1 << m_configShuttle.label_11; // #10
    list1 << m_configShuttle.label_12; // #11
    list1 << m_configShuttle.label_13; // #12
    list1 << m_configShuttle.label_14; // #13
    list1 << m_configShuttle.label_15; // #14
    list1 << m_configShuttle.label_16; // #15

457
    for (int i = 0; i < list.count(); ++i) {
458 459 460
        list[i]->hide();
        list1[i]->hide();
    }
461
#ifdef USE_JOGSHUTTLE
462 463 464
    if (!m_configShuttle.kcfg_enableshuttle->isChecked()) {
        return;
    }
465 466
    int keysCount = JogShuttle::keysCount(device);

467
    for (int i = 0; i < keysCount; ++i) {
468 469 470 471 472 473 474 475 476
        m_shuttle_buttons.push_back(list[i]);
        list[i]->show();
        list1[i]->show();
    }

    // populate the buttons with the current configuration. The items are sorted
    // according to the user-selected language, so they do not appear in random order.
    QMap<QString, QString> mappable_actions(m_mappable_actions);
    QList<QString> action_names = mappable_actions.keys();
477
    QList<QString>::Iterator iter = action_names.begin();
Nicolas Carion's avatar
Nicolas Carion committed
478
    // qCDebug(KDENLIVE_LOG) << "::::::::::::::::";
479
    while (iter != action_names.end()) {
Nicolas Carion's avatar
Nicolas Carion committed
480
        // qCDebug(KDENLIVE_LOG) << *iter;
481 482 483
        ++iter;
    }

Nicolas Carion's avatar
Nicolas Carion committed
484
    // qCDebug(KDENLIVE_LOG) << "::::::::::::::::";
485

486
    qSort(action_names);
487 488
    iter = action_names.begin();
    while (iter != action_names.end()) {
Nicolas Carion's avatar
Nicolas Carion committed
489
        // qCDebug(KDENLIVE_LOG) << *iter;
490 491
        ++iter;
    }
Nicolas Carion's avatar
Nicolas Carion committed
492
    // qCDebug(KDENLIVE_LOG) << "::::::::::::::::";
493 494 495 496 497

    // Here we need to compute the action_id -> index-in-action_names. We iterate over the
    // action_names, as the sorting may depend on the user-language.
    QStringList actions_map = JogShuttleConfig::actionMap(KdenliveSettings::shuttlebuttons());
    QMap<QString, int> action_pos;
Nicolas Carion's avatar
Nicolas Carion committed
498
    for (const QString &action_id : actions_map) {
499 500 501 502 503 504 505 506 507 508
        // This loop find out at what index is the string that would map to the action_id.
        for (int i = 0; i < action_names.size(); ++i) {
            if (mappable_actions[action_names.at(i)] == action_id) {
                action_pos[action_id] = i;
                break;
            }
        }
    }

    int i = 0;
Nicolas Carion's avatar
Nicolas Carion committed
509
    for (KComboBox *button : m_shuttle_buttons) {
510 511 512
        button->addItems(action_names);
        connect(button, SIGNAL(activated(int)), this, SLOT(slotShuttleModified()));
        ++i;
513
        if (i < actions_map.size()) {
514
            button->setCurrentIndex(action_pos[actions_map[i]]);
515
        }
516
    }
517
#endif
518 519
}

Nicolas Carion's avatar
Nicolas Carion committed
520
KdenliveSettingsDialog::~KdenliveSettingsDialog() {}
521

522
void KdenliveSettingsDialog::slotUpdateGrabRegionStatus()
523
{
524
    m_configCapture.region_group->setHidden(m_configCapture.kcfg_grab_capture_type->currentIndex() != 1);
525
}
526

527 528 529 530 531
void KdenliveSettingsDialog::slotEnableCaptureFolder()
{
    m_configEnv.capturefolderurl->setEnabled(!m_configEnv.kcfg_capturetoprojectfolder->isChecked());
}

532 533 534 535 536
void KdenliveSettingsDialog::slotEnableLibraryFolder()
{
    m_configEnv.libraryfolderurl->setEnabled(!m_configEnv.kcfg_librarytodefaultfolder->isChecked());
}

537 538
void KdenliveSettingsDialog::initDevices()
{
539 540
    // Fill audio drivers
    m_configSdl.kcfg_audio_driver->addItem(i18n("Automatic"), QString());
541
#ifndef Q_WS_MAC
542 543
    m_configSdl.kcfg_audio_driver->addItem(i18n("OSS"), "dsp");
    m_configSdl.kcfg_audio_driver->addItem(i18n("ALSA"), "alsa");
544
    m_configSdl.kcfg_audio_driver->addItem(i18n("PulseAudio"), "pulse");
545 546 547
    m_configSdl.kcfg_audio_driver->addItem(i18n("OSS with DMA access"), "dma");
    m_configSdl.kcfg_audio_driver->addItem(i18n("Esound daemon"), "esd");
    m_configSdl.kcfg_audio_driver->addItem(i18n("ARTS daemon"), "artsc");
548
#endif
549

550
    if (!KdenliveSettings::audiodrivername().isEmpty())
551
        for (int i = 1; i < m_configSdl.kcfg_audio_driver->count(); ++i) {
552 553
            if (m_configSdl.kcfg_audio_driver->itemData(i).toString() == KdenliveSettings::audiodrivername()) {
                m_configSdl.kcfg_audio_driver->setCurrentIndex(i);
Nicolas Carion's avatar
Nicolas Carion committed
554
                KdenliveSettings::setAudio_driver((uint)i);
555 556
            }
        }
557

558
    // Fill the list of audio playback / recording devices
559
    m_configSdl.kcfg_audio_device->addItem(i18n("Default"), QString());
560
    m_configCapture.kcfg_v4l_alsadevice->addItem(i18n("Default"), "default");
561
    if (!QStandardPaths::findExecutable(QStringLiteral("aplay")).isEmpty()) {
562
        m_readProcess.setOutputChannelMode(KProcess::OnlyStdoutChannel);
563
        m_readProcess.setProgram(QStringLiteral("aplay"), QStringList() << QStringLiteral("-l"));
Laurent Montel's avatar
Laurent Montel committed
564
        connect(&m_readProcess, &KProcess::readyReadStandardOutput, this, &KdenliveSettingsDialog::slotReadAudioDevices);
565 566 567
        m_readProcess.execute(5000);
    } else {
        // If aplay is not installed on the system, parse the /proc/asound/pcm file
568
        QFile file(QStringLiteral("/proc/asound/pcm"));
569
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
570
            QTextStream stream(&file);
571
            QString line = stream.readLine();
572
            QString deviceId;
573
            while (!line.isNull()) {
574
                if (line.contains(QStringLiteral("playback"))) {
Laurent Montel's avatar
Laurent Montel committed
575
                    deviceId = line.section(QLatin1Char(':'), 0, 0);
Nicolas Carion's avatar
Nicolas Carion committed
576 577 578
                    m_configSdl.kcfg_audio_device->addItem(line.section(QLatin1Char(':'), 1, 1), QStringLiteral("plughw:%1,%2")
                                                                                                     .arg(deviceId.section(QLatin1Char('-'), 0, 0).toInt())
                                                                                                     .arg(deviceId.section(QLatin1Char('-'), 1, 1).toInt()));
579
                }
580
                if (line.contains(QStringLiteral("capture"))) {
Laurent Montel's avatar
Laurent Montel committed
581
                    deviceId = line.section(QLatin1Char(':'), 0, 0);
Nicolas Carion's avatar
Nicolas Carion committed
582 583 584
                    m_configCapture.kcfg_v4l_alsadevice->addItem(
                        line.section(QLatin1Char(':'), 1, 1).simplified(),
                        QStringLiteral("hw:%1,%2").arg(deviceId.section(QLatin1Char('-'), 0, 0).toInt()).arg(deviceId.section(QLatin1Char('-'), 1, 1).toInt()));
585
                }
586
                line = stream.readLine();
587
            }
588
            file.close();
589 590 591
        } else {
            qCDebug(KDENLIVE_LOG) << " / / / /CANNOT READ PCM";
        }
592
    }
593

594 595
    // Add pulseaudio capture option
    m_configCapture.kcfg_v4l_alsadevice->addItem(i18n("PulseAudio"), "pulse");
596

597 598
    if (!KdenliveSettings::audiodevicename().isEmpty()) {
        // Select correct alsa device
599 600 601
        int ix = m_configSdl.kcfg_audio_device->findData(KdenliveSettings::audiodevicename());
        m_configSdl.kcfg_audio_device->setCurrentIndex(ix);
        KdenliveSettings::setAudio_device(ix);
602
    }
Alberto Villa's avatar
Alberto Villa committed
603

604 605 606 607 608 609 610
    if (!KdenliveSettings::v4l_alsadevicename().isEmpty()) {
        // Select correct alsa device
        int ix = m_configCapture.kcfg_v4l_alsadevice->findData(KdenliveSettings::v4l_alsadevicename());
        m_configCapture.kcfg_v4l_alsadevice->setCurrentIndex(ix);
        KdenliveSettings::setV4l_alsadevice(ix);
    }

611
    m_configSdl.kcfg_audio_backend->addItem(i18n("SDL"), KdenliveSettings::sdlAudioBackend());
612 613 614 615 616 617 618
    m_configSdl.kcfg_audio_backend->addItem(i18n("RtAudio"), "rtaudio");

    if (!KdenliveSettings::audiobackend().isEmpty()) {
        int ix = m_configSdl.kcfg_audio_backend->findData(KdenliveSettings::audiobackend());
        m_configSdl.kcfg_audio_backend->setCurrentIndex(ix);
        KdenliveSettings::setAudio_backend(ix);
    }
619
    m_configSdl.group_sdl->setEnabled(KdenliveSettings::audiobackend().startsWith(QLatin1String("sdl_audio")));
620

621
    loadCurrentV4lProfileInfo();
622 623
}

624 625
void KdenliveSettingsDialog::slotReadAudioDevices()
{
626
    QString result = QString(m_readProcess.readAllStandardOutput());
Nicolas Carion's avatar
Nicolas Carion committed
627 628
    // qCDebug(KDENLIVE_LOG) << "// / / / / / READING APLAY: ";
    // qCDebug(KDENLIVE_LOG) << result;
Laurent Montel's avatar
Laurent Montel committed
629
    const QStringList lines = result.split(QLatin1Char('\n'));
630
    for (const QString &devicestr : lines) {
Laurent Montel's avatar
Laurent Montel committed
631
        ////qCDebug(KDENLIVE_LOG) << "// READING LINE: " << data;
632 633 634
        if (!devicestr.startsWith(QLatin1Char(' ')) && devicestr.count(QLatin1Char(':')) > 1) {
            QString card = devicestr.section(QLatin1Char(':'), 0, 0).section(QLatin1Char(' '), -1);
            QString device = devicestr.section(QLatin1Char(':'), 1, 1).section(QLatin1Char(' '), -1);
635
            m_configSdl.kcfg_audio_device->addItem(devicestr.section(QLatin1Char(':'), -1).simplified(), QStringLiteral("plughw:%1,%2").arg(card).arg(device));
Nicolas Carion's avatar
Nicolas Carion committed
636 637
            m_configCapture.kcfg_v4l_alsadevice->addItem(devicestr.section(QLatin1Char(':'), -1).simplified(),
                                                         QStringLiteral("hw:%1,%2").arg(card).arg(device));
638
        }
639 640 641
    }
}

642 643
void KdenliveSettingsDialog::showPage(int page, int option)
{
644 645
    switch (page) {
    case 1:
646
        setCurrentPage(m_page1);
647 648
        break;
    case 2:
649
        setCurrentPage(m_page2);
650 651
        break;
    case 3:
652
        setCurrentPage(m_page3);
653 654
        break;
    case 4:
655
        setCurrentPage(m_page4);
656 657 658
        m_configCapture.tabWidget->setCurrentIndex(option);
        break;
    case 5:
659
        setCurrentPage(m_page5);
660
        break;
661 662 663 664 665 666 667 668
    case 6:
        setCurrentPage(m_page6);
        break;
    case 7:
        setCurrentPage(m_page7);
        break;
    default:
        setCurrentPage(m_page1);
669 670
    }
}
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
671

672 673
void KdenliveSettingsDialog::slotEditAudioApplication()
{
674
    KService::Ptr service;
675
    QPointer<KOpenWithDialog> dlg = new KOpenWithDialog(QList<QUrl>(), i18n("Select default audio editor"), m_configEnv.kcfg_defaultaudioapp->text(), this);
676 677
    if (dlg->exec() == QDialog::Accepted) {
        service = dlg->service();
678
        m_configEnv.kcfg_defaultaudioapp->setText(KRun::binaryName(service->exec(), false));
679
    }
680

681
    delete dlg;
682 683
}

684 685
void KdenliveSettingsDialog::slotEditImageApplication()
{
686
    QPointer<KOpenWithDialog> dlg = new KOpenWithDialog(QList<QUrl>(), i18n("Select default image editor"), m_configEnv.kcfg_defaultimageapp->text(), this);
687
    if (dlg->exec() == QDialog::Accepted) {
Laurent Montel's avatar
Laurent Montel committed
688
        KService::Ptr service = dlg->service();
689
        m_configEnv.kcfg_defaultimageapp->setText(KRun::binaryName(service->exec(), false));
690
    }
691
    delete dlg;
692 693
}

694 695
void KdenliveSettingsDialog::slotCheckShuttle(int state)
{
696
#ifdef USE_JOGSHUTTLE
Nicolas Carion's avatar
Nicolas Carion committed
697
    m_configShuttle.config_group->setEnabled(state != 0);
698
    m_configShuttle.shuttledevicelist->clear();
699

700 701
    QStringList devNames = KdenliveSettings::shuttledevicenames();
    QStringList devPaths = KdenliveSettings::shuttledevicepaths();
702

703 704 705
    if (devNames.count() != devPaths.count()) {
        return;
    }
706
    for (int i = 0; i < devNames.count(); ++i) {
Nicolas Carion's avatar
Nicolas Carion committed
707
        m_configShuttle.shuttledevicelist->addItem(devNames.at(i), devPaths.at(i));