/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ /* Copyright (C) 2013 Carl Hetherington This program 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "playlist.h" #include "sndfile_content.h" #include "sndfile_decoder.h" #include "video_content.h" #include "ffmpeg_decoder.h" #include "ffmpeg_content.h" #include "imagemagick_decoder.h" #include "imagemagick_content.h" #include "job.h" #include "config.h" #include "util.h" #include "i18n.h" using std::list; using std::cout; using std::vector; using std::min; using std::max; using std::string; using std::stringstream; using boost::optional; using boost::shared_ptr; using boost::weak_ptr; using boost::dynamic_pointer_cast; using boost::lexical_cast; Playlist::Playlist () : _loop (1) { } Playlist::Playlist (shared_ptr other) : _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)); } } void Playlist::content_changed (weak_ptr c, int p) { ContentChanged (c, p); } string Playlist::audio_digest () const { string t; for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) { if (!dynamic_pointer_cast (i->content)) { continue; } t += i->content->digest (); shared_ptr fc = dynamic_pointer_cast (i->content); if (fc) { t += lexical_cast (fc->audio_stream()->id); } } t += lexical_cast (_loop); return md5_digest (t.c_str(), t.length()); } string Playlist::video_digest () const { string t; for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) { if (!dynamic_pointer_cast (i->content)) { continue; } t += i->content->digest (); shared_ptr fc = dynamic_pointer_cast (i->content); if (fc && fc->subtitle_stream()) { t += fc->subtitle_stream()->id; } } t += lexical_cast (_loop); return md5_digest (t.c_str(), t.length()); } void Playlist::set_from_xml (shared_ptr node) { list > c = node->node_children ("Region"); for (list >::iterator i = c.begin(); i != c.end(); ++i) { _regions.push_back (Region (*i, this)); } _loop = node->number_child ("Loop"); } void Playlist::as_xml (xmlpp::Node* node) { for (RegionList::iterator i = _regions.begin(); i != _regions.end(); ++i) { i->as_xml (node->add_child ("Region")); } node->add_child("Loop")->add_child_text(lexical_cast (_loop)); } void Playlist::add (shared_ptr c) { _regions.push_back (Region (c, 0, this)); Changed (); } void Playlist::remove (shared_ptr c) { RegionList::iterator i = _regions.begin (); while (i != _regions.end() && i->content != c) { ++i; } if (i != _regions.end ()) { _regions.erase (i); Changed (); } } void Playlist::set_loop (int l) { _loop = l; Changed (); } bool Playlist::has_subtitles () const { for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) { shared_ptr fc = dynamic_pointer_cast (i->content); if (fc && !fc->subtitle_streams().empty()) { return true; } } return false; } Playlist::Region::Region (shared_ptr c, Time t, Playlist* p) : content (c) , time (t) { connection = c->Changed.connect (bind (&Playlist::content_changed, p, _1, _2)); } Playlist::Region::Region (shared_ptr node, Playlist* p) { shared_ptr content_node = node->node_child ("Content"); string const type = content_node->string_child ("Type"); if (type == "FFmpeg") { content.reset (new FFmpegContent (content_node)); } else if (type == "ImageMagick") { content.reset (new ImageMagickContent (content_node)); } else if (type == "Sndfile") { content.reset (new SndfileContent (content_node)); } time = node->number_child