summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-02-22 18:58:31 +0000
committerCarl Hetherington <cth@carlh.net>2013-02-22 18:58:31 +0000
commit62365221dd3cd80d6b771e9bf22b4f9365ee096a (patch)
tree6d75b967b7e250a93eb3b600ce89706b2018f069
parentfa6c885de512cdde0590c2bbe9ea424030a12c6b (diff)
parent5943bde6f1a29c84b3f79710535a41bb98f6ce7d (diff)
Merge branch 'master' into i18n
-rw-r--r--ChangeLog32
-rw-r--r--debian/changelog48
-rw-r--r--doc/manual/dvdomatic.xml51
-rw-r--r--doc/manual/screenshots/audio-tab.pngbin57463 -> 42143 bytes
-rw-r--r--doc/manual/screenshots/click-content-selector.pngbin31411 -> 31680 bytes
-rw-r--r--doc/manual/screenshots/film-tab.pngbin54280 -> 34610 bytes
-rw-r--r--doc/manual/screenshots/filters.pngbin29608 -> 36613 bytes
-rw-r--r--doc/manual/screenshots/making-dcp.pngbin20676 -> 14493 bytes
-rw-r--r--doc/manual/screenshots/prefs.pngbin55212 -> 49976 bytes
-rw-r--r--doc/manual/screenshots/subtitles-tab.pngbin28155 -> 15068 bytes
-rw-r--r--doc/manual/screenshots/video-tab.pngbin30273 -> 29555 bytes
-rw-r--r--src/lib/dcp_video_frame.cc22
-rw-r--r--src/lib/encoder.cc42
-rw-r--r--src/lib/encoder.h2
-rw-r--r--src/lib/ffmpeg_decoder.cc26
-rw-r--r--src/lib/ffmpeg_decoder.h2
-rw-r--r--src/lib/film.cc16
-rw-r--r--src/lib/film.h2
-rw-r--r--src/lib/image.cc19
-rw-r--r--src/lib/image.h1
-rw-r--r--src/lib/server.cc10
-rw-r--r--src/lib/subtitle.cc4
-rw-r--r--src/lib/util.cc128
-rw-r--r--src/lib/util.h22
-rw-r--r--src/lib/writer.cc4
-rw-r--r--src/tools/dvdomatic.cc36
-rw-r--r--src/tools/makedcp.cc2
-rw-r--r--src/tools/servomatictest.cc52
-rw-r--r--src/tools/wscript2
-rw-r--r--src/wx/film_viewer.cc12
-rw-r--r--src/wx/job_manager_view.cc6
-rw-r--r--src/wx/job_wrapper.cc4
-rw-r--r--src/wx/job_wrapper.h2
-rw-r--r--src/wx/wx_util.cc8
-rw-r--r--src/wx/wx_util.h1
-rw-r--r--test/test.cc4
-rw-r--r--windows/installer.nsi.32.in3
-rw-r--r--windows/installer.nsi.64.in3
-rw-r--r--wscript2
39 files changed, 312 insertions, 256 deletions
diff --git a/ChangeLog b/ChangeLog
index bec619ded..8facb96c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2013-02-21 Carl Hetherington <cth@carlh.net>
+
+ * Version 0.73 released.
+
+2013-02-20 Carl Hetherington <cth@carlh.net>
+
+ * Version 0.73beta9 released.
+
+2013-02-18 Carl Hetherington <cth@carlh.net>
+
+ * Version 0.73beta8 released.
+
+2013-02-18 Carl Hetherington <cth@carlh.net>
+
+ * Version 0.73beta7 released.
+
+2013-02-17 Carl Hetherington <cth@carlh.net>
+
+ * Version 0.73beta6 released.
+
+2013-02-17 Carl Hetherington <cth@carlh.net>
+
+ * Version 0.73beta3 released.
+
+2013-02-16 Carl Hetherington <cth@carlh.net>
+
+ * Version 0.73beta2 released.
+
+2013-02-16 Carl Hetherington <cth@carlh.net>
+
+ * Version 0.73beta1 released.
+
2013-02-15 Carl Hetherington <cth@carlh.net>
* Fix non-recognition of BMP for still images (#55),
diff --git a/debian/changelog b/debian/changelog
index 9ee5288ba..9aaab999d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,51 @@
+dvdomatic (0.73-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Carl Hetherington <carl@houllier.lan> Thu, 21 Feb 2013 00:43:40 +0000
+
+dvdomatic (0.73beta9-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Carl Hetherington <carl@houllier.lan> Wed, 20 Feb 2013 23:40:24 +0000
+
+dvdomatic (0.73beta8-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Carl Hetherington <carl@houllier.lan> Mon, 18 Feb 2013 22:35:51 +0000
+
+dvdomatic (0.73beta7-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Carl Hetherington <carl@houllier.lan> Mon, 18 Feb 2013 20:38:51 +0000
+
+dvdomatic (0.73beta6-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Carl Hetherington <carl@houllier.lan> Sun, 17 Feb 2013 23:05:56 +0000
+
+dvdomatic (0.73beta3-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Carl Hetherington <carl@houllier.lan> Sun, 17 Feb 2013 23:05:05 +0000
+
+dvdomatic (0.73beta2-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Carl Hetherington <carl@houllier.lan> Sat, 16 Feb 2013 22:42:32 +0000
+
+dvdomatic (0.73beta1-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Carl Hetherington <carl@houllier.lan> Sat, 16 Feb 2013 21:19:24 +0000
+
dvdomatic (0.72-1) UNRELEASED; urgency=low
* New upstream release.
diff --git a/doc/manual/dvdomatic.xml b/doc/manual/dvdomatic.xml
index 753358c22..58315eca6 100644
--- a/doc/manual/dvdomatic.xml
+++ b/doc/manual/dvdomatic.xml
@@ -277,7 +277,7 @@ that there will be no sound, and playback might not be entirely
accurate (it may be slightly slower or faster than it should be, for
example). This player is really only intended for brief inspection of
content; if you need to check it more thoroughly, use another player
-such as Totem, mplayer or VLC.
+such as <ulink url="http://projects.gnome.org/totem/index.html">Totem</ulink>, <ulink url="http://www.mplayerhq.hu/design7/news.html">mplayer</ulink> or <ulink url="http://www.videolan.org/vlc/index.html">VLC</ulink>.
</para>
</section>
@@ -325,6 +325,11 @@ open by clicking on the <guilabel>Details</guilabel> button.
</para>
<para>
+If the DCP name is long, it may not all be visible. You can see the
+full name by hovering the mouse pointer over the partial name.
+</para>
+
+<para>
The <guilabel>Trust content's header</guilabel> button starts off
checked, and this means that DVD-o-matic will use the content's header
information to determine its length. If, for some reason, this header
@@ -376,12 +381,9 @@ can project the DCP using your projector's Flat preset.
The remaining options can often be left alone, but may sometimes be
useful. The &lsquo;crop&rsquo; settings can be used to crop your
content, which can be used to remove black borders from round the
-edges of DVD images, for example. The <guilabel>L</guilabel>,
-<guilabel>R</guilabel>, <guilabel>T</guilabel> and
-<guilabel>B</guilabel> settings correspond to the left, right, top and
-bottom of the image respectively. The specified number of pixels will
+edges of DVD images, for example. The specified number of pixels will
be trimmed from each edge, and the content image in the right of the
-window will be updated to show the cropping in action.
+window will be updated to show the effect of the crop.
</para>
<para>
@@ -399,6 +401,19 @@ most situations.
<!-- XXX: link -->
</para>
+<para>
+The &lsquo;colour look-up table&rsquo; specifies the colour space that
+your input content will be expected to be in. If in doubt, leave it
+set to &lsquo;sRGB&rsquo;.
+</para>
+
+<para>
+Finally, the &lsquo;JPEG2000 bandwidth&rsquo; setting changes how big the final
+image files used within the DCP will be. Larger numbers will give
+better quality, but correspondingly larger DCPs. The bandwidth can be
+between 50 and 250 megabits per second (MBps).
+</para>
+
</section>
<section>
@@ -531,8 +546,7 @@ Now that we have set everything up, choose <guilabel>Make
DCP</guilabel> from the <guilabel>Jobs</guilabel> menu. DVD-o-matic
will encode your DCP. This may take some time (many hours in some
cases). While the job is in progress, DVD-o-matic will update you on
-how it is getting on with the progress bar in the bottom right hand
-corner of its window, as shown in <xref linkend="fig-making-dcp"/>.
+how it is getting on with the progress bar in the bottom of its window, as shown in <xref linkend="fig-making-dcp"/>.
</para>
<figure id="fig-making-dcp">
@@ -701,16 +715,6 @@ This is the directory which DVD-o-matic will suggest initially as a place to put
</section>
<section>
-<title>Colour look-up table</title>
-
-<para>
-This specifies the colour space that your input content will be
-expected to be in. If in doubt, leave it set to &lsquo;sRGB&rsquo;.
-</para>
-
-</section>
-
-<section>
<title>A/B options</title>
<para>
@@ -768,17 +772,6 @@ as shown in <xref linkend="fig-filters"/>.
</figure>
<para>
-As it stands, these filters are somewhat disorganised! Work is
-ongoing to test them with various content and choose a selection which
-work well for cinema applications.
-</para>
-
-<para>
-If you want to examine them yourself, you may find the A/B option (see
-<xref linkend="sec-ab"/>) useful.
-</para>
-
-<para>
After changing the filters setup, you will need to regenerate the DCP
to see the effect on the cinema screen. The preview in DVD-o-matic
will update itself whenever filters are changed, though of course this
diff --git a/doc/manual/screenshots/audio-tab.png b/doc/manual/screenshots/audio-tab.png
index 650f67b3c..260f573a4 100644
--- a/doc/manual/screenshots/audio-tab.png
+++ b/doc/manual/screenshots/audio-tab.png
Binary files differ
diff --git a/doc/manual/screenshots/click-content-selector.png b/doc/manual/screenshots/click-content-selector.png
index d8ff34c60..94f44c2a9 100644
--- a/doc/manual/screenshots/click-content-selector.png
+++ b/doc/manual/screenshots/click-content-selector.png
Binary files differ
diff --git a/doc/manual/screenshots/film-tab.png b/doc/manual/screenshots/film-tab.png
index 184a17b7e..e836e3e92 100644
--- a/doc/manual/screenshots/film-tab.png
+++ b/doc/manual/screenshots/film-tab.png
Binary files differ
diff --git a/doc/manual/screenshots/filters.png b/doc/manual/screenshots/filters.png
index 690abe70b..3f3c1e6c0 100644
--- a/doc/manual/screenshots/filters.png
+++ b/doc/manual/screenshots/filters.png
Binary files differ
diff --git a/doc/manual/screenshots/making-dcp.png b/doc/manual/screenshots/making-dcp.png
index 291e5f405..29e1f5d33 100644
--- a/doc/manual/screenshots/making-dcp.png
+++ b/doc/manual/screenshots/making-dcp.png
Binary files differ
diff --git a/doc/manual/screenshots/prefs.png b/doc/manual/screenshots/prefs.png
index 28706dad1..a1e0e083e 100644
--- a/doc/manual/screenshots/prefs.png
+++ b/doc/manual/screenshots/prefs.png
Binary files differ
diff --git a/doc/manual/screenshots/subtitles-tab.png b/doc/manual/screenshots/subtitles-tab.png
index 09a8b8edb..fe509fa85 100644
--- a/doc/manual/screenshots/subtitles-tab.png
+++ b/doc/manual/screenshots/subtitles-tab.png
Binary files differ
diff --git a/doc/manual/screenshots/video-tab.png b/doc/manual/screenshots/video-tab.png
index a3e21c9d3..5881a84d7 100644
--- a/doc/manual/screenshots/video-tab.png
+++ b/doc/manual/screenshots/video-tab.png
Binary files differ
diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc
index 4f3fda44a..9b96724b0 100644
--- a/src/lib/dcp_video_frame.cc
+++ b/src/lib/dcp_video_frame.cc
@@ -316,7 +316,7 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv)
shared_ptr<Socket> socket (new Socket);
- socket->connect (*endpoint_iterator, 30);
+ socket->connect (*endpoint_iterator);
stringstream s;
s << "encode please\n"
@@ -352,21 +352,17 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv)
_input->lines(0), _input->lines(1), _input->lines(2),
_input->line_size()[0], _input->line_size()[1], _input->line_size()[2]
));
-
- socket->write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30);
+
+ socket->write (s.str().length() + 1);
+ socket->write ((uint8_t *) s.str().c_str(), s.str().length() + 1);
_input->write_to_socket (socket);
if (_subtitle) {
_subtitle->image()->write_to_socket (socket);
}
- char buffer[32];
- socket->read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30);
- socket->consume (strlen (buffer) + 1);
- shared_ptr<EncodedData> e (new RemotelyEncodedData (atoi (buffer)));
-
- /* now read the rest */
- socket->read_definite_and_consume (e->data(), e->size(), 30);
+ shared_ptr<EncodedData> e (new RemotelyEncodedData (socket->read_uint32 ()));
+ socket->read (e->data(), e->size());
_log->log (String::compose ("Finished remotely-encoded frame %1", _frame));
@@ -438,10 +434,8 @@ EncodedData::write_info (shared_ptr<const Film> film, int frame, libdcp::FrameIn
void
EncodedData::send (shared_ptr<Socket> socket)
{
- stringstream s;
- s << _size;
- socket->write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30);
- socket->write (_data, _size, 30);
+ socket->write (_size);
+ socket->write (_data, _size);
}
LocallyEncodedData::LocallyEncodedData (uint8_t* d, int s)
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index d64622cba..f25256379 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -140,7 +140,7 @@ Encoder::process_end ()
}
out->set_frames (frames);
- _writer->write (out);
+ write_audio (out);
}
swr_free (&_swr_context);
@@ -319,23 +319,7 @@ Encoder::process_audio (shared_ptr<AudioBuffers> data)
}
#endif
- if (_film->audio_channels() == 1) {
- /* We need to switch things around so that the mono channel is on
- the centre channel of a 5.1 set (with other channels silent).
- */
-
- shared_ptr<AudioBuffers> b (new AudioBuffers (6, data->frames ()));
- b->make_silent (libdcp::LEFT);
- b->make_silent (libdcp::RIGHT);
- memcpy (b->data()[libdcp::CENTRE], data->data()[0], data->frames() * sizeof(float));
- b->make_silent (libdcp::LFE);
- b->make_silent (libdcp::LS);
- b->make_silent (libdcp::RS);
-
- data = b;
- }
-
- _writer->write (data);
+ write_audio (data);
}
void
@@ -435,3 +419,25 @@ Encoder::encoder_thread (ServerDescription* server)
_condition.notify_all ();
}
}
+
+void
+Encoder::write_audio (shared_ptr<const AudioBuffers> data)
+{
+ if (_film->audio_channels() == 1) {
+ /* We need to switch things around so that the mono channel is on
+ the centre channel of a 5.1 set (with other channels silent).
+ */
+
+ shared_ptr<AudioBuffers> b (new AudioBuffers (6, data->frames ()));
+ b->make_silent (libdcp::LEFT);
+ b->make_silent (libdcp::RIGHT);
+ memcpy (b->data()[libdcp::CENTRE], data->data()[0], data->frames() * sizeof(float));
+ b->make_silent (libdcp::LFE);
+ b->make_silent (libdcp::LS);
+ b->make_silent (libdcp::RS);
+
+ data = b;
+ }
+
+ _writer->write (data);
+}
diff --git a/src/lib/encoder.h b/src/lib/encoder.h
index 69a5c5a23..86880bc34 100644
--- a/src/lib/encoder.h
+++ b/src/lib/encoder.h
@@ -88,7 +88,7 @@ private:
void frame_done ();
- void write_audio (boost::shared_ptr<const AudioBuffers> audio);
+ void write_audio (boost::shared_ptr<const AudioBuffers> data);
void encoder_thread (ServerDescription *);
void terminate_threads ();
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 1f11f70a0..d4ed76e37 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -127,7 +127,7 @@ FFmpegDecoder::setup_general ()
/* This is a hack; sometimes it seems that _audio_codec_context->channel_layout isn't set up,
so bodge it here. No idea why we should have to do this.
*/
-
+
if (s->codec->channel_layout == 0) {
s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels);
}
@@ -247,7 +247,7 @@ FFmpegDecoder::pass ()
);
assert (_audio_codec_context->channels == _film->audio_channels());
- Audio (deinterleave_audio (_frame->data[0], data_size));
+ Audio (deinterleave_audio (_frame->data, data_size));
}
}
@@ -320,7 +320,7 @@ FFmpegDecoder::pass ()
);
assert (_audio_codec_context->channels == _film->audio_channels());
- Audio (deinterleave_audio (_frame->data[0], data_size));
+ Audio (deinterleave_audio (_frame->data, data_size));
}
}
@@ -350,8 +350,11 @@ FFmpegDecoder::pass ()
return false;
}
+/** @param data pointer to array of pointers to buffers.
+ * Only the first buffer will be used for non-planar data, otherwise there will be one per channel.
+ */
shared_ptr<AudioBuffers>
-FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
+FFmpegDecoder::deinterleave_audio (uint8_t** data, int size)
{
assert (_film->audio_channels());
assert (bytes_per_audio_sample());
@@ -370,7 +373,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
switch (audio_sample_format()) {
case AV_SAMPLE_FMT_S16:
{
- int16_t* p = reinterpret_cast<int16_t *> (data);
+ int16_t* p = reinterpret_cast<int16_t *> (data[0]);
int sample = 0;
int channel = 0;
for (int i = 0; i < total_samples; ++i) {
@@ -387,10 +390,10 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
case AV_SAMPLE_FMT_S16P:
{
- int16_t* p = reinterpret_cast<int16_t *> (data);
+ int16_t** p = reinterpret_cast<int16_t **> (data);
for (int i = 0; i < _film->audio_channels(); ++i) {
for (int j = 0; j < frames; ++j) {
- audio->data(i)[j] = static_cast<float>(*p++) / (1 << 15);
+ audio->data(i)[j] = static_cast<float>(p[i][j]) / (1 << 15);
}
}
}
@@ -398,7 +401,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
case AV_SAMPLE_FMT_S32:
{
- int32_t* p = reinterpret_cast<int32_t *> (data);
+ int32_t* p = reinterpret_cast<int32_t *> (data[0]);
int sample = 0;
int channel = 0;
for (int i = 0; i < total_samples; ++i) {
@@ -415,7 +418,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
case AV_SAMPLE_FMT_FLT:
{
- float* p = reinterpret_cast<float*> (data);
+ float* p = reinterpret_cast<float*> (data[0]);
int sample = 0;
int channel = 0;
for (int i = 0; i < total_samples; ++i) {
@@ -432,10 +435,9 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
case AV_SAMPLE_FMT_FLTP:
{
- float* p = reinterpret_cast<float*> (data);
+ float** p = reinterpret_cast<float**> (data);
for (int i = 0; i < _film->audio_channels(); ++i) {
- memcpy (audio->data(i), p, frames * sizeof(float));
- p += frames;
+ memcpy (audio->data(i), p[i], frames * sizeof(float));
}
}
break;
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index 17308eb56..c383b8d13 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -121,7 +121,7 @@ private:
void setup_subtitle ();
void maybe_add_subtitle ();
- boost::shared_ptr<AudioBuffers> deinterleave_audio (uint8_t* data, int size);
+ boost::shared_ptr<AudioBuffers> deinterleave_audio (uint8_t** data, int size);
void film_changed (Film::Property);
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 77f61cbac..600cdfa02 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -237,11 +237,9 @@ Film::video_mxf_filename () const
return video_state_identifier() + ".mxf";
}
-/** Add suitable Jobs to the JobManager to create a DCP for this Film.
- * @param true to transcode, false to use the WAV and J2K files that are already there.
- */
+/** Add suitable Jobs to the JobManager to create a DCP for this Film */
void
-Film::make_dcp (bool transcode)
+Film::make_dcp ()
{
set_dci_date_today ();
@@ -298,12 +296,10 @@ Film::make_dcp (bool transcode)
shared_ptr<Job> r;
- if (transcode) {
- if (dcp_ab()) {
- r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od)));
- } else {
- r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od)));
- }
+ if (dcp_ab()) {
+ r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od)));
+ } else {
+ r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od)));
}
}
diff --git a/src/lib/film.h b/src/lib/film.h
index cc77460db..04a483998 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -69,7 +69,7 @@ public:
void examine_content ();
void send_dcp_to_tms ();
- void make_dcp (bool);
+ void make_dcp ();
/** @return Logger.
* It is safe to call this from any thread.
diff --git a/src/lib/image.cc b/src/lib/image.cc
index 0ec6bd26c..73d499fe8 100644
--- a/src/lib/image.cc
+++ b/src/lib/image.cc
@@ -323,7 +323,7 @@ Image::read_from_socket (shared_ptr<Socket> socket)
for (int i = 0; i < components(); ++i) {
uint8_t* p = data()[i];
for (int y = 0; y < lines(i); ++y) {
- socket->read_definite_and_consume (p, line_size()[i], 30);
+ socket->read (p, line_size()[i]);
p += stride()[i];
}
}
@@ -335,7 +335,7 @@ Image::write_to_socket (shared_ptr<Socket> socket) const
for (int i = 0; i < components(); ++i) {
uint8_t* p = data()[i];
for (int y = 0; y < lines(i); ++y) {
- socket->write (p, line_size()[i], 30);
+ socket->write (p, line_size()[i]);
p += stride()[i];
}
}
@@ -503,12 +503,18 @@ FilterBufferImage::FilterBufferImage (AVPixelFormat p, AVFilterBufferRef* b)
: Image (p)
, _buffer (b)
{
-
+ _line_size = (int *) av_malloc (4 * sizeof (int));
+ _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
+
+ for (int i = 0; i < components(); ++i) {
+ _line_size[i] = size().width * bytes_per_pixel(i);
+ }
}
FilterBufferImage::~FilterBufferImage ()
{
avfilter_unref_buffer (_buffer);
+ av_free (_line_size);
}
uint8_t **
@@ -520,13 +526,16 @@ FilterBufferImage::data () const
int *
FilterBufferImage::line_size () const
{
- return _buffer->linesize;
+ return _line_size;
}
int *
FilterBufferImage::stride () const
{
- /* XXX? */
+ /* I've seen images where the _buffer->linesize is larger than the width
+ (by a small amount), suggesting that _buffer->linesize is what we call
+ stride. But I'm not sure.
+ */
return _buffer->linesize;
}
diff --git a/src/lib/image.h b/src/lib/image.h
index 23f13a648..f40ea9280 100644
--- a/src/lib/image.h
+++ b/src/lib/image.h
@@ -117,6 +117,7 @@ private:
FilterBufferImage& operator= (FilterBufferImage const &);
AVFilterBufferRef* _buffer;
+ int* _line_size;
};
/** @class SimpleImage
diff --git a/src/lib/server.cc b/src/lib/server.cc
index d75ab0fb6..3614ed9e4 100644
--- a/src/lib/server.cc
+++ b/src/lib/server.cc
@@ -28,6 +28,7 @@
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/scoped_array.hpp>
#include "server.h"
#include "util.h"
#include "scaler.h"
@@ -45,6 +46,7 @@ using boost::algorithm::is_any_of;
using boost::algorithm::split;
using boost::thread;
using boost::bind;
+using boost::scoped_array;
using libdcp::Size;
/** Create a server description from a string of metadata returned from as_metadata().
@@ -82,11 +84,11 @@ Server::Server (Log* log)
int
Server::process (shared_ptr<Socket> socket)
{
- char buffer[512];
- socket->read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30);
- socket->consume (strlen (buffer) + 1);
+ uint32_t length = socket->read_uint32 ();
+ scoped_array<char> buffer (new char[length]);
+ socket->read (reinterpret_cast<uint8_t*> (buffer.get()), length);
- stringstream s (buffer);
+ stringstream s (buffer.get());
multimap<string, string> kv = read_key_value (s);
if (get_required_string (kv, "encode") != "please") {
diff --git a/src/lib/subtitle.cc b/src/lib/subtitle.cc
index bd5f0c879..5bb91af63 100644
--- a/src/lib/subtitle.cc
+++ b/src/lib/subtitle.cc
@@ -134,8 +134,8 @@ subtitle_transformed_area (
* Combining these two translations gives these expressions.
*/
- tx.x = target_x_scale * (sub_area.x + (sub_area.width * (1 - subtitle_scale) / 2));
- tx.y = target_y_scale * (sub_area.y + (sub_area.height * (1 - subtitle_scale) / 2));
+ tx.x = rint (target_x_scale * (sub_area.x + (sub_area.width * (1 - subtitle_scale) / 2)));
+ tx.y = rint (target_y_scale * (sub_area.y + (sub_area.height * (1 - subtitle_scale) / 2)));
return tx;
}
diff --git a/src/lib/util.cc b/src/lib/util.cc
index c0c8be984..4ee304600 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -485,10 +485,10 @@ colour_lut_index_to_name (int index)
return "";
}
-Socket::Socket ()
+Socket::Socket (int timeout)
: _deadline (_io_service)
, _socket (_io_service)
- , _buffer_data (0)
+ , _timeout (timeout)
{
_deadline.expires_at (posix_time::pos_infin);
check ();
@@ -505,14 +505,13 @@ Socket::check ()
_deadline.async_wait (boost::bind (&Socket::check, this));
}
-/** Blocking connect with timeout.
+/** Blocking connect.
* @param endpoint End-point to connect to.
- * @param timeout Time-out in seconds.
*/
void
-Socket::connect (asio::ip::basic_resolver_entry<asio::ip::tcp> const & endpoint, int timeout)
+Socket::connect (asio::ip::basic_resolver_entry<asio::ip::tcp> const & endpoint)
{
- _deadline.expires_from_now (posix_time::seconds (timeout));
+ _deadline.expires_from_now (posix_time::seconds (_timeout));
system::error_code ec = asio::error::would_block;
_socket.async_connect (endpoint, lambda::var(ec) = lambda::_1);
do {
@@ -524,132 +523,61 @@ Socket::connect (asio::ip::basic_resolver_entry<asio::ip::tcp> const & endpoint,
}
}
-/** Blocking write with timeout.
+/** Blocking write.
* @param data Buffer to write.
* @param size Number of bytes to write.
- * @param timeout Time-out, in seconds.
*/
void
-Socket::write (uint8_t const * data, int size, int timeout)
+Socket::write (uint8_t const * data, int size)
{
- _deadline.expires_from_now (posix_time::seconds (timeout));
+ _deadline.expires_from_now (posix_time::seconds (_timeout));
system::error_code ec = asio::error::would_block;
asio::async_write (_socket, asio::buffer (data, size), lambda::var(ec) = lambda::_1);
+
do {
_io_service.run_one ();
} while (ec == asio::error::would_block);
if (ec) {
- throw NetworkError ("write timed out");
+ throw NetworkError (ec.message ());
}
}
-/** Blocking read with timeout.
+void
+Socket::write (uint32_t v)
+{
+ v = htonl (v);
+ write (reinterpret_cast<uint8_t*> (&v), 4);
+}
+
+/** Blocking read.
* @param data Buffer to read to.
* @param size Number of bytes to read.
- * @param timeout Time-out, in seconds.
*/
-int
-Socket::read (uint8_t* data, int size, int timeout)
+void
+Socket::read (uint8_t* data, int size)
{
- _deadline.expires_from_now (posix_time::seconds (timeout));
+ _deadline.expires_from_now (posix_time::seconds (_timeout));
system::error_code ec = asio::error::would_block;
- int amount_read = 0;
-
- _socket.async_read_some (
- asio::buffer (data, size),
- (lambda::var(ec) = lambda::_1, lambda::var(amount_read) = lambda::_2)
- );
+ asio::async_read (_socket, asio::buffer (data, size), lambda::var(ec) = lambda::_1);
do {
_io_service.run_one ();
} while (ec == asio::error::would_block);
if (ec) {
- amount_read = 0;
- }
-
- return amount_read;
-}
-
-/** Mark some data as being `consumed', so that it will not be returned
- * as data again.
- * @param size Amount of data to consume, in bytes.
- */
-void
-Socket::consume (int size)
-{
- assert (_buffer_data >= size);
-
- _buffer_data -= size;
- if (_buffer_data > 0) {
- /* Shift still-valid data to the start of the buffer */
- memmove (_buffer, _buffer + size, _buffer_data);
+ throw NetworkError (ec.message ());
}
}
-/** Read a definite amount of data from our socket, and mark
- * it as consumed.
- * @param data Where to put the data.
- * @param size Number of bytes to read.
- */
-void
-Socket::read_definite_and_consume (uint8_t* data, int size, int timeout)
-{
- int const from_buffer = min (_buffer_data, size);
- if (from_buffer > 0) {
- /* Get data from our buffer */
- memcpy (data, _buffer, from_buffer);
- consume (from_buffer);
- /* Update our output state */
- data += from_buffer;
- size -= from_buffer;
- }
-
- /* read() the rest */
- while (size > 0) {
- int const n = read (data, size, timeout);
- if (n <= 0) {
- throw NetworkError ("could not read");
- }
-
- data += n;
- size -= n;
- }
-}
-
-/** Read as much data as is available, up to some limit.
- * @param data Where to put the data.
- * @param size Maximum amount of data to read.
- *
- * XXX This method assumes that there is always lots of data to read();
- * if there isn't, it will hang waiting for data that will never arrive.
- */
-void
-Socket::read_indefinite (uint8_t* data, int size, int timeout)
+uint32_t
+Socket::read_uint32 ()
{
- assert (size < int (sizeof (_buffer)));
-
- /* Amount of extra data we need to read () */
- int to_read = size - _buffer_data;
- while (to_read > 0) {
- /* read as much of it as we can (into our buffer) */
- int const n = read (_buffer + _buffer_data, to_read, timeout);
- if (n <= 0) {
- throw NetworkError ("could not read");
- }
-
- to_read -= n;
- _buffer_data += n;
- }
-
- assert (_buffer_data >= size);
-
- /* copy data into the output buffer */
- assert (size >= _buffer_data);
- memcpy (data, _buffer, size);
+ uint32_t v;
+ read (reinterpret_cast<uint8_t *> (&v), 4);
+ return ntohl (v);
}
/** @param other A Rect.
diff --git a/src/lib/util.h b/src/lib/util.h
index c4940a5d7..87735ea8e 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -194,39 +194,35 @@ extern std::string get_optional_string (std::multimap<std::string, std::string>
* that are useful for DVD-o-matic.
*
* This class wraps some things that I could not work out how to do with boost;
- * most notably, sync read/write calls with timeouts, and the ability to peek into
- * data being read.
+ * most notably, sync read/write calls with timeouts.
*/
class Socket
{
public:
- Socket ();
+ Socket (int timeout = 30);
/** @return Our underlying socket */
boost::asio::ip::tcp::socket& socket () {
return _socket;
}
- void connect (boost::asio::ip::basic_resolver_entry<boost::asio::ip::tcp> const & endpoint, int timeout);
- void write (uint8_t const * data, int size, int timeout);
+ void connect (boost::asio::ip::basic_resolver_entry<boost::asio::ip::tcp> const & endpoint);
+
+ void write (uint32_t n);
+ void write (uint8_t const * data, int size);
- void read_definite_and_consume (uint8_t* data, int size, int timeout);
- void read_indefinite (uint8_t* data, int size, int timeout);
- void consume (int amount);
+ void read (uint8_t* data, int size);
+ uint32_t read_uint32 ();
private:
void check ();
- int read (uint8_t* data, int size, int timeout);
Socket (Socket const &);
boost::asio::io_service _io_service;
boost::asio::deadline_timer _deadline;
boost::asio::ip::tcp::socket _socket;
- /** a buffer for small reads */
- uint8_t _buffer[1024];
- /** amount of valid data in the buffer */
- int _buffer_data;
+ int _timeout;
};
/** @class AudioBuffers
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index 8a09f254b..c2cc00328 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -72,13 +72,13 @@ Writer::Writer (shared_ptr<Film> f)
_picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
- if (_film->audio_channels() > 0) {
+ if (dcp_audio_channels (_film->audio_channels()) > 0) {
_sound_asset.reset (
new libdcp::SoundAsset (
_film->dir (_film->dcp_name()),
"audio.mxf",
DCPFrameRate (_film->frames_per_second()).frames_per_second,
- _film->audio_channels(),
+ dcp_audio_channels (_film->audio_channels()),
dcp_audio_sample_rate (_film->audio_stream()->sample_rate())
)
);
diff --git a/src/tools/dvdomatic.cc b/src/tools/dvdomatic.cc
index 5d944a934..1b76132f6 100644
--- a/src/tools/dvdomatic.cc
+++ b/src/tools/dvdomatic.cc
@@ -146,7 +146,6 @@ enum {
ID_jobs_send_dcp_to_tms,
ID_jobs_show_dcp,
ID_jobs_examine_content,
- ID_jobs_make_dcp_from_existing_transcode,
ID_help_about
};
@@ -172,7 +171,6 @@ setup_menu (wxMenuBar* m)
add_item (jobs_menu, "S&how DCP", ID_jobs_show_dcp, NEEDS_FILM);
jobs_menu->AppendSeparator ();
add_item (jobs_menu, "&Examine content", ID_jobs_examine_content, NEEDS_FILM);
- add_item (jobs_menu, "Make DCP from existing &transcode", ID_jobs_make_dcp_from_existing_transcode, NEEDS_FILM);
wxMenu* help = new wxMenu;
add_item (help, "About", ID_help_about, ALWAYS);
@@ -210,7 +208,6 @@ public:
Connect (ID_jobs_send_dcp_to_tms, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_send_dcp_to_tms));
Connect (ID_jobs_show_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_show_dcp));
Connect (ID_jobs_examine_content, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_examine_content));
- Connect (ID_jobs_make_dcp_from_existing_transcode, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_make_dcp_from_existing_transcode));
Connect (ID_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::help_about));
Connect (wxID_ANY, wxEVT_MENU_OPEN, wxMenuEventHandler (Frame::menu_opened));
@@ -224,12 +221,12 @@ public:
film_viewer = new FilmViewer (film, panel);
JobManagerView* job_manager_view = new JobManagerView (panel);
- wxSizer* top_sizer = new wxBoxSizer (wxHORIZONTAL);
- top_sizer->Add (film_editor, 0, wxALL, 6);
- top_sizer->Add (film_viewer, 1, wxEXPAND | wxALL, 6);
+ _top_sizer = new wxBoxSizer (wxHORIZONTAL);
+ _top_sizer->Add (film_editor, 0, wxALL, 6);
+ _top_sizer->Add (film_viewer, 1, wxEXPAND | wxALL, 6);
wxBoxSizer* main_sizer = new wxBoxSizer (wxVERTICAL);
- main_sizer->Add (top_sizer, 2, wxEXPAND | wxALL, 6);
+ main_sizer->Add (_top_sizer, 2, wxEXPAND | wxALL, 6);
main_sizer->Add (job_manager_view, 1, wxEXPAND | wxALL, 6);
panel->SetSizer (main_sizer);
@@ -244,12 +241,24 @@ public:
} else {
file_changed ("");
}
-
+
set_film ();
+
+ film_editor->Connect (wxID_ANY, wxEVT_SIZE, wxSizeEventHandler (Frame::film_editor_sized), 0, this);
}
private:
+ void film_editor_sized (wxSizeEvent &)
+ {
+ static bool in_layout = false;
+ if (!in_layout) {
+ in_layout = true;
+ _top_sizer->Layout ();
+ in_layout = false;
+ }
+ }
+
void menu_opened (wxMenuEvent& ev)
{
if (ev.GetMenu() != jobs_menu) {
@@ -287,7 +296,7 @@ private:
if (r == wxID_OK) {
if (boost::filesystem::exists (d->get_path())) {
- error_dialog (this, wxString::Format (_("The directory %s already exists"), d->get_path().c_str()));
+ error_dialog (this, wxString::Format (_("The directory %s already exists."), d->get_path().c_str()));
return;
}
@@ -350,12 +359,7 @@ private:
void jobs_make_dcp (wxCommandEvent &)
{
- JobWrapper::make_dcp (this, film, true);
- }
-
- void jobs_make_dcp_from_existing_transcode (wxCommandEvent &)
- {
- JobWrapper::make_dcp (this, film, false);
+ JobWrapper::make_dcp (this, film);
}
void jobs_send_dcp_to_tms (wxCommandEvent &)
@@ -408,6 +412,8 @@ private:
info.SetWebSite (wxT ("http://carlh.net/software/dvdomatic"));
wxAboutBox (info);
}
+
+ wxSizer* _top_sizer;
};
#if wxMINOR_VERSION == 9
diff --git a/src/tools/makedcp.cc b/src/tools/makedcp.cc
index 892bed3b8..0c6390771 100644
--- a/src/tools/makedcp.cc
+++ b/src/tools/makedcp.cc
@@ -155,7 +155,7 @@ main (int argc, char* argv[])
pair<string, string> const f = Filter::ffmpeg_strings (film->filters ());
cout << "Filters: " << f.first << " " << f.second << "\n";
- film->make_dcp (true);
+ film->make_dcp ();
bool should_stop = false;
bool first = true;
diff --git a/src/tools/servomatictest.cc b/src/tools/servomatictest.cc
index 88c2a833e..91ad02120 100644
--- a/src/tools/servomatictest.cc
+++ b/src/tools/servomatictest.cc
@@ -34,22 +34,40 @@
#include "scaler.h"
#include "log.h"
#include "decoder_factory.h"
+#include "video_decoder.h"
-using namespace std;
-using namespace boost;
+using std::cout;
+using std::cerr;
+using std::string;
+using std::pair;
+using boost::shared_ptr;
-static Server* server;
-static Log log_ ("servomatictest.log");
+static ServerDescription* server;
+static FileLog log_ ("servomatictest.log");
+static int frame = 0;
void
-process_video (shared_ptr<Image> image, bool, int frame)
+process_video (shared_ptr<Image> image, bool, shared_ptr<Subtitle> sub)
{
- shared_ptr<DCPVideoFrame> local (new DCPVideoFrame (image, Size (1024, 1024), 0, Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_));
- shared_ptr<DCPVideoFrame> remote (new DCPVideoFrame (image, Size (1024, 1024), 0, Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_));
+ shared_ptr<DCPVideoFrame> local (
+ new DCPVideoFrame (
+ image, sub,
+ libdcp::Size (1024, 1024), 0, 0, 0,
+ Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_)
+ );
+
+ shared_ptr<DCPVideoFrame> remote (
+ new DCPVideoFrame (
+ image, sub,
+ libdcp::Size (1024, 1024), 0, 0, 0,
+ Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_)
+ );
cout << "Frame " << frame << ": ";
cout.flush ();
+ ++frame;
+
shared_ptr<EncodedData> local_encoded = local->encode_locally ();
shared_ptr<EncodedData> remote_encoded;
@@ -130,17 +148,21 @@ main (int argc, char* argv[])
dvdomatic_setup ();
- server = new Server (server_host, 1);
- Film film (film_dir, true);
+ server = new ServerDescription (server_host, 1);
+ shared_ptr<Film> film (new Film (film_dir, true));
- shared_ptr<Options> opt (new Options ("fred", "jim", "sheila"));
- opt->out_size = Size (1024, 1024);
- opt->decode_audio = false;
+ DecodeOptions opt;
+ opt.decode_audio = false;
+ opt.decode_subtitles = true;
+ opt.video_sync = true;
- shared_ptr<Decoder> decoder = decoder_factory (film.state_copy(), opt, 0, &log_);
+ Decoders decoders = decoder_factory (film, opt);
try {
- decoder->Video.connect (sigc::ptr_fun (process_video));
- decoder->go ();
+ decoders.video->Video.connect (boost::bind (process_video, _1, _2, _3));
+ bool done = false;
+ while (!done) {
+ done = decoders.video->pass ();
+ }
} catch (std::exception& e) {
cerr << "Error: " << e.what() << "\n";
}
diff --git a/src/tools/wscript b/src/tools/wscript
index 5a837f845..c843c61d8 100644
--- a/src/tools/wscript
+++ b/src/tools/wscript
@@ -1,5 +1,5 @@
def build(bld):
- for t in ['makedcp', 'servomatic_cli']:
+ for t in ['makedcp', 'servomatic_cli', 'servomatictest']:
obj = bld(features = 'cxx cxxprogram')
obj.uselib = 'BOOST_THREAD OPENJPEG DCP AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC'
obj.includes = ['..']
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index e9992a11f..96656ce09 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -149,7 +149,6 @@ FilmViewer::set_film (shared_ptr<Film> f)
_film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1));
film_changed (Film::CONTENT);
- film_changed (Film::CROP);
film_changed (Film::FORMAT);
film_changed (Film::WITH_SUBTITLES);
film_changed (Film::SUBTITLE_OFFSET);
@@ -289,9 +288,16 @@ FilmViewer::raw_to_display ()
}
if (_raw_sub) {
+
+ /* Our output is already cropped by the decoder, so we need to account for that
+ when working out the scale that we are applying.
+ */
+
+ Size const cropped_size = _film->cropped_size (_film->size ());
+
Rect tx = subtitle_transformed_area (
- float (_film_size.width) / _film->size().width,
- float (_film_size.height) / _film->size().height,
+ float (_film_size.width) / cropped_size.width,
+ float (_film_size.height) / cropped_size.height,
_raw_sub->area(), _film->subtitle_offset(), _film->subtitle_scale()
);
diff --git a/src/wx/job_manager_view.cc b/src/wx/job_manager_view.cc
index 8bede709f..7537da287 100644
--- a/src/wx/job_manager_view.cc
+++ b/src/wx/job_manager_view.cc
@@ -98,17 +98,17 @@ JobManagerView::update ()
if (!(*i)->finished ()) {
float const p = (*i)->overall_progress ();
if (p >= 0) {
- _job_records[*i].message->SetLabel (std_to_wx (st));
+ checked_set (_job_records[*i].message, st);
_job_records[*i].gauge->SetValue (p * 100);
} else {
- _job_records[*i].message->SetLabel (_("Running"));
+ checked_set (_job_records[*i].message, wx_to_std (_("Running")));
_job_records[*i].gauge->Pulse ();
}
}
if ((*i)->finished() && !_job_records[*i].finalised) {
_job_records[*i].gauge->SetValue (100);
- _job_records[*i].message->SetLabel (std_to_wx (st));
+ checked_set (_job_records[*i].message, st);
_job_records[*i].finalised = true;
if (!(*i)->error_details().empty ()) {
_job_records[*i].details->Enable (true);
diff --git a/src/wx/job_wrapper.cc b/src/wx/job_wrapper.cc
index cb02ecd02..8ddd3a348 100644
--- a/src/wx/job_wrapper.cc
+++ b/src/wx/job_wrapper.cc
@@ -26,14 +26,14 @@
using boost::shared_ptr;
void
-JobWrapper::make_dcp (wxWindow* parent, shared_ptr<Film> film, bool transcode)
+JobWrapper::make_dcp (wxWindow* parent, shared_ptr<Film> film)
{
if (!film) {
return;
}
try {
- film->make_dcp (transcode);
+ film->make_dcp ();
} catch (BadSettingError& e) {
error_dialog (parent, wxString::Format (_("Bad setting for %s (%s)"), e.setting().c_str(), e.what()));
} catch (std::exception& e) {
diff --git a/src/wx/job_wrapper.h b/src/wx/job_wrapper.h
index 7120e9f10..b0a4693dd 100644
--- a/src/wx/job_wrapper.h
+++ b/src/wx/job_wrapper.h
@@ -24,6 +24,6 @@ class Film;
namespace JobWrapper
{
-void make_dcp (wxWindow *, boost::shared_ptr<Film>, bool);
+void make_dcp (wxWindow *, boost::shared_ptr<Film>);
}
diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc
index 632dbc32e..bf78ff4d7 100644
--- a/src/wx/wx_util.cc
+++ b/src/wx/wx_util.cc
@@ -171,6 +171,14 @@ checked_set (wxTextCtrl* widget, string value)
}
void
+checked_set (wxStaticText* widget, string value)
+{
+ if (widget->GetLabel() != std_to_wx (value)) {
+ widget->SetLabel (std_to_wx (value));
+ }
+}
+
+void
checked_set (wxCheckBox* widget, bool value)
{
if (widget->GetValue() != value) {
diff --git a/src/wx/wx_util.h b/src/wx/wx_util.h
index dd069a9d7..6cde08a90 100644
--- a/src/wx/wx_util.h
+++ b/src/wx/wx_util.h
@@ -63,3 +63,4 @@ extern void checked_set (wxChoice* widget, std::string value);
extern void checked_set (wxTextCtrl* widget, std::string value);
extern void checked_set (wxCheckBox* widget, bool value);
extern void checked_set (wxRadioButton* widget, bool value);
+extern void checked_set (wxStaticText* widget, std::string value);
diff --git a/test/test.cc b/test/test.cc
index 771325d29..386aead2e 100644
--- a/test/test.cc
+++ b/test/test.cc
@@ -480,7 +480,7 @@ BOOST_AUTO_TEST_CASE (make_dcp_test)
film->set_content ("../../../test/test.mp4");
film->set_format (Format::from_nickname ("Flat"));
film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
- film->make_dcp (true);
+ film->make_dcp ();
film->write_metadata ();
while (JobManager::instance()->work_to_do ()) {
@@ -512,7 +512,7 @@ BOOST_AUTO_TEST_CASE (make_dcp_with_range_test)
film->set_format (Format::from_nickname ("Flat"));
film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
film->set_trim_end (42);
- film->make_dcp (true);
+ film->make_dcp ();
while (JobManager::instance()->work_to_do() && !JobManager::instance()->errors()) {
dvdomatic_sleep (1);
diff --git a/windows/installer.nsi.32.in b/windows/installer.nsi.32.in
index bd51b10a7..ccbdd1bd8 100644
--- a/windows/installer.nsi.32.in
+++ b/windows/installer.nsi.32.in
@@ -76,6 +76,9 @@ File "%deps%/bin/libglibmm-2.4-1.dll"
File "%deps%/bin/libxml++-2.6-2.dll"
File "%deps%/bin/libxml2-2.dll"
File "%deps%/bin/libpixman-1-0.dll"
+File "%deps%/bin/libfontconfig-1.dll"
+File "%deps%/bin/libexpat-1.dll"
+File "%deps%/bin/libbz2.dll"
File "%binaries%/src/wx/dvdomatic-wx.dll"
File "%binaries%/src/lib/dvdomatic.dll"
diff --git a/windows/installer.nsi.64.in b/windows/installer.nsi.64.in
index f26494554..9f47f0056 100644
--- a/windows/installer.nsi.64.in
+++ b/windows/installer.nsi.64.in
@@ -86,6 +86,9 @@ File "%deps%/bin/libglibmm-2.4-1.dll"
File "%deps%/bin/libxml++-2.6-2.dll"
File "%deps%/bin/libxml2-2.dll"
File "%deps%/bin/libpixman-1-0.dll"
+File "%deps%/bin/libfontconfig-1.dll"
+File "%deps%/bin/libexpat-1.dll"
+File "%deps%/bin/libbz2.dll"
File "%binaries%/src/wx/dvdomatic-wx.dll"
File "%binaries%/src/lib/dvdomatic.dll"
diff --git a/wscript b/wscript
index 1a8238d1c..cce8c240e 100644
--- a/wscript
+++ b/wscript
@@ -3,7 +3,7 @@ import os
import sys
APPNAME = 'dvdomatic'
-VERSION = '0.73pre'
+VERSION = '0.74pre'
def options(opt):
opt.load('compiler_cxx')