All Classes Namespaces Functions Variables Enumerations Properties Pages
soundmanager.cpp
1 /*
2 
3 Pencil2D - Traditional Animation Software
4 Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5 Copyright (C) 2012-2020 Matthew Chiawen Chang
6 
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; version 2 of the License.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 */
17 
18 #include "soundmanager.h"
19 
20 #include <QString>
21 #include <QFileInfo>
22 #include "editor.h"
23 #include "object.h"
24 #include "layersound.h"
25 #include "soundclip.h"
26 #include "soundplayer.h"
27 #include "layermanager.h"
28 
29 SoundManager::SoundManager(Editor* editor) : BaseManager(editor)
30 {
31 }
32 
33 SoundManager::~SoundManager()
34 {
35 }
36 
37 bool SoundManager::init()
38 {
39  return true;
40 }
41 
42 Status SoundManager::load(Object* obj)
43 {
44  int count = obj->getLayerCount();
45  for (int i = 0; i < count; ++i)
46  {
47  Layer* layer = obj->getLayer(i);
48  if (layer->type() != Layer::SOUND)
49  {
50  continue;
51  }
52 
53  LayerSound* soundLayer = static_cast<LayerSound*>(layer);
54 
55  soundLayer->foreachKeyFrame([this](KeyFrame* key)
56  {
57  SoundClip* clip = dynamic_cast<SoundClip*>(key);
58  Q_ASSERT(clip);
59 
60  createMediaPlayer(clip);
61  });
62  }
63  return Status::OK;
64 }
65 
66 Status SoundManager::save(Object*)
67 {
68  return Status::OK;
69 }
70 
71 Status SoundManager::loadSound(Layer* soundLayer, int frameNumber, QString strSoundFile)
72 {
73  Q_ASSERT(soundLayer);
74  if (soundLayer->type() != Layer::SOUND)
75  {
76  return Status::ERROR_INVALID_LAYER_TYPE;
77  }
78 
79  if (frameNumber < 0)
80  {
81  return Status::ERROR_INVALID_FRAME_NUMBER;
82  }
83 
84  if (!QFile::exists(strSoundFile))
85  {
86  return Status::FILE_NOT_FOUND;
87  }
88 
89  KeyFrame* key = soundLayer->getKeyFrameAt(frameNumber);
90  if (key == nullptr)
91  {
92  key = new SoundClip;
93  soundLayer->addKeyFrame(frameNumber, key);
94  }
95 
96  if (!key->fileName().isEmpty())
97  {
98  // file path should be empty.
99  // we can only load a audio clip to an empty key!
100  return Status::FAIL;
101  }
102 
103  QString strCopyFile = soundLayer->object()->copyFileToDataFolder(strSoundFile);
104  Q_ASSERT(!strCopyFile.isEmpty());
105 
106  QString sOriginalName = QFileInfo(strSoundFile).fileName();
107 
108  SoundClip* soundClip = dynamic_cast<SoundClip*>(key);
109  soundClip->init(strCopyFile);
110  soundClip->setSoundClipName(sOriginalName);
111 
112  Status st = createMediaPlayer(soundClip);
113  if (!st.ok())
114  {
115  delete soundClip;
116  return st;
117  }
118 
119  return Status::OK;
120 }
121 
122 Status SoundManager::loadSound(SoundClip* soundClip, QString strSoundFile)
123 {
124  Q_ASSERT(soundClip);
125 
126  if (!QFile::exists(strSoundFile))
127  {
128  return Status::FILE_NOT_FOUND;
129  }
130 
131  if (strSoundFile.isEmpty())
132  {
133  return Status::FAIL;
134  }
135 
136  QString strCopyFile = editor()->object()->copyFileToDataFolder(strSoundFile);
137  Q_ASSERT(!strCopyFile.isEmpty());
138 
139  soundClip->init(strCopyFile);
140  soundClip->setSoundClipName(QFileInfo(strSoundFile).fileName());
141 
142  Status st = createMediaPlayer(soundClip);
143  if (!st.ok())
144  {
145  delete soundClip;
146  return st;
147  }
148 
149  editor()->layers()->notifyAnimationLengthChanged();
150 
151  return Status::OK;
152 }
153 
154 Status SoundManager::processSound(SoundClip* soundClip)
155 {
156  Q_ASSERT(soundClip);
157 
158  if (!QFile::exists(soundClip->fileName()))
159  {
160  return Status::FILE_NOT_FOUND;
161  }
162  soundClip->init(soundClip->fileName());
163 
164  Status st = createMediaPlayer(soundClip);
165  if (!st.ok())
166  {
167  return st;
168  }
169  return Status::OK;
170 }
171 
172 void SoundManager::onDurationChanged(SoundPlayer* player, int64_t duration)
173 {
174  SoundClip* clip = player->clip();
175 
176  double fps = static_cast<double>(editor()->fps());
177 
178  double frameLength = duration * fps / 1000.0;
179  clip->setLength(static_cast<int>(frameLength));
180  clip->setDuration(duration);
181 
182  editor()->layers()->notifyAnimationLengthChanged();
183 
184  emit soundClipDurationChanged();
185 }
186 
187 Status SoundManager::createMediaPlayer(SoundClip* clip)
188 {
189  SoundPlayer* newPlayer = new SoundPlayer();
190  newPlayer->init(clip);
191 
192  connect(newPlayer, &SoundPlayer::durationChanged, this, &SoundManager::onDurationChanged);
193 
194  return Status::OK;
195 }
bool exists() const const
QString fileName() const const
bool isEmpty() const const
Definition: layer.h:39
Definition: object.h:54
Definition: editor.h:51
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)