src/platform/qt/GIFView.cpp (view raw)
1/* Copyright (c) 2013-2014 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "GIFView.h"
7
8#ifdef USE_FFMPEG
9
10#include "CoreController.h"
11#include "GBAApp.h"
12#include "LogController.h"
13
14#include <QMap>
15
16using namespace QGBA;
17
18GIFView::GIFView(QWidget* parent)
19 : QWidget(parent)
20{
21 m_ui.setupUi(this);
22
23 connect(m_ui.start, &QAbstractButton::clicked, this, &GIFView::startRecording);
24 connect(m_ui.stop, &QAbstractButton::clicked, this, &GIFView::stopRecording);
25
26 connect(m_ui.selectFile, &QAbstractButton::clicked, this, &GIFView::selectFile);
27 connect(m_ui.filename, &QLineEdit::textChanged, this, &GIFView::setFilename);
28 connect(m_ui.fmtGif, &QAbstractButton::clicked, this, &GIFView::changeExtension);
29 connect(m_ui.fmtApng, &QAbstractButton::clicked, this, &GIFView::changeExtension);
30 connect(m_ui.fmtWebP, &QAbstractButton::clicked, this, &GIFView::changeExtension);
31
32 FFmpegEncoderInit(&m_encoder);
33 FFmpegEncoderSetAudio(&m_encoder, nullptr, 0);
34}
35
36GIFView::~GIFView() {
37 stopRecording();
38}
39
40void GIFView::setController(std::shared_ptr<CoreController> controller) {
41 connect(controller.get(), &CoreController::stopping, this, &GIFView::stopRecording);
42 connect(this, &GIFView::recordingStarted, controller.get(), &CoreController::setAVStream);
43 connect(this, &GIFView::recordingStopped, controller.get(), &CoreController::clearAVStream, Qt::DirectConnection);
44 QSize size(controller->screenDimensions());
45 FFmpegEncoderSetDimensions(&m_encoder, size.width(), size.height());
46}
47
48void GIFView::startRecording() {
49 if (m_ui.fmtWebP->isChecked()) {
50 FFmpegEncoderSetContainer(&m_encoder, "webp");
51 FFmpegEncoderSetVideo(&m_encoder, "libwebp_anim", 0, m_ui.frameskip->value());
52 } else if (m_ui.fmtApng->isChecked()) {
53 FFmpegEncoderSetContainer(&m_encoder, "apng");
54 FFmpegEncoderSetVideo(&m_encoder, "apng", 0, m_ui.frameskip->value());
55 } else {
56 FFmpegEncoderSetContainer(&m_encoder, "gif");
57 FFmpegEncoderSetVideo(&m_encoder, "gif", 0, m_ui.frameskip->value());
58 }
59 FFmpegEncoderSetLooping(&m_encoder, m_ui.loop->isChecked());
60 if (!FFmpegEncoderOpen(&m_encoder, m_filename.toUtf8().constData())) {
61 LOG(QT, ERROR) << tr("Failed to open output file: %1").arg(m_filename);
62 return;
63 }
64 m_ui.start->setEnabled(false);
65 m_ui.stop->setEnabled(true);
66 m_ui.frameskip->setEnabled(false);
67 m_ui.loop->setEnabled(false);
68 m_ui.fmtWebP->setEnabled(false);
69 m_ui.fmtApng->setEnabled(false);
70 m_ui.fmtGif->setEnabled(false);
71 m_ui.fmtWebP->setEnabled(false);
72 emit recordingStarted(&m_encoder.d);
73}
74
75void GIFView::stopRecording() {
76 emit recordingStopped();
77 FFmpegEncoderClose(&m_encoder);
78 m_ui.stop->setEnabled(false);
79 m_ui.start->setEnabled(!m_filename.isEmpty());
80 m_ui.frameskip->setEnabled(true);
81 m_ui.loop->setEnabled(true);
82 m_ui.fmtWebP->setEnabled(true);
83 m_ui.fmtApng->setEnabled(true);
84 m_ui.fmtGif->setEnabled(true);
85}
86
87void GIFView::selectFile() {
88 QString filename = GBAApp::app()->getSaveFileName(this, tr("Select output file"), tr("Graphics Interchange Format (*.gif);;Animated Portable Network Graphics (*.png *.webp *.apng)"));
89 m_ui.filename->setText(filename);
90}
91
92void GIFView::setFilename(const QString& filename) {
93 m_filename = filename;
94 if (!FFmpegEncoderIsOpen(&m_encoder)) {
95 m_ui.start->setEnabled(!filename.isEmpty());
96 if (filename.endsWith(".gif")) {
97 m_ui.fmtGif->setChecked(Qt::Checked);
98 } else if (filename.endsWith(".png") || filename.endsWith(".apng")) {
99 m_ui.fmtApng->setChecked(Qt::Checked);
100 } else if (filename.endsWith(".webp")) {
101 m_ui.fmtWebP->setChecked(Qt::Checked);
102 }
103 }
104}
105
106void GIFView::changeExtension() {
107 if (m_filename.isEmpty()) {
108 return;
109 }
110 QString filename = m_filename;
111 int index = m_filename.lastIndexOf(".");
112 if (index >= 0) {
113 filename.truncate(index);
114 }
115 if (m_ui.fmtGif->isChecked()) {
116 filename += ".gif";
117 } else if (m_ui.fmtWebP->isChecked()) {
118 filename += ".webp";
119 } else if (m_ui.fmtApng->isChecked()) {
120 filename += ".png";
121 }
122 m_ui.filename->setText(filename);
123}
124
125#endif