2 Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /** @file src/lib/content_factory.cc
21 * @brief Methods to create content objects.
24 #include "ffmpeg_content.h"
25 #include "image_content.h"
26 #include "sndfile_content.h"
27 #include "subrip_content.h"
28 #include "dcp_content.h"
29 #include "dcp_subtitle_content.h"
31 #include <libcxml/cxml.h>
32 #include <dcp/smpte_subtitle_asset.h>
33 #include <boost/algorithm/string.hpp>
37 using boost::shared_ptr;
39 /** Create a Content object from an XML node.
40 * @param film Film that the content will be in.
41 * @param node XML description.
42 * @param version XML state version.
43 * @param notes A list to which is added descriptions of any non-critial warnings / messages.
44 * @return Content object, or 0 if no content was recognised in the XML.
47 content_factory (shared_ptr<const Film> film, cxml::NodePtr node, int version, list<string>& notes)
49 string const type = node->string_child ("Type");
51 boost::shared_ptr<Content> content;
53 if (type == "FFmpeg") {
54 content.reset (new FFmpegContent (film, node, version, notes));
55 } else if (type == "Image") {
56 content.reset (new ImageContent (film, node, version));
57 } else if (type == "Sndfile") {
58 content.reset (new SndfileContent (film, node, version));
59 } else if (type == "SubRip") {
60 content.reset (new SubRipContent (film, node, version));
61 } else if (type == "DCP") {
62 content.reset (new DCPContent (film, node, version));
63 } else if (type == "DCPSubtitle") {
64 content.reset (new DCPSubtitleContent (film, node, version));
70 /** Create a Content object from a file or directory.
71 * @param film Film that the content will be in.
72 * @param path File or directory.
73 * @return Content object.
76 content_factory (shared_ptr<const Film> film, boost::filesystem::path path)
78 shared_ptr<Content> content;
80 if (boost::filesystem::is_directory (path)) {
82 if (boost::filesystem::is_empty (path)) {
83 return shared_ptr<Content> ();
86 /* Guess if this is a DCP or a set of images: read the first ten filenames and if they
87 are all valid image files we assume it is a set of images.
92 for (boost::filesystem::directory_iterator i(path); i != boost::filesystem::directory_iterator() && read < 10; ++i) {
94 if (boost::starts_with (i->path().leaf().string(), "._")) {
95 /* We ignore these files */
99 if (!boost::filesystem::is_regular_file (i->path()) || !valid_image_file (i->path())) {
107 content.reset (new DCPContent (film, path));
109 content.reset (new ImageContent (film, path));
114 string ext = path.extension().string ();
115 transform (ext.begin(), ext.end(), ext.begin(), ::tolower);
117 if (valid_image_file (path)) {
118 content.reset (new ImageContent (film, path));
119 } else if (SndfileContent::valid_file (path)) {
120 content.reset (new SndfileContent (film, path));
121 } else if (ext == ".srt") {
122 content.reset (new SubRipContent (film, path));
123 } else if (ext == ".xml") {
124 content.reset (new DCPSubtitleContent (film, path));
125 } else if (ext == ".mxf" && dcp::SMPTESubtitleAsset::valid_mxf (path)) {
126 content.reset (new DCPSubtitleContent (film, path));
130 content.reset (new FFmpegContent (film, path));