-audio map view is screwed up on windows, apparently not extended to full height
-still image stuff pretty slow
+ffmpeg content selected stream is really a playlist thing.
+
#define DCPOMATIC_AUDIO_CONTENT_H
#include "content.h"
-#include "audio_mapping.h"
namespace cxml {
class Node;
virtual ContentAudioFrame audio_length () const = 0;
virtual int content_audio_frame_rate () const = 0;
virtual int output_audio_frame_rate (boost::shared_ptr<const Film>) const = 0;
- virtual AudioMapping audio_mapping () const = 0;
};
#endif
}
FFmpegAudioStream::FFmpegAudioStream (shared_ptr<const cxml::Node> node)
- : mapping (node->node_child ("Mapping"))
{
name = node->string_child ("Name");
id = node->number_child<int> ("Id");
root->add_child("Id")->add_child_text (lexical_cast<string> (id));
root->add_child("FrameRate")->add_child_text (lexical_cast<string> (frame_rate));
root->add_child("Channels")->add_child_text (lexical_cast<string> (channels));
- mapping.as_xml (root->add_child("Mapping"));
}
/** Construct a SubtitleStream from a value returned from to_string().
FrameRateConversion frc (video_frame_rate (), film->dcp_video_frame_rate ());
return video_length() * frc.factor() * TIME_HZ / film->dcp_video_frame_rate ();
}
-
-AudioMapping
-FFmpegContent::audio_mapping () const
-{
- if (!_audio_stream) {
- return AudioMapping ();
- }
-
- return _audio_stream->mapping;
-}
, id (i)
, frame_rate (f)
, channels (c)
- , mapping (c)
{}
FFmpegAudioStream (boost::shared_ptr<const cxml::Node>);
int id;
int frame_rate;
int channels;
- AudioMapping mapping;
};
extern bool operator== (FFmpegAudioStream const & a, FFmpegAudioStream const & b);
ContentAudioFrame audio_length () const;
int content_audio_frame_rate () const;
int output_audio_frame_rate (boost::shared_ptr<const Film>) const;
- AudioMapping audio_mapping () const;
std::vector<FFmpegSubtitleStream> subtitle_streams () const {
boost::mutex::scoped_lock lm (_mutex);
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
/*
Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
if (!_trust_content_headers && !regions.empty()) {
/* We just said that we don't trust the content's header */
for (Playlist::RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
- examine_content (i->content);
+ examine_content ((*i)->content);
}
}
}
Time next_wait = TIME_MAX;
for (list<shared_ptr<RegionDecoder> >::iterator i = _decoders.begin(); i != _decoders.end(); ++i) {
- Time const ts = (*i)->region.time;
- Time const te = (*i)->region.time + (*i)->region.content->length (_film);
+ Time const ts = (*i)->region->time;
+ Time const te = (*i)->region->time + (*i)->region->content->length (_film);
if (ts <= _position && te > _position) {
Time const pos = ts + (*i)->last;
if (pos < earliest_pos) {
{
shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> (rd->decoder);
- Time const global_time = rd->region.time + time;
+ Time const global_time = rd->region->time + time;
while ((global_time - _last_video) > 1) {
/* Fill in with black */
emit_black_frame ();
/* XXX: into content? */
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (i->content);
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> ((*i)->content);
if (fc) {
shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio, _subtitles));
rd->decoder = fd;
}
- shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (i->content);
+ shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> ((*i)->content);
if (ic) {
shared_ptr<ImageMagickDecoder> id;
rd->decoder = id;
}
- shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (i->content);
+ shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> ((*i)->content);
if (sc) {
shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
sd->Audio.connect (bind (&Player::process_audio, this, rd, _1, _2));
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
/*
Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
: last (0)
{}
- Playlist::Region region;
+ boost::shared_ptr<Playlist::Region> region;
boost::shared_ptr<Decoder> decoder;
Time last;
};
: _loop (other->_loop)
{
for (RegionList::const_iterator i = other->_regions.begin(); i != other->_regions.end(); ++i) {
- _regions.push_back (Region (i->content->clone(), i->time, this));
+ _regions.push_back (shared_ptr<Region> (new Region ((*i)->content->clone(), (*i)->time, this)));
}
}
string t;
for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) {
- if (!dynamic_pointer_cast<const AudioContent> (i->content)) {
+ if (!dynamic_pointer_cast<const AudioContent> ((*i)->content)) {
continue;
}
- t += i->content->digest ();
+ t += (*i)->content->digest ();
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (i->content);
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> ((*i)->content);
if (fc) {
t += lexical_cast<string> (fc->audio_stream()->id);
}
string t;
for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) {
- if (!dynamic_pointer_cast<const VideoContent> (i->content)) {
+ if (!dynamic_pointer_cast<const VideoContent> ((*i)->content)) {
continue;
}
- t += i->content->digest ();
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (i->content);
+ t += (*i)->content->digest ();
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> ((*i)->content);
if (fc && fc->subtitle_stream()) {
t += fc->subtitle_stream()->id;
}
{
list<shared_ptr<cxml::Node> > c = node->node_children ("Region");
for (list<shared_ptr<cxml::Node> >::iterator i = c.begin(); i != c.end(); ++i) {
- _regions.push_back (Region (*i, this));
+ _regions.push_back (shared_ptr<Region> (new Region (*i, this)));
}
_loop = node->number_child<int> ("Loop");
Playlist::as_xml (xmlpp::Node* node)
{
for (RegionList::iterator i = _regions.begin(); i != _regions.end(); ++i) {
- i->as_xml (node->add_child ("Region"));
+ (*i)->as_xml (node->add_child ("Region"));
}
node->add_child("Loop")->add_child_text(lexical_cast<string> (_loop));
void
Playlist::add (shared_ptr<Content> c)
{
- _regions.push_back (Region (c, 0, this));
+ _regions.push_back (shared_ptr<Region> (new Region (c, 0, this)));
Changed ();
}
Playlist::remove (shared_ptr<Content> c)
{
RegionList::iterator i = _regions.begin ();
- while (i != _regions.end() && i->content != c) {
+ while (i != _regions.end() && (*i)->content != c) {
++i;
}
Playlist::has_subtitles () const
{
for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) {
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (i->content);
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> ((*i)->content);
if (fc && !fc->subtitle_streams().empty()) {
return true;
}
}
time = node->number_child<Time> ("Time");
+ audio_mapping = AudioMapping (node->node_child ("AudioMapping"));
connection = content->Changed.connect (bind (&Playlist::content_changed, p, _1, _2));
}
xmlpp::Node* sub = node->add_child ("Content");
content->as_xml (sub);
node->add_child ("Time")->add_child_text (lexical_cast<string> (time));
+ audio_mapping.as_xml (node->add_child ("AudioMapping"));
}
class FrameRateCandidate
float this_error = std::numeric_limits<float>::max ();
for (RegionList::const_iterator j = _regions.begin(); j != _regions.end(); ++j) {
- shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (j->content);
+ shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*j)->content);
if (!vc) {
continue;
}
{
Time len = 0;
for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) {
- Time const t = i->time + i->content->length (film);
+ Time const t = (*i)->time + (*i)->content->length (film);
len = max (len, t);
}
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
/*
Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
boost::shared_ptr<Content> content;
Time time;
+ /* XXX: obviously not used for video-only; there should
+ really by AudioRegion / VideoRegion etc.
+ */
+ AudioMapping audio_mapping;
boost::signals2::connection connection;
};
- typedef std::vector<Region> RegionList;
+ typedef std::vector<boost::shared_ptr<Region> > RegionList;
RegionList regions () const {
return _regions;
_audio_channels = node->number_child<int> ("AudioChannels");
_audio_length = node->number_child<ContentAudioFrame> ("AudioLength");
_audio_frame_rate = node->number_child<int> ("AudioFrameRate");
- _mapping = AudioMapping (node->node_child ("Mapping"));
}
string
_audio_channels = dec.audio_channels ();
_audio_length = dec.audio_length ();
_audio_frame_rate = dec.audio_frame_rate ();
- _mapping = AudioMapping (_audio_channels);
}
signal_changed (AudioContentProperty::AUDIO_CHANNELS);
node->add_child("AudioChannels")->add_child_text (lexical_cast<string> (_audio_channels));
node->add_child("AudioLength")->add_child_text (lexical_cast<string> (_audio_length));
node->add_child("AudioFrameRate")->add_child_text (lexical_cast<string> (_audio_frame_rate));
- _mapping.as_xml (node->add_child("Mapping"));
}
int
int output_audio_frame_rate (boost::shared_ptr<const Film>) const;
- AudioMapping audio_mapping () const {
- boost::mutex::scoped_lock lm (_mutex);
- return _mapping;
- }
-
static bool valid_file (boost::filesystem::path);
private:
int _audio_channels;
ContentAudioFrame _audio_length;
int _audio_frame_rate;
- AudioMapping _mapping;
};
_grid->AutoSize ();
- wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
- s->Add (_grid, 1, wxEXPAND);
- SetSizerAndFit (s);
+ _sizer = new wxBoxSizer (wxVERTICAL);
+ _sizer->Add (_grid, 1, wxEXPAND | wxALL);
+ SetSizerAndFit (_sizer);
Connect (wxID_ANY, wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler (AudioMappingView::left_click), 0, this);
}
} else {
_grid->SetCellValue (ev.GetRow(), ev.GetCol(), wxT("1"));
}
+
+ AudioMapping mapping;
+ for (int i = 0; i < _grid->GetNumberRows(); ++i) {
+ for (int j = 0; j < _grid->GetNumberCols(); ++j) {
+ if (_grid->GetCellValue (i, j) == wxT ("1")) {
+ mapping.add (i, static_cast<libdcp::Channel> (j));
+ }
+ }
+ }
+
+ Changed (mapping);
}
void
}
++n;
}
-
- _grid->AutoSize ();
}
void set_mapping (AudioMapping);
+ boost::signals2::signal<void (AudioMapping)> Changed;
+
private:
void left_click (wxGridEvent &);
wxGrid* _grid;
+ wxSizer* _sizer;
};
#include <boost/lexical_cast.hpp>
#include "lib/ffmpeg_content.h"
+#include "lib/playlist.h"
#include "ffmpeg_content_dialog.h"
#include "wx_util.h"
#include "audio_mapping_view.h"
using std::vector;
using std::string;
+using std::cout;
using boost::shared_ptr;
using boost::lexical_cast;
+using boost::dynamic_pointer_cast;
-FFmpegContentDialog::FFmpegContentDialog (wxWindow* parent, shared_ptr<FFmpegContent> content)
+FFmpegContentDialog::FFmpegContentDialog (wxWindow* parent, shared_ptr<Playlist::Region> region)
: wxDialog (parent, wxID_ANY, _("Video"))
+ , _region (region)
+ , _content (dynamic_pointer_cast<FFmpegContent> (region->content))
{
wxFlexGridSizer* grid = new wxFlexGridSizer (3, 6, 6);
grid->AddGrowableCol (1, 1);
grid->Add (_subtitle_stream, 1, wxEXPAND | wxALL, 6);
grid->AddSpacer (0);
- _audio_mapping = new AudioMappingView (this);
- grid->Add (_audio_mapping, 1, wxEXPAND | wxALL, 6);
- grid->AddSpacer (0);
+ shared_ptr<FFmpegContent> content = _content.lock ();
+ assert (content);
_audio_stream->Clear ();
vector<FFmpegAudioStream> a = content->audio_streams ();
_subtitle_stream->SetSelection (wxNOT_FOUND);
}
- _audio_mapping->set_mapping (content->audio_mapping ());
-
wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
+
overall_sizer->Add (grid, 1, wxEXPAND | wxALL, 6);
+ _audio_mapping = new AudioMappingView (this);
+ _audio_mapping->set_mapping (region->audio_mapping);
+ overall_sizer->Add (_audio_mapping, 1, wxEXPAND | wxALL, 6);
+
wxSizer* buttons = CreateSeparatedButtonSizer (wxOK);
if (buttons) {
overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
_audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FFmpegContentDialog::audio_stream_changed), 0, this);
_subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FFmpegContentDialog::subtitle_stream_changed), 0, this);
+ _audio_mapping->Changed.connect (bind (&FFmpegContentDialog::audio_mapping_changed, this, _1));
}
void
c->set_subtitle_stream (*i);
}
}
+
+void
+FFmpegContentDialog::audio_mapping_changed (AudioMapping m)
+{
+ shared_ptr<FFmpegContent> content = _content.lock ();
+
+ if (!content || !content->audio_stream()) {
+ return;
+ }
+
+ /* XXX: set mapping in playlist */
+}
+
#include <wx/wx.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
+#include "lib/audio_mapping.h"
+#include "lib/playlist.h"
class wxSpinCtrl;
class FFmpegContent;
class FFmpegContentDialog : public wxDialog
{
public:
- FFmpegContentDialog (wxWindow *, boost::shared_ptr<FFmpegContent>);
+ FFmpegContentDialog (wxWindow *, boost::shared_ptr<Playlist::Region>);
private:
void audio_stream_changed (wxCommandEvent &);
void subtitle_stream_changed (wxCommandEvent &);
+ void audio_mapping_changed (AudioMapping);
+ boost::weak_ptr<Playlist::Region> _region;
boost::weak_ptr<FFmpegContent> _content;
wxChoice* _audio_stream;
wxStaticText* _audio_description;
} else if (property == VideoContentProperty::VIDEO_LENGTH || property == AudioContentProperty::AUDIO_LENGTH) {
setup_length ();
boost::shared_ptr<Content> c = content.lock ();
- if (c && c == selected_content()) {
+ if (selected_region() && c == selected_region()->content) {
setup_content_information ();
}
} else if (property == FFmpegContentProperty::AUDIO_STREAM) {
Playlist::RegionList regions = _film->regions ();
for (Playlist::RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
int const t = _content->GetItemCount ();
- _content->InsertItem (t, std_to_wx (i->content->summary ()));
- if (i->content->summary() == selected_summary) {
+ _content->InsertItem (t, std_to_wx ((*i)->content->summary ()));
+ if ((*i)->content->summary() == selected_summary) {
_content->SetItemState (t, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
}
}
void
FilmEditor::content_remove_clicked (wxCommandEvent &)
{
- shared_ptr<Content> c = selected_content ();
- if (c) {
- _film->remove_content (c);
+ shared_ptr<Playlist::Region> r = selected_region ();
+ if (r) {
+ _film->remove_content (r->content);
}
}
Playlist::RegionList r = _film->regions ();
assert (ev.GetIndex() >= 0 && size_t (ev.GetIndex()) < r.size ());
- content_properties (r[ev.GetIndex()].content);
+ region_properties (r[ev.GetIndex()]);
}
void
FilmEditor::content_properties_clicked (wxCommandEvent &)
{
- shared_ptr<Content> c = selected_content ();
- if (!c) {
+ shared_ptr<Playlist::Region> r = selected_region ();
+ if (!r) {
return;
}
- content_properties (c);
+ content_properties (r);
}
void
-FilmEditor::content_properties (shared_ptr<Content> content)
+FilmEditor::region_properties (shared_ptr<Playlist::Region> region)
{
- shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (content);
- if (im) {
- ImageMagickContentDialog* d = new ImageMagickContentDialog (this, im);
+ if (dynamic_pointer_cast<ImageMagickContent> (region->content)) {
+ ImageMagickContentDialog* d = new ImageMagickContentDialog (this, region);
d->ShowModal ();
d->Destroy ();
}
- shared_ptr<FFmpegContent> ff = dynamic_pointer_cast<FFmpegContent> (content);
- if (ff) {
- FFmpegContentDialog* d = new FFmpegContentDialog (this, ff);
+ if (dynamic_pointer_cast<FFmpegContent> (region->content)) {
+ FFmpegContentDialog* d = new FFmpegContentDialog (this, region);
d->ShowModal ();
d->Destroy ();
}
void
FilmEditor::setup_content_information ()
{
- shared_ptr<Content> c = selected_content ();
- if (!c) {
+ shared_ptr<Playlist::Region> r = selected_region ();
+ if (!r) {
_content_information->SetValue (wxT (""));
return;
}
- _content_information->SetValue (std_to_wx (c->information ()));
+ _content_information->SetValue (std_to_wx (r->content->information ()));
}
void
{
_content_add->Enable (_generally_sensitive);
- shared_ptr<Content> selection = selected_content ();
+ shared_ptr<Playlist::Region> selection = selected_region ();
_content_properties->Enable (
selection && _generally_sensitive &&
- (dynamic_pointer_cast<ImageMagickContent> (selection) || dynamic_pointer_cast<FFmpegContent> (selection))
+ (dynamic_pointer_cast<ImageMagickContent> (selection->content) || dynamic_pointer_cast<FFmpegContent> (selection->content))
);
_content_remove->Enable (selection && _generally_sensitive);
_content_timeline->Enable (_generally_sensitive);
}
-shared_ptr<Content>
-FilmEditor::selected_content ()
+shared_ptr<Playlist::Region>
+FilmEditor::selected_region ()
{
int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (s == -1) {
- return shared_ptr<Content> ();
+ return shared_ptr<Playlist::Region> ();
}
Playlist::RegionList r = _film->regions ();
if (s < 0 || size_t (s) >= r.size ()) {
- return shared_ptr<Content> ();
+ return shared_ptr<Playlist::Region> ();
}
- return r[s].content;
+ return r[s];
}
void
void setup_loop_sensitivity ();
void active_jobs_changed (bool);
- boost::shared_ptr<Content> selected_content ();
- void content_properties (boost::shared_ptr<Content>);
+ boost::shared_ptr<Playlist::Region> selected_region ();
+ void region_properties (boost::shared_ptr<Playlist::Region>);
wxNotebook* _notebook;
wxPanel* _film_panel;
Playlist::RegionList regions = fl->playlist()->regions ();
for (Playlist::RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
- if (dynamic_pointer_cast<VideoContent> (i->content)) {
- _views.push_back (shared_ptr<View> (new VideoContentView (*this, i->content, i->time, 0)));
+ if (dynamic_pointer_cast<VideoContent> ((*i)->content)) {
+ _views.push_back (shared_ptr<View> (new VideoContentView (*this, (*i)->content, (*i)->time, 0)));
} else {
- _views.push_back (shared_ptr<View> (new AudioContentView (*this, i->content, i->time, 1)));
+ _views.push_back (shared_ptr<View> (new AudioContentView (*this, (*i)->content, (*i)->time, 1)));
}
}