justburner 64e039
#include "thirdparty.h"
justburner 64e039
justburner 64e039
// TnzLib includes
justburner 64e039
#include "toonz/preferences.h"
justburner 64e039
justburner 64e039
// TnzCore includes
justburner 64e039
#include "tsystem.h"
justburner 64e039
#include "tmsgcore.h"
justburner 64e039
justburner 64e039
// QT includes
justburner 64e039
#include <qcoreapplication></qcoreapplication>
justburner 64e039
#include <qeventloop></qeventloop>
justburner 64e039
#include <qtimer></qtimer>
justburner 64e039
justburner 64e039
namespace ThirdParty {
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void initialize() {
justburner 64e039
  // Auto detect FFmpeg
justburner 64e039
  if (!ThirdParty::checkFFmpeg()) {
justburner 64e039
    QString path = ThirdParty::autodetectFFmpeg();
justburner 64e039
    if (!path.isEmpty()) ThirdParty::setFFmpegDir(path);
justburner 64e039
  }
justburner 64e039
justburner 64e039
  // Auto detect Rhubarb
justburner 64e039
  if (!ThirdParty::checkRhubarb()) {
justburner 64e039
    QString path = ThirdParty::autodetectRhubarb();
justburner 64e039
    if (!path.isEmpty()) ThirdParty::setRhubarbDir(path);
justburner 64e039
  }
justburner 64e039
}
justburner 64e039
justburner 64e039
//=============================================================================
justburner 64e039
// FFmpeg interface
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
#ifdef _WIN32
justburner 64e039
#define FFMPEG_EXE "/ffmpeg.exe"
justburner 64e039
#define FFPROBE_EXE "/ffprobe.exe"
justburner 64e039
#else
justburner 64e039
#define FFMPEG_EXE "/ffmpeg"
justburner 64e039
#define FFPROBE_EXE "/ffprobe"
justburner 64e039
#endif
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void getFFmpegVideoSupported(QStringList &exts) {
justburner 64e039
  exts.append("gif");
justburner 64e039
  exts.append("mp4");
justburner 64e039
  exts.append("webm");
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void getFFmpegAudioSupported(QStringList &exts) {
justburner 64e039
  exts.append("mp3");
justburner 64e039
  exts.append("ogg");
justburner 64e039
  exts.append("flac");
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
bool findFFmpeg(QString dir) {
justburner 64e039
  // Relative path
justburner 64e039
  if (dir.isEmpty() || dir.at(0) == ".") {
justburner 64e039
    dir = QCoreApplication::applicationDirPath() + "/" + dir;
justburner 64e039
  }
justburner 64e039
justburner 64e039
  // Check if both executables exist
justburner 64e039
  return TSystem::doesExistFileOrLevel(TFilePath(dir + FFMPEG_EXE)) &&
justburner 64e039
         TSystem::doesExistFileOrLevel(TFilePath(dir + FFPROBE_EXE));
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
bool checkFFmpeg() {
justburner 64e039
  // Path in preferences
justburner 64e039
  return findFFmpeg(Preferences::instance()->getFfmpegPath());
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
QString autodetectFFmpeg() {
justburner 64e039
  QString dir = Preferences::instance()->getFfmpegPath();
justburner 64e039
  if (findFFmpeg(dir)) return dir;
justburner 64e039
justburner 64e039
  if (findFFmpeg(".")) return ".";
justburner 64e039
  if (findFFmpeg("./ffmpeg")) return "./ffmpeg";
justburner 64e039
  if (findFFmpeg("./ffmpeg/bin")) return "./ffmpeg/bin";
justburner 64e039
  if (findFFmpeg("./FFmpeg")) return "./FFmpeg";
justburner 64e039
  if (findFFmpeg("./FFmpeg/bin")) return "./FFmpeg/bin";
justburner 64e039
justburner 64e039
#ifndef _WIN32
justburner 64e039
  if (findFFmpeg("/usr/local/bin")) return "/usr/local/bin";
justburner 64e039
  if (findFFmpeg("/usr/bin")) return "/usr/bin";
justburner 64e039
  if (findFFmpeg("/bin")) return "/bin";
justburner 64e039
#endif
justburner 64e039
justburner 64e039
  return "";
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
QString getFFmpegDir() {
justburner 64e039
  return Preferences::instance()->getStringValue(ffmpegPath);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void setFFmpegDir(const QString &dir) {
justburner 64e039
  QString path = Preferences::instance()->getFfmpegPath();
justburner 64e039
  if (path != dir) Preferences::instance()->setValue(ffmpegPath, dir);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
int getFFmpegTimeout() {
justburner 64e039
  return Preferences::instance()->getIntValue(ffmpegTimeout);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void setFFmpegTimeout(int secs) {
justburner 64e039
  int timeout = Preferences::instance()->getIntValue(ffmpegTimeout);
justburner 64e039
  if (secs != timeout) Preferences::instance()->setValue(ffmpegTimeout, secs);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void runFFmpeg(QProcess &process, const QStringList &arguments) {
justburner 64e039
  QString dir = Preferences::instance()->getFfmpegPath();
justburner 64e039
  if (dir.at(0) == '.')  // Relative path
justburner 64e039
    dir = QCoreApplication::applicationDirPath() + "/" + dir;
justburner 64e039
justburner 64e039
  process.start(dir + FFMPEG_EXE, arguments);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void runFFprobe(QProcess &process, const QStringList &arguments) {
justburner 64e039
  QString dir = Preferences::instance()->getFfmpegPath();
justburner 64e039
  if (dir.at(0) == '.')  // Relative path
justburner 64e039
    dir = QCoreApplication::applicationDirPath() + "/" + dir;
justburner 64e039
justburner 64e039
  process.start(dir + FFPROBE_EXE, arguments);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void runFFmpegAudio(QProcess &process, QString srcPath, QString dstPath,
justburner 64e039
                    int samplerate, int bpp, int channels) {
justburner 64e039
  QStringList args;
justburner 64e039
  args << "-y";
justburner 64e039
  args << "-i";
justburner 64e039
  args << srcPath;
justburner 64e039
  args << "-f";
justburner 64e039
  switch (bpp) {
justburner 64e039
  case 8:  // unsigned
justburner 64e039
    args << "u8";
justburner 64e039
    break;
justburner 64e039
  case 16:
justburner 64e039
    args << "s16le";
justburner 64e039
    break;
justburner 64e039
  case 24:
justburner 64e039
    args << "s24le";
justburner 64e039
    break;
justburner 64e039
  case 32:  // floating-point
justburner 64e039
    args << "f32le";
justburner 64e039
    break;
justburner 64e039
  default:
justburner 64e039
    return;
justburner 64e039
  }
justburner 64e039
  args << "-ac";
justburner 64e039
  args << QString::number(channels);
justburner 64e039
  args << "-ar";
justburner 64e039
  args << QString::number(samplerate);
justburner 64e039
  args << dstPath;
justburner 64e039
justburner 64e039
  ThirdParty::runFFmpeg(process, args);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
bool readFFmpegAudio(QProcess &process, QByteArray &rawData) {
justburner 64e039
  if (!process.waitForStarted()) return false;
justburner 64e039
  if (!process.waitForFinished(30000)) return false;
justburner 64e039
  bool success = (process.exitCode() == 0);
justburner 64e039
justburner 64e039
  if (success) rawData = process.readAllStandardOutput();
justburner 64e039
  process.close();
justburner 64e039
justburner 64e039
  return success;
justburner 64e039
}
justburner 64e039
justburner 64e039
//=============================================================================
justburner 64e039
// Rhubarb interface
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
#ifdef _WIN32
justburner 64e039
#define RHUBARB_EXE "/rhubarb.exe"
justburner 64e039
#else
justburner 64e039
#define RHUBARB_EXE "/rhubarb"
justburner 64e039
#endif
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
bool findRhubarb(QString dir) {
justburner 64e039
  // Rhubarb executable
justburner 64e039
justburner 64e039
  // Relative path
justburner 64e039
  if (dir.isEmpty() || dir.at(0) == ".") {
justburner 64e039
    dir = QCoreApplication::applicationDirPath() + "/" + dir;
justburner 64e039
  }
justburner 64e039
justburner 64e039
  // Check if executable exist
justburner 64e039
  return TSystem::doesExistFileOrLevel(TFilePath(dir + RHUBARB_EXE));
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
bool checkRhubarb() {
justburner 64e039
  // Path in preferences
justburner 64e039
  return findRhubarb(Preferences::instance()->getRhubarbPath());
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
QString autodetectRhubarb() {
justburner 64e039
  QString dir = Preferences::instance()->getRhubarbPath();
justburner 64e039
  if (findRhubarb(dir)) return dir;
justburner 64e039
justburner 64e039
  if (findRhubarb(".")) return ".";
justburner 64e039
  if (findRhubarb("./rhubarb")) return "./rhubarb";
justburner 64e039
  if (findRhubarb("./rhubarb/bin")) return "./rhubarb/bin";
justburner 64e039
  if (findRhubarb("./Rhubarb-Lip-Sync")) return "./Rhubarb-Lip-Sync";
justburner 64e039
justburner 64e039
#ifndef _WIN32
justburner 64e039
  if (findRhubarb("/usr/local/bin")) return "/usr/local/bin";
justburner 64e039
  if (findRhubarb("/usr/bin")) return "/usr/bin";
justburner 64e039
  if (findRhubarb("/bin")) return "/bin";
justburner 64e039
#endif
justburner 64e039
justburner 64e039
  return "";
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void runRhubarb(QProcess &process, const QStringList &arguments) {
justburner 64e039
  QString dir = Preferences::instance()->getRhubarbPath();
justburner 64e039
  if (dir.at(0) == '.')  // Relative path
justburner 64e039
    dir = QCoreApplication::applicationDirPath() + "/" + dir;
justburner 64e039
justburner 64e039
  process.start(dir + RHUBARB_EXE, arguments);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
QString getRhubarbDir() {
justburner 64e039
  return Preferences::instance()->getStringValue(rhubarbPath);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void setRhubarbDir(const QString &dir) {
justburner 64e039
  QString path = Preferences::instance()->getRhubarbPath();
justburner 64e039
  if (path != dir) Preferences::instance()->setValue(rhubarbPath, dir);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
int getRhubarbTimeout() {
justburner 64e039
  return Preferences::instance()->getIntValue(rhubarbTimeout);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
void setRhubarbTimeout(int secs) {
justburner 64e039
  int timeout = Preferences ::instance()->getIntValue(rhubarbTimeout);
justburner 64e039
  if (secs != timeout) Preferences::instance()->setValue(rhubarbTimeout, secs);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
int waitAsyncProcess(const QProcess &process, int timeout) {
justburner 64e039
  QEventLoop eloop;
justburner 64e039
  QTimer timer;
justburner 64e039
  timer.connect(&timer, &QTimer::timeout, &eloop, [&eloop] { eloop.exit(-2); });
justburner 64e039
  QMetaObject::Connection con1 = process.connect(
justburner 64e039
      &process, &QProcess::errorOccurred, &eloop, [&eloop] { eloop.exit(-1); });
justburner 64e039
  QMetaObject::Connection con2 = process.connect(
justburner 64e039
      &process,
justburner 64e039
      static_cast<void (qprocess::*)(int,="" qprocess::exitstatus)="">(</void>
justburner 64e039
          &QProcess::finished),
justburner 64e039
      &eloop, &QEventLoop::quit);
justburner 64e039
  if (timeout >= 0) timer.start(timeout);
justburner 64e039
justburner 64e039
  int result = eloop.exec();
justburner 64e039
  process.disconnect(con1);
justburner 64e039
  process.disconnect(con2);
justburner 64e039
justburner 64e039
  return result;
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------------------------
justburner 64e039
justburner 64e039
}  // namespace ThirdParty