Merge branch 'master' into content-rework-take5
[dcpomatic.git] / src / lib / sndfile_content.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 <libcxml/cxml.h>
21 #include "sndfile_content.h"
22 #include "sndfile_decoder.h"
23 #include "compose.hpp"
24 #include "job.h"
25
26 #include "i18n.h"
27
28 using std::string;
29 using std::stringstream;
30 using std::cout;
31 using boost::shared_ptr;
32 using boost::lexical_cast;
33
34 SndfileContent::SndfileContent (boost::filesystem::path f)
35         : Content (f)
36         , AudioContent (f)
37         , _audio_channels (0)
38         , _audio_length (0)
39         , _audio_frame_rate (0)
40 {
41
42 }
43
44 SndfileContent::SndfileContent (shared_ptr<const cxml::Node> node)
45         : Content (node)
46         , AudioContent (node)
47 {
48         _audio_channels = node->number_child<int> ("AudioChannels");
49         _audio_length = node->number_child<ContentAudioFrame> ("AudioLength");
50         _audio_frame_rate = node->number_child<int> ("AudioFrameRate");
51 }
52
53 string
54 SndfileContent::summary () const
55 {
56         return String::compose (_("Sound file: %1"), file().filename().string());
57 }
58
59 string
60 SndfileContent::information () const
61 {
62         if (_audio_frame_rate == 0) {
63                 return "";
64         }
65         
66         stringstream s;
67
68         s << String::compose (
69                 _("%1 channels, %2kHz, %3 samples"),
70                 audio_channels(),
71                 audio_frame_rate() / 1000.0,
72                 audio_length()
73                 );
74         
75         return s.str ();
76 }
77
78 bool
79 SndfileContent::valid_file (boost::filesystem::path f)
80 {
81         /* XXX: more extensions */
82         string ext = f.extension().string();
83         transform (ext.begin(), ext.end(), ext.begin(), ::tolower);
84         return (ext == ".wav" || ext == ".aif" || ext == ".aiff");
85 }
86
87 shared_ptr<Content>
88 SndfileContent::clone () const
89 {
90         return shared_ptr<Content> (new SndfileContent (*this));
91 }
92
93 void
94 SndfileContent::examine (shared_ptr<Film> film, shared_ptr<Job> job, bool quick)
95 {
96         job->set_progress_unknown ();
97         Content::examine (film, job, quick);
98
99         SndfileDecoder dec (film, shared_from_this());
100
101         {
102                 boost::mutex::scoped_lock lm (_mutex);
103                 _audio_channels = dec.audio_channels ();
104                 _audio_length = dec.audio_length ();
105                 _audio_frame_rate = dec.audio_frame_rate ();
106         }
107
108         signal_changed (AudioContentProperty::AUDIO_CHANNELS);
109         signal_changed (AudioContentProperty::AUDIO_LENGTH);
110         signal_changed (AudioContentProperty::AUDIO_FRAME_RATE);
111 }
112
113 void
114 SndfileContent::as_xml (xmlpp::Node* node) const
115 {
116         node->add_child("Type")->add_child_text ("Sndfile");
117         Content::as_xml (node);
118         node->add_child("AudioChannels")->add_child_text (lexical_cast<string> (_audio_channels));
119         node->add_child("AudioLength")->add_child_text (lexical_cast<string> (_audio_length));
120         node->add_child("AudioFrameRate")->add_child_text (lexical_cast<string> (_audio_frame_rate));
121 }
122