0a4803f6e225404c4ae8998131672b357fde46a4
[dcpomatic.git] / src / lib / playlist.cc
1 /*
2     Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
3
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.
8
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.
13
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.
17
18 */
19
20 #include <boost/shared_ptr.hpp>
21 #include "playlist.h"
22 #include "sndfile_content.h"
23 #include "sndfile_decoder.h"
24 #include "ffmpeg_content.h"
25 #include "ffmpeg_decoder.h"
26 #include "imagemagick_content.h"
27 #include "imagemagick_decoder.h"
28 #include "job.h"
29
30 using std::list;
31 using std::cout;
32 using std::vector;
33 using boost::shared_ptr;
34 using boost::dynamic_pointer_cast;
35
36 Playlist::Playlist ()
37         : _video_from (VIDEO_NONE)
38         , _audio_from (AUDIO_NONE)
39 {
40
41 }
42
43 void
44 Playlist::setup (ContentList content)
45 {
46         _video_from = VIDEO_NONE;
47         _audio_from = AUDIO_NONE;
48
49         _ffmpeg.reset ();
50         _imagemagick.clear ();
51         _sndfile.clear ();
52
53         for (ContentList::const_iterator i = content.begin(); i != content.end(); ++i) {
54                 shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
55                 if (fc) {
56                         assert (!_ffmpeg);
57                         _ffmpeg = fc;
58                         _video_from = VIDEO_FFMPEG;
59                         if (_audio_from == AUDIO_NONE) {
60                                 _audio_from = AUDIO_FFMPEG;
61                         }
62                 }
63                 
64                 shared_ptr<ImageMagickContent> ic = dynamic_pointer_cast<ImageMagickContent> (*i);
65                 if (ic) {
66                         _imagemagick.push_back (ic);
67                         if (_video_from == VIDEO_NONE) {
68                                 _video_from = VIDEO_IMAGEMAGICK;
69                         }
70                 }
71
72                 shared_ptr<SndfileContent> sc = dynamic_pointer_cast<SndfileContent> (*i);
73                 if (sc) {
74                         _sndfile.push_back (sc);
75                         _audio_from = AUDIO_SNDFILE;
76                 }
77         }
78 }
79
80 ContentAudioFrame
81 Playlist::audio_length () const
82 {
83         switch (_audio_from) {
84         case AUDIO_NONE:
85                 return 0;
86         case AUDIO_FFMPEG:
87                 return _ffmpeg->audio_length ();
88         case AUDIO_SNDFILE:
89         {
90                 ContentAudioFrame l = 0;
91                 for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
92                         l += (*i)->audio_length ();
93                 }
94                 return l;
95         }
96         }
97
98         return 0;
99 }
100
101 int
102 Playlist::audio_channels () const
103 {
104         switch (_audio_from) {
105         case AUDIO_NONE:
106                 return 0;
107         case AUDIO_FFMPEG:
108                 return _ffmpeg->audio_channels ();
109         case AUDIO_SNDFILE:
110         {
111                 int c = 0;
112                 for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
113                         c += (*i)->audio_channels ();
114                 }
115                 return c;
116         }
117         }
118
119         return 0;
120 }
121
122 int
123 Playlist::audio_frame_rate () const
124 {
125         switch (_audio_from) {
126         case AUDIO_NONE:
127                 return 0;
128         case AUDIO_FFMPEG:
129                 return _ffmpeg->audio_frame_rate ();
130         case AUDIO_SNDFILE:
131                 return _sndfile.front()->audio_frame_rate ();
132         }
133
134         return 0;
135 }
136
137 int64_t
138 Playlist::audio_channel_layout () const
139 {
140         switch (_audio_from) {
141         case AUDIO_NONE:
142                 return 0;
143         case AUDIO_FFMPEG:
144                 return _ffmpeg->audio_channel_layout ();
145         case AUDIO_SNDFILE:
146                 /* XXX */
147                 return 0;
148         }
149
150         return 0;
151 }
152
153 float
154 Playlist::video_frame_rate () const
155 {
156         switch (_video_from) {
157         case VIDEO_NONE:
158                 return 0;
159         case VIDEO_FFMPEG:
160                 return _ffmpeg->video_frame_rate ();
161         case VIDEO_IMAGEMAGICK:
162                 return 24;
163         }
164
165         return 0;
166 }
167
168 libdcp::Size
169 Playlist::video_size () const
170 {
171         switch (_video_from) {
172         case VIDEO_NONE:
173                 return libdcp::Size ();
174         case VIDEO_FFMPEG:
175                 return _ffmpeg->video_size ();
176         case VIDEO_IMAGEMAGICK:
177                 /* XXX */
178                 return _imagemagick.front()->video_size ();
179         }
180
181         return libdcp::Size ();
182 }
183
184 ContentVideoFrame
185 Playlist::video_length () const
186 {
187         switch (_video_from) {
188         case VIDEO_NONE:
189                 return 0;
190         case VIDEO_FFMPEG:
191                 return _ffmpeg->video_length ();
192         case VIDEO_IMAGEMAGICK:
193         {
194                 ContentVideoFrame l = 0;
195                 for (list<shared_ptr<const ImageMagickContent> >::const_iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) {
196                         l += (*i)->video_length ();
197                 }
198                 return l;
199         }
200         }
201
202         return 0;
203 }
204
205 bool
206 Playlist::has_audio () const
207 {
208         return _audio_from != AUDIO_NONE;
209 }
210