All Classes Namespaces Functions Variables Enumerations Properties Pages
layersound.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 #include "layersound.h"
18 
19 #include <QDebug>
20 #include <QMediaPlayer>
21 #include <QFileInfo>
22 #include <QDir>
23 #include "object.h"
24 #include "soundclip.h"
25 
26 
27 LayerSound::LayerSound(Object* object) : Layer(object, Layer::SOUND)
28 {
29  setName(tr("Sound Layer"));
30 }
31 
32 LayerSound::~LayerSound()
33 {
34 }
35 
36 Status LayerSound::loadSoundClipAtFrame(const QString& sSoundClipName,
37  const QString& strFilePath,
38  int frameNumber)
39 {
40  if (!QFile::exists(strFilePath))
41  {
42  return Status::FILE_NOT_FOUND;
43  }
44 
45  QFileInfo info(strFilePath);
46  if (!info.isFile())
47  {
48  return Status::ERROR_LOAD_SOUND_FILE;
49  }
50 
51  SoundClip* clip = new SoundClip;
52  clip->setSoundClipName(sSoundClipName);
53  clip->init(strFilePath);
54  clip->setPos(frameNumber);
55  loadKey(clip);
56  return Status::OK;
57 }
58 
59 void LayerSound::updateFrameLengths(int fps)
60 {
61  foreachKeyFrame([&fps](KeyFrame* pKeyFrame)
62  {
63  auto soundClip = dynamic_cast<SoundClip *>(pKeyFrame);
64  soundClip->updateLength(fps);
65  });
66 }
67 
68 QDomElement LayerSound::createDomElement(QDomDocument& doc) const
69 {
70  QDomElement layerElem = createBaseDomElement(doc);
71 
72  foreachKeyFrame([&doc, &layerElem](KeyFrame* pKeyFrame)
73  {
74  SoundClip* clip = static_cast<SoundClip*>(pKeyFrame);
75 
76  QDomElement imageTag = doc.createElement("sound");
77  imageTag.setAttribute("frame", clip->pos());
78  imageTag.setAttribute("name", clip->soundClipName());
79 
80  QFileInfo info(clip->fileName());
81  //qDebug() << "Save=" << info.fileName();
82  imageTag.setAttribute("src", info.fileName());
83  layerElem.appendChild(imageTag);
84  });
85 
86  return layerElem;
87 }
88 
89 void LayerSound::loadDomElement(const QDomElement& element, QString dataDirPath, ProgressCallback progressStep)
90 {
91  this->loadBaseDomElement(element);
92 
93  QDomNode soundTag = element.firstChild();
94  while (!soundTag.isNull())
95  {
96  QDomElement soundElement = soundTag.toElement();
97  if (soundElement.isNull())
98  {
99  continue;
100  }
101 
102  if (soundElement.tagName() == "sound")
103  {
104  const QString soundFile = soundElement.attribute("src");
105  const QString sSoundClipName = soundElement.attribute("name", "My Sound Clip");
106 
107  if (!soundFile.isEmpty())
108  {
109  // the file is supposed to be in the data directory
110  const QString sFullPath = QDir(dataDirPath).filePath(soundFile);
111 
112  int position = soundElement.attribute("frame").toInt();
113  Status st = loadSoundClipAtFrame(sSoundClipName, sFullPath, position);
114  Q_ASSERT(st.ok());
115  }
116  progressStep();
117  }
118 
119  soundTag = soundTag.nextSibling();
120  }
121 }
122 
123 Status LayerSound::saveKeyFrameFile(KeyFrame* key, QString path)
124 {
125  Q_ASSERT(key);
126 
127  if (key->fileName().isEmpty())
128  {
129  return Status::SAFE;
130  }
131 
132  QFileInfo info(key->fileName());
133  QString sDestFileLocation = QDir(path).filePath(info.fileName());
134 
135  if (sDestFileLocation != key->fileName())
136  {
137  if (QFile::exists(sDestFileLocation))
138  QFile::remove(sDestFileLocation);
139 
140  bool ok = QFile::copy(key->fileName(), sDestFileLocation);
141  if (!ok)
142  {
143  key->setFileName("");
144 
145  DebugDetails dd;
146  dd << __FUNCTION__;
147  dd << QString(" KeyFrame.pos() = %1").arg(key->pos());
148  dd << QString(" Key->fileName() = %1").arg(key->fileName());
149  dd << QString(" FilePath = %1").arg(sDestFileLocation);
150  dd << QString("Couldn't save the sound clip");
151  return Status(Status::FAIL, dd);
152  }
153  key->setFileName(sDestFileLocation);
154  }
155  return Status::OK;
156 }
157 
158 KeyFrame* LayerSound::createKeyFrame(int position, Object*)
159 {
160  SoundClip* s = new SoundClip;
161  s->setPos(position);
162  return s;
163 }
164 
165 SoundClip* LayerSound::getSoundClipWhichCovers(int frameNumber)
166 {
167  KeyFrame* key = getKeyFrameWhichCovers(frameNumber);
168  return static_cast<SoundClip*>(key);
169 }
QDomNode appendChild(const QDomNode &newChild)
QString attribute(const QString &name, const QString &defValue) const const
bool remove()
QString filePath(const QString &fileName) const const
bool exists() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool copy(const QString &newName)
QDomNode nextSibling() const const
QDomElement toElement() const const
void setAttribute(const QString &name, const QString &value)
int toInt(bool *ok, int base) const const
bool isEmpty() const const
Definition: layer.h:38
bool isNull() const const
QDomNode firstChild() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
Definition: object.h:41
QString tagName() const const
QDomElement createElement(const QString &tagName)