Jeremy Bullock 3f5067
#include <memory></memory>
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
#include "tmachine.h"
Jeremy Bullock 3f5067
#include "tsio_mp3.h"
Jeremy Bullock 3f5067
#include "tsystem.h"
Jeremy Bullock 3f5067
#include "tfilepath_io.h"
Jeremy Bullock 3f5067
#include "tsound_t.h"
Jeremy Bullock 3f5067
#include "toonz/preferences.h"
Jeremy Bullock 3f5067
#include "toonz/toonzfolders.h"
Jeremy Bullock 3f5067
#include <qdir></qdir>
Jeremy Bullock 3f5067
#include <qprocess></qprocess>
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
//==============================================================================
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
TSoundTrackReaderMp3::TSoundTrackReaderMp3(const TFilePath &fp)
Jeremy Bullock 3f5067
    : TSoundTrackReader(fp) {}
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
//------------------------------------------------------------------------------
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
TSoundTrackP TSoundTrackReaderMp3::load() {
Jeremy Bullock 3f5067
  FfmpegAudio *ffmepegAudio = new FfmpegAudio();
Jeremy Bullock 3f5067
  TFilePath tempFile        = ffmepegAudio->getRawAudio(m_path);
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
  Tifstream is(tempFile);
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
  if (!is)
Jeremy Bullock 3f5067
    throw TException(L"Unable to load the RAW file " + m_path.getWideString() +
Jeremy Bullock 3f5067
                     L" : doesn't exist");
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
  is.seekg(0, std::ios_base::end);
Jeremy Bullock 3f5067
  long sampleCount = is.tellg() / 4;
Jeremy Bullock 3f5067
  is.seekg(0, std::ios_base::beg);
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
  TSoundTrack *track = new TSoundTrackStereo16(44100, 2, sampleCount);
Jeremy Bullock 3f5067
  is.read((char *)track->getRawData(), sampleCount * 4);
Jeremy Bullock 3f5067
  return track;
Jeremy Bullock 3f5067
}
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
bool FfmpegAudio::checkFfmpeg() {
Jeremy Bullock 3f5067
  // check the user defined path in preferences first
Jeremy Bullock 3f5067
  QString path = Preferences::instance()->getFfmpegPath() + "/ffmpeg";
Jeremy Bullock 3f5067
#if defined(_WIN32)
Jeremy Bullock 3f5067
  path = path + ".exe";
Jeremy Bullock 3f5067
#endif
Jeremy Bullock 3f5067
  if (TSystem::doesExistFileOrLevel(TFilePath(path))) return true;
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
  // check the OpenToonz root directory next
Jeremy Bullock 3f5067
  path = QDir::currentPath() + "/ffmpeg";
Jeremy Bullock 3f5067
#if defined(_WIN32)
Jeremy Bullock 3f5067
  path = path + ".exe";
Jeremy Bullock 3f5067
#endif
Jeremy Bullock 3f5067
  if (TSystem::doesExistFileOrLevel(TFilePath(path))) {
Jeremy Bullock 3f5067
    Preferences::instance()->setFfmpegPath(QDir::currentPath().toStdString());
Jeremy Bullock 3f5067
    return true;
Jeremy Bullock 3f5067
  }
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
  // give up
Jeremy Bullock 3f5067
  return false;
Jeremy Bullock 3f5067
}
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
TFilePath FfmpegAudio::getFfmpegCache() {
Jeremy Bullock 3f5067
  QString cacheRoot = ToonzFolder::getCacheRootFolder().getQString();
Jeremy Bullock 3f5067
  if (!TSystem::doesExistFileOrLevel(TFilePath(cacheRoot + "/ffmpeg"))) {
Jeremy Bullock 3f5067
    TSystem::mkDir(TFilePath(cacheRoot + "/ffmpeg"));
Jeremy Bullock 3f5067
  }
Jeremy Bullock 3f5067
  std::string ffmpegPath =
Jeremy Bullock 3f5067
      TFilePath(cacheRoot + "/ffmpeg").getQString().toStdString();
Jeremy Bullock 3f5067
  return TFilePath(cacheRoot + "/ffmpeg");
Jeremy Bullock 3f5067
}
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
void FfmpegAudio::runFfmpeg(QStringList args) {
Jeremy Bullock 3f5067
  // write the file
Jeremy Bullock 3f5067
  QString m_ffmpegPath      = Preferences::instance()->getFfmpegPath();
Jeremy Bullock 3f5067
  std::string strFfmpegPath = m_ffmpegPath.toStdString();
Jeremy Bullock 3f5067
  QProcess ffmpeg;
Jeremy Bullock 3f5067
  ffmpeg.start(m_ffmpegPath + "/ffmpeg", args);
Jeremy Bullock 3f5067
  ffmpeg.waitForFinished(30000);
Jeremy Bullock 3f5067
  QString results = ffmpeg.readAllStandardError();
Jeremy Bullock 3f5067
  results += ffmpeg.readAllStandardOutput();
Jeremy Bullock 3f5067
  int exitCode = ffmpeg.exitCode();
Jeremy Bullock 3f5067
  ffmpeg.close();
Jeremy Bullock 3f5067
  std::string strResults = results.toStdString();
Jeremy Bullock 3f5067
}
Jeremy Bullock 3f5067
Jeremy Bullock 3f5067
TFilePath FfmpegAudio::getRawAudio(TFilePath path) {
Jeremy Bullock 3f5067
  std::string name       = path.getName();
Jeremy Bullock 3f5067
  TFilePath outPath      = getFfmpegCache() + TFilePath(name + ".raw");
Jeremy Bullock 3f5067
  std::string strPath    = path.getQString().toStdString();
Jeremy Bullock 3f5067
  std::string strOutPath = outPath.getQString().toStdString();
Jeremy Bullock 3f5067
  QStringList args;
Jeremy Bullock 3f5067
  args << "-i";
Jeremy Bullock 3f5067
  args << path.getQString();
Jeremy Bullock 3f5067
  args << "-f";
Jeremy Bullock 3f5067
  args << "s16le";
Jeremy Bullock 3f5067
  args << "-ac";
Jeremy Bullock 3f5067
  args << "2";
Jeremy Bullock 3f5067
  args << "-ar";
Jeremy Bullock 3f5067
  args << "44100";
Jeremy Bullock 3f5067
  args << "-y";
Jeremy Bullock 3f5067
  args << outPath.getQString();
Jeremy Bullock 3f5067
  runFfmpeg(args);
Jeremy Bullock 3f5067
  return outPath;
Jeremy Bullock 3f5067
}