export LD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:$LD_LIBRARY_PATH
if [ "$1" == "--debug" ]; then
shift
- gdb --args build/src/tools/dvdomatic "$*"
+ gdb --args build/src/tools/dvdomatic $*
elif [ "$1" == "--valgrind" ]; then
shift
valgrind --tool="memcheck" build/src/tools/dvdomatic $*
shift
LANGUAGE=fr_FR.UTF8 LANG=fr_FR.UTF8 build/src/tools/dvdomatic "$*"
else
- build/src/tools/dvdomatic "$*"
+ build/src/tools/dvdomatic $*
fi
_film_connection = f->Changed.connect (bind (&Decoder::film_changed, this, _1));
}
-/** Seek to a position as a source timestamp in seconds.
+/** Seek to a position as a content timestamp in seconds.
* @return true on error.
*/
bool
{
throw DecodeError (N_("decoder does not support seek"));
}
-
-/** Seek so that the next frame we will produce is the same as the last one.
- * @return true on error.
- */
-bool
-Decoder::seek_to_last ()
-{
- throw DecodeError (N_("decoder does not support seek"));
-}
virtual bool pass () = 0;
virtual bool seek (double);
- virtual bool seek_to_last ();
protected:
boost::shared_ptr<const Film> _film;
bool
FFmpegDecoder::seek (double p)
{
- return do_seek (p, false);
-}
-
-bool
-FFmpegDecoder::seek_to_last ()
-{
- /* This AVSEEK_FLAG_BACKWARD in do_seek is a bit of a hack; without it, if we ask for a seek to the same place as last time
+ /* This use of AVSEEK_FLAG_BACKWARD is a bit of a hack; without it, if we ask for a seek to the same place as last time
(used when we change decoder parameters and want to re-fetch the frame) we end up going forwards rather than
staying in the same place.
*/
- return do_seek (last_source_time(), true);
-}
-
-bool
-FFmpegDecoder::do_seek (double p, bool backwards)
-{
+ bool const backwards = (p == last_content_time());
+
int64_t const vt = p / av_q2d (_format_context->streams[_video_stream]->time_base);
int const r = av_seek_frame (_format_context, _video_stream, vt, backwards ? AVSEEK_FLAG_BACKWARD : 0);
}
bool seek (double);
- bool seek_to_last ();
bool pass ();
private:
FFmpegDecoder (FFmpegDecoder const &);
FFmpegDecoder& operator= (FFmpegDecoder const &);
- bool do_seek (double p, bool);
PixelFormat pixel_format () const;
AVSampleFormat audio_sample_format () const;
int bytes_per_audio_sample () const;
using std::min;
using std::make_pair;
using std::endl;
+using std::cout;
using std::list;
using boost::shared_ptr;
using boost::lexical_cast;
--j;
swap (*i, *j);
- _playlist->setup (_content);
}
signal_changed (CONTENT);
}
swap (*i, *j);
- _playlist->setup (_content);
}
signal_changed (CONTENT);
: Content (f)
, VideoContent (f)
{
-
+
}
ImageMagickContent::ImageMagickContent (shared_ptr<const cxml::Node> node)
return PIX_FMT_RGB24;
}
-bool
-ImageMagickDecoder::seek_to_last ()
-{
- if (_position > 0) {
- --_position;
- }
-
- return false;
-}
-
bool
ImageMagickDecoder::seek (double t)
{
}
bool seek (double);
- bool seek_to_last ();
bool pass ();
protected:
#include "player.h"
#include "film.h"
#include "ffmpeg_decoder.h"
+#include "ffmpeg_content.h"
#include "imagemagick_decoder.h"
+#include "imagemagick_content.h"
#include "sndfile_decoder.h"
#include "sndfile_content.h"
#include "playlist.h"
, _audio (true)
, _subtitles (true)
, _have_valid_decoders (false)
- , _ffmpeg_decoder_done (false)
, _video_sync (true)
{
_playlist->Changed.connect (bind (&Player::playlist_changed, this));
bool done = true;
- if (_playlist->video_from() == Playlist::VIDEO_FFMPEG || _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
- if (!_ffmpeg_decoder_done) {
- if (_ffmpeg_decoder->pass ()) {
- _ffmpeg_decoder_done = true;
- } else {
- done = false;
- }
+ if (_video_decoder != _video_decoders.end ()) {
+ if ((*_video_decoder)->pass ()) {
+ _video_decoder++;
}
- }
-
- if (_playlist->video_from() == Playlist::VIDEO_IMAGEMAGICK) {
- if (_imagemagick_decoder != _imagemagick_decoders.end ()) {
- if ((*_imagemagick_decoder)->pass ()) {
- _imagemagick_decoder++;
- }
-
- if (_imagemagick_decoder != _imagemagick_decoders.end ()) {
- done = false;
- }
+
+ if (_video_decoder != _video_decoders.end ()) {
+ done = false;
}
}
Player::set_progress (shared_ptr<Job> job)
{
/* Assume progress can be divined from how far through the video we are */
- switch (_playlist->video_from ()) {
- case Playlist::VIDEO_NONE:
- break;
- case Playlist::VIDEO_FFMPEG:
- if (_playlist->video_length ()) {
- job->set_progress (float(_ffmpeg_decoder->video_frame()) / _playlist->video_length ());
- }
- break;
- case Playlist::VIDEO_IMAGEMAGICK:
- {
- int n = 0;
- for (list<shared_ptr<ImageMagickDecoder> >::iterator i = _imagemagick_decoders.begin(); i != _imagemagick_decoders.end(); ++i) {
- if (_imagemagick_decoder == i) {
- job->set_progress (float (n) / _imagemagick_decoders.size ());
- }
- ++n;
- }
- break;
+
+ if (_video_decoder == _video_decoders.end() || !_playlist->video_length()) {
+ return;
}
+
+ ContentVideoFrame p = 0;
+ list<shared_ptr<VideoDecoder> >::iterator i = _video_decoders.begin ();
+ while (i != _video_decoders.end() && i != _video_decoder) {
+ p += (*i)->video_length ();
}
+
+ job->set_progress (float ((*_video_decoder)->video_frame ()) / _playlist->video_length ());
}
void
_have_valid_decoders = true;
}
- bool r = false;
-
- switch (_playlist->video_from()) {
- case Playlist::VIDEO_NONE:
- break;
- case Playlist::VIDEO_FFMPEG:
- if (!_ffmpeg_decoder || _ffmpeg_decoder->seek (t)) {
- r = true;
- }
- /* We're seeking, so all `all done' bets are off */
- _ffmpeg_decoder_done = false;
- break;
- case Playlist::VIDEO_IMAGEMAGICK:
- /* Find the decoder that contains this position */
- _imagemagick_decoder = _imagemagick_decoders.begin ();
- while (_imagemagick_decoder != _imagemagick_decoders.end ()) {
- double const this_length = (*_imagemagick_decoder)->video_length() / _film->video_frame_rate ();
- if (t < this_length) {
- break;
- }
- t -= this_length;
- ++_imagemagick_decoder;
+ /* Find the decoder that contains this position */
+ _video_decoder = _video_decoders.begin ();
+ while (_video_decoder != _video_decoders.end ()) {
+ double const this_length = (*_video_decoder)->video_length() / _film->video_frame_rate ();
+ if (t < this_length) {
+ break;
}
-
- if (_imagemagick_decoder != _imagemagick_decoders.end()) {
- (*_imagemagick_decoder)->seek (t);
- } else {
- r = true;
- }
- break;
- }
-
- /* XXX: don't seek audio because we don't need to... */
-
- return r;
-}
-
-bool
-Player::seek_to_last ()
-{
- if (!_have_valid_decoders) {
- setup_decoders ();
- _have_valid_decoders = true;
+ t -= this_length;
+ ++_video_decoder;
}
-
- bool r = false;
- switch (_playlist->video_from ()) {
- case Playlist::VIDEO_NONE:
- break;
- case Playlist::VIDEO_FFMPEG:
- if (!_ffmpeg_decoder || _ffmpeg_decoder->seek_to_last ()) {
- r = true;
- }
-
- /* We're seeking, so all `all done' bets are off */
- _ffmpeg_decoder_done = false;
- break;
- case Playlist::VIDEO_IMAGEMAGICK:
- if ((*_imagemagick_decoder)->seek_to_last ()) {
- r = true;
- }
- break;
+ if (_video_decoder != _video_decoders.end()) {
+ (*_video_decoder)->seek (t);
+ } else {
+ return true;
}
/* XXX: don't seek audio because we don't need to... */
- return r;
+ return false;
}
void
Player::setup_decoders ()
{
- if ((_video && _playlist->video_from() == Playlist::VIDEO_FFMPEG) || (_audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG)) {
- _ffmpeg_decoder.reset (
- new FFmpegDecoder (
- _film,
- _playlist->ffmpeg(),
- _video && _playlist->video_from() == Playlist::VIDEO_FFMPEG,
- _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
- _subtitles && _film->with_subtitles(),
- _video_sync
- )
- );
- }
-
- if (_video && _playlist->video_from() == Playlist::VIDEO_FFMPEG) {
- _ffmpeg_decoder->connect_video (shared_from_this ());
- }
+ if (_video) {
+ list<shared_ptr<const VideoContent> > vc = _playlist->video ();
+ for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
+
+ shared_ptr<VideoDecoder> d;
+
+ /* XXX: into content? */
+
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ shared_ptr<FFmpegDecoder> fd (
+ new FFmpegDecoder (
+ _film, fc, _video,
+ _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
+ _subtitles && _film->with_subtitles(),
+ _video_sync
+ )
+ );
+
+ if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
+ fd->Audio.connect (bind (&Player::process_audio, this, fc, _1));
+ }
+
+ d = fd;
+ }
- if (_audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
- _ffmpeg_decoder->Audio.connect (bind (&Player::process_audio, this, _playlist->ffmpeg (), _1));
- }
+ shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
+ if (ic) {
+ d.reset (new ImageMagickDecoder (_film, ic));
+ }
- if (_video && _playlist->video_from() == Playlist::VIDEO_IMAGEMAGICK) {
- list<shared_ptr<const ImageMagickContent> > ic = _playlist->imagemagick ();
- for (list<shared_ptr<const ImageMagickContent> >::iterator i = ic.begin(); i != ic.end(); ++i) {
- shared_ptr<ImageMagickDecoder> d (new ImageMagickDecoder (_film, *i));
- _imagemagick_decoders.push_back (d);
d->connect_video (shared_from_this ());
+ _video_decoders.push_back (d);
}
- _imagemagick_decoder = _imagemagick_decoders.begin ();
+ _video_decoder = _video_decoders.begin ();
}
if (_audio && _playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
double
Player::last_video_time () const
{
- switch (_playlist->video_from ()) {
- case Playlist::VIDEO_NONE:
- return 0;
- case Playlist::VIDEO_FFMPEG:
- return _ffmpeg_decoder->last_source_time ();
- case Playlist::VIDEO_IMAGEMAGICK:
- {
- double t = 0;
- for (list<shared_ptr<ImageMagickDecoder> >::const_iterator i = _imagemagick_decoders.begin(); i != _imagemagick_decoder; ++i) {
- t += (*i)->video_length() / (*i)->video_frame_rate ();
- }
-
- return t + (*_imagemagick_decoder)->last_source_time ();
- }
+ double t = 0;
+ for (list<shared_ptr<VideoDecoder> >::const_iterator i = _video_decoders.begin(); i != _video_decoder; ++i) {
+ t += (*i)->video_length() / (*i)->video_frame_rate ();
}
- return 0;
+ return t + (*_video_decoder)->last_content_time ();
}
void
if (p == VideoContentProperty::VIDEO_LENGTH) {
if (dynamic_pointer_cast<FFmpegContent> (c)) {
+ /* FFmpeg content length changes are serious; we need new decoders */
_have_valid_decoders = false;
}
}
#include "video_sink.h"
#include "audio_sink.h"
-class FFmpegDecoder;
-class ImageMagickDecoder;
+class VideoDecoder;
class SndfileDecoder;
class Job;
class Film;
bool pass ();
void set_progress (boost::shared_ptr<Job>);
bool seek (double);
- bool seek_to_last ();
double last_video_time () const;
bool _subtitles;
bool _have_valid_decoders;
- boost::shared_ptr<FFmpegDecoder> _ffmpeg_decoder;
- bool _ffmpeg_decoder_done;
- std::list<boost::shared_ptr<ImageMagickDecoder> > _imagemagick_decoders;
- std::list<boost::shared_ptr<ImageMagickDecoder> >::iterator _imagemagick_decoder;
+ std::list<boost::shared_ptr<VideoDecoder> > _video_decoders;
+ std::list<boost::shared_ptr<VideoDecoder> >::iterator _video_decoder;
std::list<boost::shared_ptr<SndfileDecoder> > _sndfile_decoders;
boost::shared_ptr<AudioBuffers> _sndfile_buffers;
#include "playlist.h"
#include "sndfile_content.h"
#include "sndfile_decoder.h"
-#include "ffmpeg_content.h"
+#include "video_content.h"
#include "ffmpeg_decoder.h"
-#include "imagemagick_content.h"
+#include "ffmpeg_content.h"
#include "imagemagick_decoder.h"
#include "job.h"
using std::cout;
using std::vector;
using std::min;
+using std::max;
using boost::shared_ptr;
using boost::weak_ptr;
using boost::dynamic_pointer_cast;
Playlist::Playlist ()
- : _video_from (VIDEO_NONE)
- , _audio_from (AUDIO_NONE)
+ : _audio_from (AUDIO_FFMPEG)
{
}
void
Playlist::setup (ContentList content)
{
- _video_from = VIDEO_NONE;
- _audio_from = AUDIO_NONE;
+ _audio_from = AUDIO_FFMPEG;
- _ffmpeg.reset ();
- _imagemagick.clear ();
+ _video.clear ();
_sndfile.clear ();
for (list<boost::signals2::connection>::iterator i = _content_connections.begin(); i != _content_connections.end(); ++i) {
_content_connections.clear ();
for (ContentList::const_iterator i = content.begin(); i != content.end(); ++i) {
- shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
- if (fc) {
- assert (!_ffmpeg);
- _ffmpeg = fc;
- _video_from = VIDEO_FFMPEG;
- if (_audio_from == AUDIO_NONE) {
- _audio_from = AUDIO_FFMPEG;
- }
+ shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*i);
+ if (vc) {
+ _video.push_back (vc);
}
- shared_ptr<ImageMagickContent> ic = dynamic_pointer_cast<ImageMagickContent> (*i);
- if (ic) {
- _imagemagick.push_back (ic);
- if (_video_from == VIDEO_NONE) {
- _video_from = VIDEO_IMAGEMAGICK;
- }
- }
-
shared_ptr<SndfileContent> sc = dynamic_pointer_cast<SndfileContent> (*i);
if (sc) {
_sndfile.push_back (sc);
ContentAudioFrame
Playlist::audio_length () const
{
+ ContentAudioFrame len = 0;
+
switch (_audio_from) {
- case AUDIO_NONE:
- return 0;
case AUDIO_FFMPEG:
- return _ffmpeg->audio_length ();
+ for (list<shared_ptr<const VideoContent> >::const_iterator i = _video.begin(); i != _video.end(); ++i) {
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ len += fc->audio_length ();
+ }
+ }
+ break;
case AUDIO_SNDFILE:
- {
- ContentAudioFrame l = 0;
for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
- l += (*i)->audio_length ();
+ len += (*i)->audio_length ();
}
- return l;
- }
+ break;
}
- return 0;
+ return len;
}
int
Playlist::audio_channels () const
{
+ int channels = 0;
+
switch (_audio_from) {
- case AUDIO_NONE:
- return 0;
case AUDIO_FFMPEG:
- return _ffmpeg->audio_channels ();
+ for (list<shared_ptr<const VideoContent> >::const_iterator i = _video.begin(); i != _video.end(); ++i) {
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ channels = max (channels, fc->audio_channels ());
+ }
+ }
+ break;
case AUDIO_SNDFILE:
- {
- int c = 0;
for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
- c += (*i)->audio_channels ();
+ channels += (*i)->audio_channels ();
}
- return c;
- }
+ break;
}
- return 0;
+ return channels;
}
int
Playlist::audio_frame_rate () const
{
+ /* XXX: assuming that all content has the same rate */
+
switch (_audio_from) {
- case AUDIO_NONE:
- return 0;
case AUDIO_FFMPEG:
- return _ffmpeg->audio_frame_rate ();
+ {
+ shared_ptr<const FFmpegContent> fc = first_ffmpeg ();
+ if (fc) {
+ return fc->audio_channels ();
+ }
+ break;
+ }
case AUDIO_SNDFILE:
return _sndfile.front()->audio_frame_rate ();
}
int64_t
Playlist::audio_channel_layout () const
{
+ /* XXX: assuming that all content has the same layout */
+
switch (_audio_from) {
- case AUDIO_NONE:
- return 0;
case AUDIO_FFMPEG:
- return _ffmpeg->audio_channel_layout ();
+ {
+ shared_ptr<const FFmpegContent> fc = first_ffmpeg ();
+ if (fc) {
+ return fc->audio_channel_layout ();
+ }
+ break;
+ }
case AUDIO_SNDFILE:
/* XXX */
return 0;
float
Playlist::video_frame_rate () const
{
- switch (_video_from) {
- case VIDEO_NONE:
+ if (_video.empty ()) {
return 0;
- case VIDEO_FFMPEG:
- return _ffmpeg->video_frame_rate ();
- case VIDEO_IMAGEMAGICK:
- return 24;
}
-
- return 0;
+
+ /* XXX: assuming all the same */
+ return _video.front()->video_frame_rate ();
}
libdcp::Size
Playlist::video_size () const
{
- switch (_video_from) {
- case VIDEO_NONE:
+ if (_video.empty ()) {
return libdcp::Size ();
- case VIDEO_FFMPEG:
- return _ffmpeg->video_size ();
- case VIDEO_IMAGEMAGICK:
- /* XXX */
- return _imagemagick.front()->video_size ();
}
- return libdcp::Size ();
+ /* XXX: assuming all the same */
+ return _video.front()->video_size ();
}
ContentVideoFrame
Playlist::video_length () const
{
- switch (_video_from) {
- case VIDEO_NONE:
- return 0;
- case VIDEO_FFMPEG:
- return _ffmpeg->video_length ();
- case VIDEO_IMAGEMAGICK:
- {
- ContentVideoFrame l = 0;
- for (list<shared_ptr<const ImageMagickContent> >::const_iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) {
- l += (*i)->video_length ();
- }
- return l;
+ ContentVideoFrame len = 0;
+ for (list<shared_ptr<const VideoContent> >::const_iterator i = _video.begin(); i != _video.end(); ++i) {
+ len += (*i)->video_length ();
}
- }
-
- return 0;
+
+ return len;
}
bool
Playlist::has_audio () const
{
- return _audio_from != AUDIO_NONE;
+ /* XXX */
+ return true;
}
void
ContentChanged (c, p);
}
+shared_ptr<const FFmpegContent>
+Playlist::first_ffmpeg () const
+{
+ for (list<shared_ptr<const VideoContent> >::const_iterator i = _video.begin(); i != _video.end(); ++i) {
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ return fc;
+ }
+ }
+
+ return shared_ptr<const FFmpegContent> ();
+}
+
+
AudioMapping
Playlist::default_audio_mapping () const
{
AudioMapping m;
switch (_audio_from) {
- case AUDIO_NONE:
- break;
case AUDIO_FFMPEG:
- if (_ffmpeg->audio_channels() == 1) {
+ {
+ shared_ptr<const FFmpegContent> fc = first_ffmpeg ();
+ if (!fc) {
+ break;
+ }
+
+ /* XXX: assumes all the same */
+ if (fc->audio_channels() == 1) {
/* Map mono sources to centre */
- m.add (AudioMapping::Channel (_ffmpeg, 0), libdcp::CENTRE);
+ m.add (AudioMapping::Channel (fc, 0), libdcp::CENTRE);
} else {
- int const N = min (_ffmpeg->audio_channels (), MAX_AUDIO_CHANNELS);
+ int const N = min (fc->audio_channels (), MAX_AUDIO_CHANNELS);
/* Otherwise just start with a 1:1 mapping */
for (int i = 0; i < N; ++i) {
- m.add (AudioMapping::Channel (_ffmpeg, i), (libdcp::Channel) i);
+ m.add (AudioMapping::Channel (fc, i), (libdcp::Channel) i);
}
}
break;
+ }
case AUDIO_SNDFILE:
{
int n = 0;
for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
- cout << "sndfile " << (*i)->audio_channels() << "\n";
for (int j = 0; j < (*i)->audio_channels(); ++j) {
m.add (AudioMapping::Channel (*i, j), (libdcp::Channel) n);
++n;
AudioMapping default_audio_mapping () const;
- enum VideoFrom {
- VIDEO_NONE,
- VIDEO_FFMPEG,
- VIDEO_IMAGEMAGICK
- };
-
enum AudioFrom {
- AUDIO_NONE,
AUDIO_FFMPEG,
AUDIO_SNDFILE
};
- VideoFrom video_from () const {
- return _video_from;
- }
-
AudioFrom audio_from () const {
return _audio_from;
}
- boost::shared_ptr<const FFmpegContent> ffmpeg () const {
- return _ffmpeg;
- }
-
- std::list<boost::shared_ptr<const ImageMagickContent> > imagemagick () const {
- return _imagemagick;
+ std::list<boost::shared_ptr<const VideoContent> > video () const {
+ return _video;
}
std::list<boost::shared_ptr<const SndfileContent> > sndfile () const {
private:
void content_changed (boost::weak_ptr<Content>, int);
+ boost::shared_ptr<const FFmpegContent> first_ffmpeg () const;
- VideoFrom _video_from;
AudioFrom _audio_from;
- boost::shared_ptr<const FFmpegContent> _ffmpeg;
- std::list<boost::shared_ptr<const ImageMagickContent> > _imagemagick;
+ std::list<boost::shared_ptr<const VideoContent> > _video;
std::list<boost::shared_ptr<const SndfileContent> > _sndfile;
std::list<boost::signals2::connection> _content_connections;
VideoDecoder::VideoDecoder (shared_ptr<const Film> f)
: Decoder (f)
, _video_frame (0)
- , _last_source_time (0)
+ , _last_content_time (0)
{
}
_last_image = image;
_last_subtitle = sub;
- _last_source_time = t;
+ _last_content_time = t;
}
/** Set up the current subtitle. This will be put onto frames that
return _video_frame;
}
- double last_source_time () const {
- return _last_source_time;
+ double last_content_time () const {
+ return _last_content_time;
}
protected:
void signal_video (boost::shared_ptr<Image>, bool, boost::shared_ptr<Subtitle>, double);
int _video_frame;
- double _last_source_time;
+ double _last_content_time;
boost::shared_ptr<TimedSubtitle> _timed_subtitle;
static shared_ptr<Film> film;
static std::string log_level;
static std::string film_to_load;
+static std::string film_to_create;
static wxMenu* jobs_menu = 0;
static wxLocale* locale = 0;
#if wxMINOR_VERSION == 9
static const wxCmdLineEntryDesc command_line_description[] = {
{ wxCMD_LINE_OPTION, "l", "log", "set log level (silent, verbose or timing)", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
- { wxCMD_LINE_PARAM, 0, 0, "film to load", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_SWITCH, "n", "new", "create new film", wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_PARAM, 0, 0, "film to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 }
};
#else
static const wxCmdLineEntryDesc command_line_description[] = {
{ wxCMD_LINE_OPTION, wxT("l"), wxT("log"), wxT("set log level (silent, verbose or timing)"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
- { wxCMD_LINE_PARAM, 0, 0, wxT("film to load"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_SWITCH, wxT("n"), wxT("new"), wxT("create new film"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_PARAM, 0, 0, wxT("film to load or create"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_NONE, wxT(""), wxT(""), wxT(""), wxCmdLineParamType (0), 0 }
};
#endif
}
}
+ if (!film_to_create.empty ()) {
+ film.reset (new Film (film_to_create, false));
+ film->log()->set_level (log_level);
+ film->set_name (boost::filesystem::path (film_to_create).filename().generic_string ());
+ }
+
Frame* f = new Frame (_("DVD-o-matic"));
SetTopWindow (f);
f->Maximize ();
bool OnCmdLineParsed (wxCmdLineParser& parser)
{
if (parser.GetParamCount() > 0) {
- film_to_load = wx_to_std (parser.GetParam(0));
+ if (parser.FoundSwitch (wxT ("new"))) {
+ film_to_create = wx_to_std (parser.GetParam (0));
+ } else {
+ film_to_load = wx_to_std (parser.GetParam(0));
+ }
}
wxString log;
- if (parser.Found(wxT("log"), &log)) {
+ if (parser.Found (wxT ("log"), &log)) {
log_level = wx_to_std (log);
}
void
FilmViewer::update_from_decoder ()
{
- if (!_player || _player->seek_to_last ()) {
+ if (!_player || _player->seek (_player->last_video_time ())) {
return;
}