1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
/*
Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
DCP-o-matic 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.
DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file src/film_viewer.h
* @brief FilmViewer class.
*/
#include "video_view.h"
#include "lib/film.h"
#include "lib/config.h"
#include "lib/player_text.h"
#include "lib/timer.h"
#include "lib/signaller.h"
#include <RtAudio.h>
#include <wx/wx.h>
class wxToggleButton;
class FFmpegPlayer;
class Image;
class RGBPlusAlphaImage;
class PlayerVideo;
class Player;
class Butler;
class ClosedCaptionsDialog;
/** @class FilmViewer
* @brief A wx widget to view a Film.
*/
class FilmViewer : public Signaller
{
public:
FilmViewer (wxWindow *);
~FilmViewer ();
/** @return the window showing the film's video */
wxWindow* panel () const {
return _video_view->get();
}
VideoView const * video_view () const {
return _video_view;
}
void show_closed_captions ();
void set_film (boost::shared_ptr<Film>);
boost::shared_ptr<Film> film () const {
return _film;
}
void seek (dcpomatic::DCPTime t, bool accurate);
void seek (boost::shared_ptr<Content> content, dcpomatic::ContentTime p, bool accurate);
void seek_by (dcpomatic::DCPTime by, bool accurate);
/** @return our `playhead' position; this may not lie exactly on a frame boundary */
dcpomatic::DCPTime position () const {
return _video_view->position();
}
dcpomatic::DCPTime one_video_frame () const;
void start ();
bool stop ();
void suspend ();
void resume ();
bool playing () const {
return _playing;
}
void set_coalesce_player_changes (bool c);
void set_dcp_decode_reduction (boost::optional<int> reduction);
boost::optional<int> dcp_decode_reduction () const;
void set_outline_content (bool o);
void set_eyes (Eyes e);
void set_pad_black (bool p);
void slow_refresh ();
dcpomatic::DCPTime time () const;
boost::optional<dcpomatic::DCPTime> audio_time () const;
int dropped () const;
int gets () const;
int audio_callback (void* out, unsigned int frames);
#ifdef DCPOMATIC_VARIANT_SWAROOP
void set_background_image (bool b) {
_background_image = b;
_video_view->update ();
}
bool background_image () const {
return _background_image;
}
#endif
StateTimer const & state_timer () const {
return _video_view->state_timer ();
}
/* Some accessors and utility methods that VideoView classes need */
dcp::Size out_size () const {
return _out_size;
}
bool outline_content () const {
return _outline_content;
}
bool pad_black () const {
return _pad_black;
}
boost::shared_ptr<Butler> butler () const {
return _butler;
}
ClosedCaptionsDialog* closed_captions_dialog () const {
return _closed_captions_dialog;
}
void finished ();
boost::signals2::signal<void (boost::weak_ptr<PlayerVideo>)> ImageChanged;
boost::signals2::signal<void (dcpomatic::DCPTime)> Started;
boost::signals2::signal<void (dcpomatic::DCPTime)> Stopped;
/** While playing back we reached the end of the film (emitted from GUI thread) */
boost::signals2::signal<void ()> Finished;
boost::signals2::signal<bool ()> PlaybackPermitted;
private:
void video_view_sized ();
void calculate_sizes ();
void player_change (ChangeType type, int, bool);
void idle_handler ();
void request_idle_display_next_frame ();
void film_change (ChangeType, Film::Property);
void recreate_butler ();
void config_changed (Config::Property);
void film_length_change ();
void ui_finished ();
dcpomatic::DCPTime uncorrected_time () const;
Frame average_latency () const;
bool quick_refresh ();
boost::shared_ptr<Film> _film;
boost::shared_ptr<Player> _player;
VideoView* _video_view;
bool _coalesce_player_changes;
std::list<int> _pending_player_changes;
/** Size of our output (including padding if we have any) */
dcp::Size _out_size;
RtAudio _audio;
int _audio_channels;
unsigned int _audio_block_size;
bool _playing;
int _suspended;
boost::shared_ptr<Butler> _butler;
std::list<Frame> _latency_history;
/** Mutex to protect _latency_history */
mutable boost::mutex _latency_history_mutex;
int _latency_history_count;
boost::optional<int> _dcp_decode_reduction;
ClosedCaptionsDialog* _closed_captions_dialog;
bool _outline_content;
/** true to pad the viewer panel with black, false to use
the normal window background colour.
*/
bool _pad_black;
#ifdef DCPOMATIC_VARIANT_SWAROOP
bool _background_image;
#endif
/** true if an get() is required next time we are idle */
bool _idle_get;
boost::signals2::scoped_connection _config_changed_connection;
};
|