~ubuntu-branches/ubuntu/wily/aegisub/wily-proposed

« back to all changes in this revision

Viewing changes to src/video_display.cpp

  • Committer: Package Import Robot
  • Author(s): Sebastian Reichel, Pascal De Vuyst, Juan Picca, Sebastian Reichel
  • Date: 2015-08-04 21:40:50 UTC
  • mfrom: (5.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20150804214050-y2aghm9vdksoc8t7
Tags: 3.2.2+dfsg-1
[ Pascal De Vuyst ]
* Fix Typo in package description (Closes: #739219)

[ Juan Picca ]
* Add patch to fix reproducible build (Closes: #789728)

[ Sebastian Reichel ]
* New upstream release
 - remove vendor directory from orig tarball
* Update Debian Standards Version to 3.9.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
/// @ingroup video main_ui
33
33
///
34
34
 
35
 
#include "config.h"
36
 
 
37
35
#include "video_display.h"
38
36
 
39
37
#include "ass_file.h"
 
38
#include "async_video_provider.h"
40
39
#include "command/command.h"
41
40
#include "compat.h"
 
41
#include "format.h"
42
42
#include "include/aegisub/context.h"
43
43
#include "include/aegisub/hotkey.h"
44
44
#include "include/aegisub/menu.h"
45
45
#include "options.h"
 
46
#include "project.h"
 
47
#include "retina_helper.h"
46
48
#include "spline_curve.h"
47
 
#include "subs_controller.h"
48
 
#include "threaded_frame_source.h"
49
49
#include "utils.h"
50
50
#include "video_out_gl.h"
51
 
#include "video_context.h"
52
 
#include "video_frame.h"
 
51
#include "video_controller.h"
53
52
#include "visual_tool.h"
54
53
 
55
 
#include <libaegisub/util.h>
 
54
#include <libaegisub/make_unique.h>
56
55
 
57
56
#include <algorithm>
58
 
 
59
57
#include <wx/combobox.h>
60
 
#include <wx/dataobj.h>
61
 
#include <wx/dcclient.h>
62
58
#include <wx/menu.h>
63
59
#include <wx/textctrl.h>
64
60
#include <wx/toolbar.h>
72
68
/// Attribute list for gl canvases; set the canvases to doublebuffered rgba with an 8 bit stencil buffer
73
69
int attribList[] = { WX_GL_RGBA , WX_GL_DOUBLEBUFFER, WX_GL_STENCIL_SIZE, 8, 0 };
74
70
 
75
 
/// @class VideoOutRenderException
76
 
/// @extends VideoOutException
77
 
/// @brief An OpenGL error occurred while uploading or displaying a frame
78
 
class OpenGlException : public agi::Exception {
 
71
/// An OpenGL error occurred while uploading or displaying a frame
 
72
class OpenGlException final : public agi::Exception {
79
73
public:
80
74
        OpenGlException(const char *func, int err)
81
 
        : agi::Exception(from_wx(wxString::Format("%s failed with error code %d", func, err)))
 
75
        : agi::Exception(agi::format("%s failed with error code %d", func, err))
82
76
        { }
83
 
        const char * GetName() const override { return "video/opengl"; }
84
 
        Exception * Copy() const override { return new OpenGlException(*this); }
85
77
};
86
78
 
87
79
#define E(cmd) cmd; if (GLenum err = glGetError()) throw OpenGlException(#cmd, err)
88
80
 
89
 
VideoDisplay::VideoDisplay(
90
 
        wxToolBar *visualSubToolBar,
91
 
        bool freeSize,
92
 
        wxComboBox *zoomBox,
93
 
        wxWindow* parent,
94
 
        agi::Context *c)
 
81
VideoDisplay::VideoDisplay(wxToolBar *toolbar, bool freeSize, wxComboBox *zoomBox, wxWindow *parent, agi::Context *c)
95
82
: wxGLCanvas(parent, -1, attribList)
96
83
, autohideTools(OPT_GET("Tool/Visual/Autohide"))
97
84
, con(c)
98
85
, zoomValue(OPT_GET("Video/Default Zoom")->GetInt() * .125 + .125)
99
 
, toolBar(visualSubToolBar)
 
86
, toolBar(toolbar)
100
87
, zoomBox(zoomBox)
101
88
, freeSize(freeSize)
 
89
, retina_helper(agi::make_unique<RetinaHelper>(this))
 
90
, scale_factor(retina_helper->GetScaleFactor())
 
91
, scale_factor_connection(retina_helper->AddScaleFactorListener([=](int new_scale_factor) {
 
92
        double new_zoom = zoomValue * new_scale_factor / scale_factor;
 
93
        scale_factor = new_scale_factor;
 
94
        SetZoom(new_zoom);
 
95
}))
102
96
{
103
 
        zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.));
 
97
        zoomBox->SetValue(fmt_wx("%g%%", zoomValue * 100.));
104
98
        zoomBox->Bind(wxEVT_COMBOBOX, &VideoDisplay::SetZoomFromBox, this);
105
99
        zoomBox->Bind(wxEVT_TEXT_ENTER, &VideoDisplay::SetZoomFromBoxText, this);
106
100
 
107
101
        con->videoController->Bind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
108
 
        slots.push_back(con->videoController->AddVideoOpenListener(&VideoDisplay::UpdateSize, this));
109
 
        slots.push_back(con->videoController->AddARChangeListener(&VideoDisplay::UpdateSize, this));
110
 
 
111
 
        slots.push_back(con->subsController->AddFileSaveListener(&VideoDisplay::OnSubtitlesSave, this));
 
102
        connections = agi::signal::make_vector({
 
103
                con->project->AddVideoProviderListener(&VideoDisplay::UpdateSize, this),
 
104
                con->videoController->AddARChangeListener(&VideoDisplay::UpdateSize, this),
 
105
        });
112
106
 
113
107
        Bind(wxEVT_PAINT, std::bind(&VideoDisplay::Render, this));
114
108
        Bind(wxEVT_SIZE, &VideoDisplay::OnSizeEvent, this);
126
120
 
127
121
        c->videoDisplay = this;
128
122
 
129
 
        if (con->videoController->IsLoaded())
130
 
                con->videoController->JumpToFrame(con->videoController->GetFrameN());
 
123
        con->videoController->JumpToFrame(con->videoController->GetFrameN());
 
124
 
 
125
        SetLayoutDirection(wxLayout_LeftToRight);
131
126
}
132
127
 
133
128
VideoDisplay::~VideoDisplay () {
144
139
                return false;
145
140
 
146
141
        if (!glContext)
147
 
                glContext = agi::util::make_unique<wxGLContext>(this);
 
142
                glContext = agi::make_unique<wxGLContext>(this);
148
143
 
149
144
        SetCurrent(*glContext);
150
145
        return true;
156
151
}
157
152
 
158
153
void VideoDisplay::Render() try {
159
 
        if (!con->videoController->IsLoaded() || !InitContext() || (!videoOut && !pending_frame))
 
154
        if (!con->project->VideoProvider() || !InitContext() || (!videoOut && !pending_frame))
160
155
                return;
161
156
 
162
157
        if (!videoOut)
163
 
                videoOut = agi::util::make_unique<VideoOutGL>();
 
158
                videoOut = agi::make_unique<VideoOutGL>();
164
159
 
165
160
        if (!tool)
166
161
                cmd::call("video/tool/cross", con);
177
172
                        "programs and updating your video card drivers may fix this.\n"
178
173
                        "Error message reported: %s",
179
174
                        err.GetMessage());
180
 
                con->videoController->SetVideo("");
 
175
                con->project->CloseVideo();
181
176
                return;
182
177
        }
183
178
        catch (const VideoOutRenderException& err) {
199
194
 
200
195
        E(glMatrixMode(GL_PROJECTION));
201
196
        E(glLoadIdentity());
202
 
        E(glOrtho(0.0f, videoSize.GetWidth(), videoSize.GetHeight(), 0.0f, -1000.0f, 1000.0f));
 
197
        E(glOrtho(0.0f, videoSize.GetWidth() / scale_factor, videoSize.GetHeight() / scale_factor, 0.0f, -1000.0f, 1000.0f));
203
198
 
204
199
        if (OPT_GET("Video/Overscan Mask")->GetBool()) {
205
200
                double ar = con->videoController->GetAspectRatioValue();
226
221
        wxLogError(
227
222
                "An error occurred trying to render the video frame on the screen.\n"
228
223
                "Error message reported: %s",
229
 
                err.GetChainedMessage());
230
 
        con->videoController->SetVideo("");
 
224
                err.GetMessage());
 
225
        con->project->CloseVideo();
231
226
}
232
227
 
233
228
void VideoDisplay::DrawOverscanMask(float horizontal_percent, float vertical_percent) const {
269
264
}
270
265
 
271
266
void VideoDisplay::PositionVideo() {
272
 
        if (!con->videoController->IsLoaded() || !IsShownOnScreen()) return;
 
267
        auto provider = con->project->VideoProvider();
 
268
        if (!provider || !IsShownOnScreen()) return;
273
269
 
274
270
        viewport_left = 0;
275
 
        viewport_bottom = GetClientSize().GetHeight() - videoSize.GetHeight();
 
271
        viewport_bottom = GetClientSize().GetHeight() * scale_factor - videoSize.GetHeight();
276
272
        viewport_top = 0;
277
273
        viewport_width = videoSize.GetWidth();
278
274
        viewport_height = videoSize.GetHeight();
279
275
 
280
276
        if (freeSize) {
281
 
                int vidW = con->videoController->GetWidth();
282
 
                int vidH = con->videoController->GetHeight();
 
277
                int vidW = provider->GetWidth();
 
278
                int vidH = provider->GetHeight();
283
279
 
284
280
                AspectRatio arType = con->videoController->GetAspectRatioType();
285
281
                double displayAr = double(viewport_width) / viewport_height;
300
296
        }
301
297
 
302
298
        if (tool)
303
 
                tool->SetDisplayArea(viewport_left, viewport_top, viewport_width, viewport_height);
 
299
                tool->SetDisplayArea(viewport_left / scale_factor, viewport_top / scale_factor,
 
300
                                     viewport_width / scale_factor, viewport_height / scale_factor);
304
301
 
305
302
        Render();
306
303
}
307
304
 
308
305
void VideoDisplay::UpdateSize() {
309
 
        if (!con->videoController->IsLoaded() || !IsShownOnScreen()) return;
 
306
        auto provider = con->project->VideoProvider();
 
307
        if (!provider || !IsShownOnScreen()) return;
310
308
 
311
 
        videoSize.Set(con->videoController->GetWidth(), con->videoController->GetHeight());
 
309
        videoSize.Set(provider->GetWidth(), provider->GetHeight());
312
310
        videoSize *= zoomValue;
313
311
        if (con->videoController->GetAspectRatioType() != AspectRatio::Default)
314
312
                videoSize.SetWidth(videoSize.GetHeight() * con->videoController->GetAspectRatioValue());
320
318
 
321
319
                wxSize cs = GetClientSize();
322
320
                wxSize oldSize = top->GetSize();
323
 
                top->SetSize(top->GetSize() + videoSize - cs);
 
321
                top->SetSize(top->GetSize() + videoSize / scale_factor - cs);
324
322
                SetClientSize(cs + top->GetSize() - oldSize);
325
323
        }
326
324
        else {
327
 
                SetMinClientSize(videoSize);
328
 
                SetMaxClientSize(videoSize);
 
325
                SetMinClientSize(videoSize / scale_factor);
 
326
                SetMaxClientSize(videoSize / scale_factor);
329
327
 
330
328
                GetGrandParent()->Layout();
331
329
        }
335
333
 
336
334
void VideoDisplay::OnSizeEvent(wxSizeEvent &event) {
337
335
        if (freeSize) {
338
 
                videoSize = GetClientSize();
 
336
                videoSize = GetClientSize() * scale_factor;
339
337
                PositionVideo();
340
 
                zoomValue = double(viewport_height) / con->videoController->GetHeight();
341
 
                zoomBox->ChangeValue(wxString::Format("%g%%", zoomValue * 100.));
 
338
                zoomValue = double(viewport_height) / con->project->VideoProvider()->GetHeight();
 
339
                zoomBox->ChangeValue(fmt_wx("%g%%", zoomValue * 100.));
 
340
                con->ass->Properties.video_zoom = zoomValue;
342
341
        }
343
342
        else {
344
343
                PositionVideo();
379
378
}
380
379
 
381
380
void VideoDisplay::SetZoom(double value) {
 
381
        if (value == 0) return;
382
382
        zoomValue = std::max(value, .125);
383
383
        size_t selIndex = zoomValue / .125 - 1;
384
384
        if (selIndex < zoomBox->GetCount())
385
385
                zoomBox->SetSelection(selIndex);
386
 
        zoomBox->ChangeValue(wxString::Format("%g%%", zoomValue * 100.));
 
386
        zoomBox->ChangeValue(fmt_wx("%g%%", zoomValue * 100.));
 
387
        con->ass->Properties.video_zoom = zoomValue;
387
388
        UpdateSize();
388
389
}
389
390
 
391
392
        int sel = zoomBox->GetSelection();
392
393
        if (sel != wxNOT_FOUND) {
393
394
                zoomValue = (sel + 1) * .125;
 
395
                con->ass->Properties.video_zoom = zoomValue;
394
396
                UpdateSize();
395
397
        }
396
398
}
419
421
        else {
420
422
                // UpdateSize fits the window to the video, which we don't want to do
421
423
                GetGrandParent()->Layout();
422
 
                tool->SetDisplayArea(viewport_left, viewport_top, viewport_width, viewport_height);
 
424
                tool->SetDisplayArea(viewport_left / scale_factor, viewport_top / scale_factor,
 
425
                                     viewport_width / scale_factor, viewport_height / scale_factor);
423
426
        }
424
427
}
425
428
 
437
440
        tool.reset();
438
441
        pending_frame.reset();
439
442
}
440
 
 
441
 
void VideoDisplay::OnSubtitlesSave() {
442
 
        con->ass->SaveUIState("Video Zoom Percent", std::to_string(zoomValue));
443
 
}