<commit_before>/* This file is part of the KDE project
   Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "kwrite.h"

#include <ktexteditor/document.h>
#include <ktexteditor/view.h>
#include <ktexteditor/editor.h>

#include <KAboutData>
#include <KLocalizedString>
#include <KMessageBox>
#include <KDBusService>

#include <QCommandLineParser>
#include <QLoggingCategory>
#include <QApplication>
#include <QTextCodec>
#include <QFileInfo>
#include <QDir>

Q_DECLARE_LOGGING_CATEGORY(LOG_KWRITE)
Q_LOGGING_CATEGORY(LOG_KWRITE, "kwrite")

extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv)
{
  QLoggingCategory::setFilterRules(QStringLiteral("kwrite = true"));

  KAboutData aboutData ( QLatin1String("kwrite"), QString(),
                         i18n("KWrite"),
                         QLatin1String(KATE_VERSION),
                         i18n( "KWrite - Text Editor" ), KAboutData::License_LGPL_V2,
                         i18n( "(c) 2000-2014 The Kate Authors" ), QString(), QLatin1String("http://kate-editor.org") );

  /**
   * right dbus prefix == org.kde.
   */
  aboutData.setOrganizationDomain (QByteArray("kde.org"));

  aboutData.addAuthor (i18n("Christoph Cullmann"), i18n("Maintainer"), QLatin1String("cullmann@kde.org"), QLatin1String("http://www.cullmann.io"));
  aboutData.addAuthor (i18n("Anders Lund"), i18n("Core Developer"), QLatin1String("anders@alweb.dk"), QLatin1String("http://www.alweb.dk"));
  aboutData.addAuthor (i18n("Joseph Wenninger"), i18n("Core Developer"), QLatin1String("jowenn@kde.org"), QLatin1String("http://stud3.tuwien.ac.at/~e9925371"));
  aboutData.addAuthor (i18n("Hamish Rodda"),i18n("Core Developer"), QLatin1String("rodda@kde.org"));
  aboutData.addAuthor (i18n("Dominik Haumann"), i18n("Developer & Highlight wizard"), QLatin1String("dhdev@gmx.de"));
  aboutData.addAuthor (i18n("Waldo Bastian"), i18n("The cool buffersystem"), QLatin1String("bastian@kde.org") );
  aboutData.addAuthor (i18n("Charles Samuels"), i18n("The Editing Commands"), QLatin1String("charles@kde.org"));
  aboutData.addAuthor (i18n("Matt Newell"), i18nc("Credit text for someone that did testing and some other similar things", "Testing, ..."), QLatin1String("newellm@proaxis.com"));
  aboutData.addAuthor (i18n("Michael Bartl"), i18n("Former Core Developer"), QLatin1String("michael.bartl1@chello.at"));
  aboutData.addAuthor (i18n("Michael McCallum"), i18n("Core Developer"), QLatin1String("gholam@xtra.co.nz"));
  aboutData.addAuthor (i18n("Jochen Wilhemly"), i18n("KWrite Author"), QLatin1String("digisnap@cs.tu-berlin.de") );
  aboutData.addAuthor (i18n("Michael Koch"),i18n("KWrite port to KParts"), QLatin1String("koch@kde.org"));
  aboutData.addAuthor (i18n("Christian Gebauer"), QString(), QLatin1String("gebauer@kde.org") );
  aboutData.addAuthor (i18n("Simon Hausmann"), QString(), QLatin1String("hausmann@kde.org") );
  aboutData.addAuthor (i18n("Glen Parker"),i18n("KWrite Undo History, Kspell integration"), QLatin1String("glenebob@nwlink.com"));
  aboutData.addAuthor (i18n("Scott Manson"),i18n("KWrite XML Syntax highlighting support"), QLatin1String("sdmanson@alltel.net"));
  aboutData.addAuthor (i18n("John Firebaugh"),i18n("Patches and more"), QLatin1String("jfirebaugh@kde.org"));
  aboutData.addAuthor (i18n("Gerald Senarclens de Grancy"), i18n("QA and Scripting"), QLatin1String("oss@senarclens.eu"), QLatin1String("http://find-santa.eu/"));

  aboutData.addCredit (i18n("Matteo Merli"),i18n("Highlighting for RPM Spec-Files, Perl, Diff and more"), QLatin1String("merlim@libero.it"));
  aboutData.addCredit (i18n("Rocky Scaletta"),i18n("Highlighting for VHDL"), QLatin1String("rocky@purdue.edu"));
  aboutData.addCredit (i18n("Yury Lebedev"),i18n("Highlighting for SQL"));
  aboutData.addCredit (i18n("Chris Ross"),i18n("Highlighting for Ferite"));
  aboutData.addCredit (i18n("Nick Roux"),i18n("Highlighting for ILERPG"));
  aboutData.addCredit (i18n("Carsten Niehaus"), i18n("Highlighting for LaTeX"));
  aboutData.addCredit (i18n("Per Wigren"), i18n("Highlighting for Makefiles, Python"));
  aboutData.addCredit (i18n("Jan Fritz"), i18n("Highlighting for Python"));
  aboutData.addCredit (i18n("Daniel Naber"));
  aboutData.addCredit (i18n("Roland Pabel"),i18n("Highlighting for Scheme"));
  aboutData.addCredit (i18n("Cristi Dumitrescu"),i18n("PHP Keyword/Datatype list"));
  aboutData.addCredit (i18n("Carsten Pfeiffer"), i18nc("Credit text for someone that helped a lot", "Very nice help"));
  aboutData.addCredit (i18n("All people who have contributed and I have forgotten to mention"));

  aboutData.setProgramIconName (QLatin1String("accessories-text-editor"));
  aboutData.setProductName(QByteArray("kate/kwrite"));

  /**
   * register about data
   */
  KAboutData::setApplicationData (aboutData);

  /**
   * Create the QApplication with the right options set
   * take component name and org. name from KAboutData
   */
  QApplication app (argc, argv);
  app.setApplicationName (aboutData.componentName());
  app.setApplicationDisplayName (aboutData.displayName());
  app.setOrganizationDomain (aboutData.organizationDomain());
  app.setApplicationVersion (aboutData.version());

  /**
   * Create command line parser and feed it with known options
   */
  QCommandLineParser parser;
  parser.setApplicationDescription(aboutData.shortDescription());
  parser.addHelpOption();
  parser.addVersionOption();

  // -e/--encoding option
  const QCommandLineOption useEncoding (QStringList () << QLatin1String("e") << QLatin1String("encoding"), i18n("Set encoding for the file to open."), QLatin1String("encoding"));
  parser.addOption (useEncoding);

  // -l/--line option
  const QCommandLineOption gotoLine (QStringList () << QLatin1String("l") << QLatin1String("line"), i18n("Navigate to this line."), QLatin1String("line"));
  parser.addOption (gotoLine);

  // -c/--column option
  const QCommandLineOption gotoColumn (QStringList () << QLatin1String("c") << QLatin1String("column"), i18n("Navigate to this column."), QLatin1String("column"));
  parser.addOption (gotoColumn);

  // -i/--stdin option
  const QCommandLineOption readStdIn (QStringList () << QLatin1String("i") << QLatin1String("stdin"), i18n("Read the contents of stdin."));
  parser.addOption (readStdIn);

  // --tempfile option
  const QCommandLineOption tempfile (QStringList () << QLatin1String("tempfile"), i18n("The files/URLs opened by the application will be deleted after use"));
  parser.addOption (tempfile);

  // urls to open
  parser.addPositionalArgument(QLatin1String("urls"), i18n("Documents to open."), QLatin1String("[urls...]"));

  /**
   * do the command line parsing
   */
  parser.process (app);

  // read from global config once
  KTextEditor::Editor::instance()->readConfig(KSharedConfig::openConfig().data());

  if ( app.isSessionRestored() )
  {
    KWrite::restore();
  }
  else
  {
    bool nav = false;
    int line = 0, column = 0;

    QTextCodec *codec = parser.isSet(QLatin1String("encoding")) ? QTextCodec::codecForName(parser.value(QLatin1String("encoding")).toLocal8Bit()) : 0;

    if (parser.isSet (QLatin1String("line")))
    {
      line = parser.value (QLatin1String("line")).toInt() - 1;
      nav = true;
    }

    if (parser.isSet (QLatin1String("column")))
    {
      column = parser.value (QLatin1String("column")).toInt() - 1;
      nav = true;
    }

    if ( parser.positionalArguments().count() == 0 )
    {
        KWrite *t = new KWrite;

        if( parser.isSet( QLatin1String("stdin") ) )
        {
          QTextStream input(stdin, QIODevice::ReadOnly);

          // set chosen codec
          if (codec)
            input.setCodec (codec);

          QString line;
          QString text;

          do
          {
            line = input.readLine();
            text.append( line + QLatin1Char('\n') );
          } while( !line.isNull() );

          KTextEditor::Document *doc = t->view()->document();
          if( doc )
              doc->setText( text );
        }

        if (nav && t->view())
          t->view()->setCursorPosition (KTextEditor::Cursor (line, column));
    }
    else
    {
      int docs_opened = 0;
      Q_FOREACH (const QString positionalArgument, parser.positionalArguments())
      {
        QUrl url;

        // convert to an url
        QRegExp withProtocol(QLatin1String("^[a-zA-Z]+:")); // TODO: remove after Qt supports this on its own
        if (withProtocol.indexIn(positionalArgument) == 0) {
          url = QUrl::fromUserInput(positionalArgument);
        } else {
          url = QUrl::fromLocalFile(positionalArgument);
        }

        // this file is no local dir, open it, else warn
        bool noDir = !url.isLocalFile() || !QFileInfo (url.toLocalFile()).isDir();

        if (noDir)
        {
          ++docs_opened;
          KWrite *t = new KWrite();

          if (codec)
            t->view()->document()->setEncoding(QString::fromLatin1(codec->name()));

          t->loadURL( url );

          if (nav)
            t->view()->setCursorPosition (KTextEditor::Cursor (line, column));
        }
        else
        {
          KMessageBox::sorry(0, i18n("The file '%1' could not be opened: it is not a normal file, it is a folder.", url.toString()));
        }
      }
      if (!docs_opened) ::exit(1); // see http://bugs.kde.org/show_bug.cgi?id=124708
    }
  }

  // no window there, uh, ohh, for example borked session config !!!
  // create at least one !!
  if (KWrite::noWindows())
    new KWrite();

  /**
   * finally register this kwrite instance for dbus
   */
  const KDBusService dbusService (KDBusService::Multiple);

  /**
   * Run the event loop
   */
  return app.exec ();
}
<commit_msg>no logging stuff used here<commit_after>/* This file is part of the KDE project
   Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "kwrite.h"

#include <ktexteditor/document.h>
#include <ktexteditor/view.h>
#include <ktexteditor/editor.h>

#include <KAboutData>
#include <KLocalizedString>
#include <KMessageBox>
#include <KDBusService>

#include <QCommandLineParser>
#include <QApplication>
#include <QTextCodec>
#include <QFileInfo>
#include <QDir>

extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv)
{
  KAboutData aboutData ( QLatin1String("kwrite"), QString(),
                         i18n("KWrite"),
                         QLatin1String(KATE_VERSION),
                         i18n( "KWrite - Text Editor" ), KAboutData::License_LGPL_V2,
                         i18n( "(c) 2000-2014 The Kate Authors" ), QString(), QLatin1String("http://kate-editor.org") );

  /**
   * right dbus prefix == org.kde.
   */
  aboutData.setOrganizationDomain (QByteArray("kde.org"));

  aboutData.addAuthor (i18n("Christoph Cullmann"), i18n("Maintainer"), QLatin1String("cullmann@kde.org"), QLatin1String("http://www.cullmann.io"));
  aboutData.addAuthor (i18n("Anders Lund"), i18n("Core Developer"), QLatin1String("anders@alweb.dk"), QLatin1String("http://www.alweb.dk"));
  aboutData.addAuthor (i18n("Joseph Wenninger"), i18n("Core Developer"), QLatin1String("jowenn@kde.org"), QLatin1String("http://stud3.tuwien.ac.at/~e9925371"));
  aboutData.addAuthor (i18n("Hamish Rodda"),i18n("Core Developer"), QLatin1String("rodda@kde.org"));
  aboutData.addAuthor (i18n("Dominik Haumann"), i18n("Developer & Highlight wizard"), QLatin1String("dhdev@gmx.de"));
  aboutData.addAuthor (i18n("Waldo Bastian"), i18n("The cool buffersystem"), QLatin1String("bastian@kde.org") );
  aboutData.addAuthor (i18n("Charles Samuels"), i18n("The Editing Commands"), QLatin1String("charles@kde.org"));
  aboutData.addAuthor (i18n("Matt Newell"), i18nc("Credit text for someone that did testing and some other similar things", "Testing, ..."), QLatin1String("newellm@proaxis.com"));
  aboutData.addAuthor (i18n("Michael Bartl"), i18n("Former Core Developer"), QLatin1String("michael.bartl1@chello.at"));
  aboutData.addAuthor (i18n("Michael McCallum"), i18n("Core Developer"), QLatin1String("gholam@xtra.co.nz"));
  aboutData.addAuthor (i18n("Jochen Wilhemly"), i18n("KWrite Author"), QLatin1String("digisnap@cs.tu-berlin.de") );
  aboutData.addAuthor (i18n("Michael Koch"),i18n("KWrite port to KParts"), QLatin1String("koch@kde.org"));
  aboutData.addAuthor (i18n("Christian Gebauer"), QString(), QLatin1String("gebauer@kde.org") );
  aboutData.addAuthor (i18n("Simon Hausmann"), QString(), QLatin1String("hausmann@kde.org") );
  aboutData.addAuthor (i18n("Glen Parker"),i18n("KWrite Undo History, Kspell integration"), QLatin1String("glenebob@nwlink.com"));
  aboutData.addAuthor (i18n("Scott Manson"),i18n("KWrite XML Syntax highlighting support"), QLatin1String("sdmanson@alltel.net"));
  aboutData.addAuthor (i18n("John Firebaugh"),i18n("Patches and more"), QLatin1String("jfirebaugh@kde.org"));
  aboutData.addAuthor (i18n("Gerald Senarclens de Grancy"), i18n("QA and Scripting"), QLatin1String("oss@senarclens.eu"), QLatin1String("http://find-santa.eu/"));

  aboutData.addCredit (i18n("Matteo Merli"),i18n("Highlighting for RPM Spec-Files, Perl, Diff and more"), QLatin1String("merlim@libero.it"));
  aboutData.addCredit (i18n("Rocky Scaletta"),i18n("Highlighting for VHDL"), QLatin1String("rocky@purdue.edu"));
  aboutData.addCredit (i18n("Yury Lebedev"),i18n("Highlighting for SQL"));
  aboutData.addCredit (i18n("Chris Ross"),i18n("Highlighting for Ferite"));
  aboutData.addCredit (i18n("Nick Roux"),i18n("Highlighting for ILERPG"));
  aboutData.addCredit (i18n("Carsten Niehaus"), i18n("Highlighting for LaTeX"));
  aboutData.addCredit (i18n("Per Wigren"), i18n("Highlighting for Makefiles, Python"));
  aboutData.addCredit (i18n("Jan Fritz"), i18n("Highlighting for Python"));
  aboutData.addCredit (i18n("Daniel Naber"));
  aboutData.addCredit (i18n("Roland Pabel"),i18n("Highlighting for Scheme"));
  aboutData.addCredit (i18n("Cristi Dumitrescu"),i18n("PHP Keyword/Datatype list"));
  aboutData.addCredit (i18n("Carsten Pfeiffer"), i18nc("Credit text for someone that helped a lot", "Very nice help"));
  aboutData.addCredit (i18n("All people who have contributed and I have forgotten to mention"));

  aboutData.setProgramIconName (QLatin1String("accessories-text-editor"));
  aboutData.setProductName(QByteArray("kate/kwrite"));

  /**
   * register about data
   */
  KAboutData::setApplicationData (aboutData);

  /**
   * Create the QApplication with the right options set
   * take component name and org. name from KAboutData
   */
  QApplication app (argc, argv);
  app.setApplicationName (aboutData.componentName());
  app.setApplicationDisplayName (aboutData.displayName());
  app.setOrganizationDomain (aboutData.organizationDomain());
  app.setApplicationVersion (aboutData.version());

  /**
   * Create command line parser and feed it with known options
   */
  QCommandLineParser parser;
  parser.setApplicationDescription(aboutData.shortDescription());
  parser.addHelpOption();
  parser.addVersionOption();

  // -e/--encoding option
  const QCommandLineOption useEncoding (QStringList () << QLatin1String("e") << QLatin1String("encoding"), i18n("Set encoding for the file to open."), QLatin1String("encoding"));
  parser.addOption (useEncoding);

  // -l/--line option
  const QCommandLineOption gotoLine (QStringList () << QLatin1String("l") << QLatin1String("line"), i18n("Navigate to this line."), QLatin1String("line"));
  parser.addOption (gotoLine);

  // -c/--column option
  const QCommandLineOption gotoColumn (QStringList () << QLatin1String("c") << QLatin1String("column"), i18n("Navigate to this column."), QLatin1String("column"));
  parser.addOption (gotoColumn);

  // -i/--stdin option
  const QCommandLineOption readStdIn (QStringList () << QLatin1String("i") << QLatin1String("stdin"), i18n("Read the contents of stdin."));
  parser.addOption (readStdIn);

  // --tempfile option
  const QCommandLineOption tempfile (QStringList () << QLatin1String("tempfile"), i18n("The files/URLs opened by the application will be deleted after use"));
  parser.addOption (tempfile);

  // urls to open
  parser.addPositionalArgument(QLatin1String("urls"), i18n("Documents to open."), QLatin1String("[urls...]"));

  /**
   * do the command line parsing
   */
  parser.process (app);

  // read from global config once
  KTextEditor::Editor::instance()->readConfig(KSharedConfig::openConfig().data());

  if ( app.isSessionRestored() )
  {
    KWrite::restore();
  }
  else
  {
    bool nav = false;
    int line = 0, column = 0;

    QTextCodec *codec = parser.isSet(QLatin1String("encoding")) ? QTextCodec::codecForName(parser.value(QLatin1String("encoding")).toLocal8Bit()) : 0;

    if (parser.isSet (QLatin1String("line")))
    {
      line = parser.value (QLatin1String("line")).toInt() - 1;
      nav = true;
    }

    if (parser.isSet (QLatin1String("column")))
    {
      column = parser.value (QLatin1String("column")).toInt() - 1;
      nav = true;
    }

    if ( parser.positionalArguments().count() == 0 )
    {
        KWrite *t = new KWrite;

        if( parser.isSet( QLatin1String("stdin") ) )
        {
          QTextStream input(stdin, QIODevice::ReadOnly);

          // set chosen codec
          if (codec)
            input.setCodec (codec);

          QString line;
          QString text;

          do
          {
            line = input.readLine();
            text.append( line + QLatin1Char('\n') );
          } while( !line.isNull() );

          KTextEditor::Document *doc = t->view()->document();
          if( doc )
              doc->setText( text );
        }

        if (nav && t->view())
          t->view()->setCursorPosition (KTextEditor::Cursor (line, column));
    }
    else
    {
      int docs_opened = 0;
      Q_FOREACH (const QString positionalArgument, parser.positionalArguments())
      {
        QUrl url;

        // convert to an url
        QRegExp withProtocol(QLatin1String("^[a-zA-Z]+:")); // TODO: remove after Qt supports this on its own
        if (withProtocol.indexIn(positionalArgument) == 0) {
          url = QUrl::fromUserInput(positionalArgument);
        } else {
          url = QUrl::fromLocalFile(positionalArgument);
        }

        // this file is no local dir, open it, else warn
        bool noDir = !url.isLocalFile() || !QFileInfo (url.toLocalFile()).isDir();

        if (noDir)
        {
          ++docs_opened;
          KWrite *t = new KWrite();

          if (codec)
            t->view()->document()->setEncoding(QString::fromLatin1(codec->name()));

          t->loadURL( url );

          if (nav)
            t->view()->setCursorPosition (KTextEditor::Cursor (line, column));
        }
        else
        {
          KMessageBox::sorry(0, i18n("The file '%1' could not be opened: it is not a normal file, it is a folder.", url.toString()));
        }
      }
      if (!docs_opened) ::exit(1); // see http://bugs.kde.org/show_bug.cgi?id=124708
    }
  }

  // no window there, uh, ohh, for example borked session config !!!
  // create at least one !!
  if (KWrite::noWindows())
    new KWrite();

  /**
   * finally register this kwrite instance for dbus
   */
  const KDBusService dbusService (KDBusService::Multiple);

  /**
   * Run the event loop
   */
  return app.exec ();
}
<|endoftext|>


<commit_before><commit_msg>ZMQhistSource: pack histos in AliHLTObjArray<commit_after><|endoftext|>


<commit_before>/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __STOUT_NET_HPP__
#define __STOUT_NET_HPP__

#if defined(__linux__) || defined(__APPLE__)
#include <ifaddrs.h>
#endif
#include <netdb.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <arpa/inet.h>

#ifdef __linux__
#include <linux/if_packet.h>
#endif

#include <net/if.h>
#ifdef __APPLE__
#include <net/if_dl.h>
#include <net/if_types.h>
#endif

#include <sys/param.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <curl/curl.h>

#include <iostream>
#include <set>
#include <string>

#include "abort.hpp"
#include "error.hpp"
#include "none.hpp"
#include "option.hpp"
#include "os.hpp"
#include "result.hpp"
#include "stringify.hpp"
#include "try.hpp"

// Network utilities.
namespace net {

// Returns the HTTP response code resulting from attempting to download the
// specified HTTP or FTP URL into a file at the specified path.
inline Try<int> download(const std::string& url, const std::string& path)
{
  Try<int> fd = os::open(
      path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);

  if (fd.isError()) {
    return Error(fd.error());
  }

  curl_global_init(CURL_GLOBAL_ALL);
  CURL* curl = curl_easy_init();

  if (curl == NULL) {
    curl_easy_cleanup(curl);
    os::close(fd.get());
    return Error("Failed to initialize libcurl");
  }

  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);

  FILE* file = fdopen(fd.get(), "w");
  if (file == NULL) {
    return ErrnoError("Failed to open file handle of '" + path + "'");
  }
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);

  CURLcode curlErrorCode = curl_easy_perform(curl);
  if (curlErrorCode != 0) {
    curl_easy_cleanup(curl);
    fclose(file);
    return Error(curl_easy_strerror(curlErrorCode));
  }

  long code;
  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
  curl_easy_cleanup(curl);

  if (fclose(file) != 0) {
    return ErrnoError("Failed to close file handle of '" + path + "'");
  }

  return Try<int>::some(code);
}

// Returns a Try of the hostname for the provided IP. If the hostname cannot
// be resolved, then a string version of the IP address is returned.
inline Try<std::string> getHostname(uint32_t ip)
{
  sockaddr_in addr;
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = ip;

  char hostname[MAXHOSTNAMELEN];
  if (getnameinfo(
      (sockaddr*)&addr,
      sizeof(addr),
      hostname,
      MAXHOSTNAMELEN,
      NULL,
      0,
      0) != 0) {
    return ErrnoError();
  }

  return std::string(hostname);
}

// Returns the names of all the link devices in the system.
inline Try<std::set<std::string> > links()
{
#if !defined(__linux__) && !defined(__APPLE__)
  return Error("Not implemented");
#else
  struct ifaddrs* ifaddr = NULL;
  if (getifaddrs(&ifaddr) == -1) {
    return ErrnoError();
  }

  std::set<std::string> names;
  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
    if (ifa->ifa_name != NULL) {
      names.insert(ifa->ifa_name);
    }
  }

  freeifaddrs(ifaddr);
  return names;
#endif
}

// Represents a MAC address. A MAC address is a 48-bit unique
// identifier assigned to a network interface for communications on
// the physical network segment. We use a byte array (in network
// order) to represent a MAC address. For example, for a MAC address
// 01:23:34:67:89:ab, the format is shown as follows:
//
//    MSB                                          LSB
//     |                                            |
//     v                                            v
// +--------+--------+--------+--------+--------+--------+
// |bytes[0]|bytes[1]|bytes[2]|bytes[3]|bytes[4]|bytes[5]|
// +--------+--------+--------+--------+--------+--------+
//
//     01   :   23   :   45   :   67   :   89   :   ab
class MAC
{
public:
  // Returns the byte at the given index. For example, for a MAC
  // address 01:23:45:67:89:ab, mac[0] = 01, mac[1] = 23 and etc.
  uint8_t operator [] (size_t index) const
  {
    if (index >= 6) {
      ABORT("Invalid index specified in MAC::operator []\n");
    }

    return bytes[index];
  }

private:
  friend std::ostream& operator << (std::ostream& stream, const MAC& mac);
  friend Result<MAC> mac(const std::string& name);

  explicit MAC(uint8_t* _bytes)
  {
    for (size_t i = 0; i < 6; i++) {
      bytes[i] = _bytes[i];
    }
  }

  // Byte array of this MAC address (in network order).
  uint8_t bytes[6];
};

// Returns the standard string format (IEEE 802) of the given MAC
// address, which contains six groups of two hexadecimal digits,
// separated by colons, in network order (e.g., 01:23:45:67:89:ab).
inline std::ostream& operator << (std::ostream& stream, const MAC& mac)
{
  char buffer[18];

  sprintf(
      buffer,
      "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
      mac.bytes[0],
      mac.bytes[1],
      mac.bytes[2],
      mac.bytes[3],
      mac.bytes[4],
      mac.bytes[5]);

  return stream << buffer;
}

// Returns the MAC address of a given link device. The link device is
// specified using its name (e.g., eth0). Returns error if the link
// device is not found. Returns none if the link device is found, but
// does not have a MAC address (e.g., loopback).
inline Result<MAC> mac(const std::string& name)
{
#if !defined(__linux__) && !defined(__APPLE__)
  return Error("Not implemented");
#else
  struct ifaddrs* ifaddr = NULL;
  if (getifaddrs(&ifaddr) == -1) {
    return ErrnoError();
  }

  // Indicates whether the link device is found or not.
  bool found = false;

  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
    if (ifa->ifa_name != NULL && !strcmp(ifa->ifa_name, name.c_str())) {
      found = true;

# if defined(__linux__)
     if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_PACKET) {
        struct sockaddr_ll* link = (struct sockaddr_ll*) ifa->ifa_addr;

        if (link->sll_halen == 6) {
          MAC mac((uint8_t*) link->sll_addr);

          // Ignore if the address is 0 so that the results are
          // consistent on both OSX and Linux.
          if (stringify(mac) == "00:00:00:00:00:00") {
            continue;
          }

          freeifaddrs(ifaddr);
          return mac;
        }
      }
# elif defined(__APPLE__)
      if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK) {
        struct sockaddr_dl* link = (struct sockaddr_dl*) ifa->ifa_addr;

        if (link->sdl_type == IFT_ETHER && link->sdl_alen == 6) {
          MAC mac((uint8_t*) LLADDR(link));

          freeifaddrs(ifaddr);
          return mac;
        }
      }
# endif
    }
  }

  freeifaddrs(ifaddr);

  if (!found) {
    return Error("Cannot find the link device");
  }

  return None();
#endif
}

// Represents an IPv4 address. Besides the actual IP address, we also
// store additional information about the address such as the net mask
// which defines the subnet.
class IP
{
public:
  // Returns the IP address (in network order).
  uint32_t address() const { return address_; }

  // Returns the net mask (in network order).
  Option<uint32_t> netmask() const { return netmask_; }

  // Returns the prefix of the subnet defined by the net mask.
  Option<size_t> prefix() const
  {
    if (netmask_.isNone()) {
      return None();
    }

    // Convert the net mask to host order.
    uint32_t mask = ntohl(netmask_.get());

    size_t value = 0;
    while (mask != 0) {
      value += mask & 0x1;
      mask >>= 1;
    }

    return value;
  }

private:
  friend std::ostream& operator << (std::ostream& stream, const IP& ip);
  friend Result<IP> ip(const std::string& name);

  explicit IP(uint32_t _address) : address_(_address) {}

  IP(uint32_t _address, uint32_t _netmask)
    : address_(_address), netmask_(_netmask) {}

  // IP address (in network order).
  uint32_t address_;

  // The optional net mask (in network order).
  Option<uint32_t> netmask_;
};

// Returns the string representation of the given IP address using the
// canonical dot-decimal form with prefix. For example: "10.0.0.1/8".
inline std::ostream& operator << (std::ostream& stream, const IP& ip)
{
  char buffer[INET_ADDRSTRLEN];

  const char* addr = inet_ntop(AF_INET, &ip.address_, buffer, sizeof(buffer));
  if (addr == NULL) {
    // We do not expect inet_ntop to fail because all parameters
    // passed in are valid.
    std::string message =
      "inet_ntop returns error for address " + stringify(ip.address());

    perror(message.c_str());
    abort();
  }

  stream << addr;

  if (ip.prefix().isSome()) {
    stream << "/" << ip.prefix().get();
  }

  return stream;
}

// Returns the first available IPv4 address of a given link device.
// The link device is specified using its name (e.g., eth0). Returns
// error if the link device is not found. Returns none if the link
// device is found, but does not have an IPv4 address.
// TODO(jieyu): It is uncommon, but likely that a link device has
// multiple IPv4 addresses. In that case, consider returning the
// primary IP address instead of the first one.
inline Result<IP> ip(const std::string& name)
{
#if !defined(__linux__) && !defined(__APPLE__)
  return Error("Not implemented");
#else
  struct ifaddrs* ifaddr = NULL;
  if (getifaddrs(&ifaddr) == -1) {
    return ErrnoError();
  }

  // Indicates whether the link device is found or not.
  bool found = false;

  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
    if (ifa->ifa_name != NULL && !strcmp(ifa->ifa_name, name.c_str())) {
      found = true;

      if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_INET) {
        struct sockaddr_in* addr = (struct sockaddr_in*) ifa->ifa_addr;

        if (ifa->ifa_netmask != NULL &&
            ifa->ifa_netmask->sa_family == AF_INET) {
          struct sockaddr_in* netmask = (struct sockaddr_in*) ifa->ifa_netmask;

          IP ip((uint32_t) addr->sin_addr.s_addr,
                (uint32_t) netmask->sin_addr.s_addr);

          freeifaddrs(ifaddr);
          return ip;
        }

        // Note that this is the case where net mask is not specified.
        // We've seen such cases when VPN is used.
        IP ip((uint32_t) addr->sin_addr.s_addr);

        freeifaddrs(ifaddr);
        return ip;
      }
    }
  }

  freeifaddrs(ifaddr);

  if (!found) {
    return Error("Cannot find the link device");
  }

  return None();
#endif
}

} // namespace net {

#endif // __STOUT_NET_HPP__
<commit_msg>Adjusted the includes in stout/net.hpp to avoid definition conflicts caused by netlink.<commit_after>/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __STOUT_NET_HPP__
#define __STOUT_NET_HPP__

#if defined(__linux__) || defined(__APPLE__)
#include <ifaddrs.h>
#endif
#include <netdb.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <arpa/inet.h>

#ifdef __linux__
#include <linux/if.h>
#include <linux/if_packet.h>
#endif

#ifdef __APPLE__
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#endif

#include <sys/param.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <curl/curl.h>

#include <iostream>
#include <set>
#include <string>

#include "abort.hpp"
#include "error.hpp"
#include "none.hpp"
#include "option.hpp"
#include "os.hpp"
#include "result.hpp"
#include "stringify.hpp"
#include "try.hpp"

// Network utilities.
namespace net {

// Returns the HTTP response code resulting from attempting to download the
// specified HTTP or FTP URL into a file at the specified path.
inline Try<int> download(const std::string& url, const std::string& path)
{
  Try<int> fd = os::open(
      path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);

  if (fd.isError()) {
    return Error(fd.error());
  }

  curl_global_init(CURL_GLOBAL_ALL);
  CURL* curl = curl_easy_init();

  if (curl == NULL) {
    curl_easy_cleanup(curl);
    os::close(fd.get());
    return Error("Failed to initialize libcurl");
  }

  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);

  FILE* file = fdopen(fd.get(), "w");
  if (file == NULL) {
    return ErrnoError("Failed to open file handle of '" + path + "'");
  }
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);

  CURLcode curlErrorCode = curl_easy_perform(curl);
  if (curlErrorCode != 0) {
    curl_easy_cleanup(curl);
    fclose(file);
    return Error(curl_easy_strerror(curlErrorCode));
  }

  long code;
  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
  curl_easy_cleanup(curl);

  if (fclose(file) != 0) {
    return ErrnoError("Failed to close file handle of '" + path + "'");
  }

  return Try<int>::some(code);
}

// Returns a Try of the hostname for the provided IP. If the hostname cannot
// be resolved, then a string version of the IP address is returned.
inline Try<std::string> getHostname(uint32_t ip)
{
  sockaddr_in addr;
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = ip;

  char hostname[MAXHOSTNAMELEN];
  if (getnameinfo(
      (sockaddr*)&addr,
      sizeof(addr),
      hostname,
      MAXHOSTNAMELEN,
      NULL,
      0,
      0) != 0) {
    return ErrnoError();
  }

  return std::string(hostname);
}

// Returns the names of all the link devices in the system.
inline Try<std::set<std::string> > links()
{
#if !defined(__linux__) && !defined(__APPLE__)
  return Error("Not implemented");
#else
  struct ifaddrs* ifaddr = NULL;
  if (getifaddrs(&ifaddr) == -1) {
    return ErrnoError();
  }

  std::set<std::string> names;
  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
    if (ifa->ifa_name != NULL) {
      names.insert(ifa->ifa_name);
    }
  }

  freeifaddrs(ifaddr);
  return names;
#endif
}

// Represents a MAC address. A MAC address is a 48-bit unique
// identifier assigned to a network interface for communications on
// the physical network segment. We use a byte array (in network
// order) to represent a MAC address. For example, for a MAC address
// 01:23:34:67:89:ab, the format is shown as follows:
//
//    MSB                                          LSB
//     |                                            |
//     v                                            v
// +--------+--------+--------+--------+--------+--------+
// |bytes[0]|bytes[1]|bytes[2]|bytes[3]|bytes[4]|bytes[5]|
// +--------+--------+--------+--------+--------+--------+
//
//     01   :   23   :   45   :   67   :   89   :   ab
class MAC
{
public:
  // Returns the byte at the given index. For example, for a MAC
  // address 01:23:45:67:89:ab, mac[0] = 01, mac[1] = 23 and etc.
  uint8_t operator [] (size_t index) const
  {
    if (index >= 6) {
      ABORT("Invalid index specified in MAC::operator []\n");
    }

    return bytes[index];
  }

private:
  friend std::ostream& operator << (std::ostream& stream, const MAC& mac);
  friend Result<MAC> mac(const std::string& name);

  explicit MAC(uint8_t* _bytes)
  {
    for (size_t i = 0; i < 6; i++) {
      bytes[i] = _bytes[i];
    }
  }

  // Byte array of this MAC address (in network order).
  uint8_t bytes[6];
};

// Returns the standard string format (IEEE 802) of the given MAC
// address, which contains six groups of two hexadecimal digits,
// separated by colons, in network order (e.g., 01:23:45:67:89:ab).
inline std::ostream& operator << (std::ostream& stream, const MAC& mac)
{
  char buffer[18];

  sprintf(
      buffer,
      "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
      mac.bytes[0],
      mac.bytes[1],
      mac.bytes[2],
      mac.bytes[3],
      mac.bytes[4],
      mac.bytes[5]);

  return stream << buffer;
}

// Returns the MAC address of a given link device. The link device is
// specified using its name (e.g., eth0). Returns error if the link
// device is not found. Returns none if the link device is found, but
// does not have a MAC address (e.g., loopback).
inline Result<MAC> mac(const std::string& name)
{
#if !defined(__linux__) && !defined(__APPLE__)
  return Error("Not implemented");
#else
  struct ifaddrs* ifaddr = NULL;
  if (getifaddrs(&ifaddr) == -1) {
    return ErrnoError();
  }

  // Indicates whether the link device is found or not.
  bool found = false;

  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
    if (ifa->ifa_name != NULL && !strcmp(ifa->ifa_name, name.c_str())) {
      found = true;

# if defined(__linux__)
     if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_PACKET) {
        struct sockaddr_ll* link = (struct sockaddr_ll*) ifa->ifa_addr;

        if (link->sll_halen == 6) {
          MAC mac((uint8_t*) link->sll_addr);

          // Ignore if the address is 0 so that the results are
          // consistent on both OSX and Linux.
          if (stringify(mac) == "00:00:00:00:00:00") {
            continue;
          }

          freeifaddrs(ifaddr);
          return mac;
        }
      }
# elif defined(__APPLE__)
      if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK) {
        struct sockaddr_dl* link = (struct sockaddr_dl*) ifa->ifa_addr;

        if (link->sdl_type == IFT_ETHER && link->sdl_alen == 6) {
          MAC mac((uint8_t*) LLADDR(link));

          freeifaddrs(ifaddr);
          return mac;
        }
      }
# endif
    }
  }

  freeifaddrs(ifaddr);

  if (!found) {
    return Error("Cannot find the link device");
  }

  return None();
#endif
}

// Represents an IPv4 address. Besides the actual IP address, we also
// store additional information about the address such as the net mask
// which defines the subnet.
class IP
{
public:
  // Returns the IP address (in network order).
  uint32_t address() const { return address_; }

  // Returns the net mask (in network order).
  Option<uint32_t> netmask() const { return netmask_; }

  // Returns the prefix of the subnet defined by the net mask.
  Option<size_t> prefix() const
  {
    if (netmask_.isNone()) {
      return None();
    }

    // Convert the net mask to host order.
    uint32_t mask = ntohl(netmask_.get());

    size_t value = 0;
    while (mask != 0) {
      value += mask & 0x1;
      mask >>= 1;
    }

    return value;
  }

private:
  friend std::ostream& operator << (std::ostream& stream, const IP& ip);
  friend Result<IP> ip(const std::string& name);

  explicit IP(uint32_t _address) : address_(_address) {}

  IP(uint32_t _address, uint32_t _netmask)
    : address_(_address), netmask_(_netmask) {}

  // IP address (in network order).
  uint32_t address_;

  // The optional net mask (in network order).
  Option<uint32_t> netmask_;
};

// Returns the string representation of the given IP address using the
// canonical dot-decimal form with prefix. For example: "10.0.0.1/8".
inline std::ostream& operator << (std::ostream& stream, const IP& ip)
{
  char buffer[INET_ADDRSTRLEN];

  const char* addr = inet_ntop(AF_INET, &ip.address_, buffer, sizeof(buffer));
  if (addr == NULL) {
    // We do not expect inet_ntop to fail because all parameters
    // passed in are valid.
    std::string message =
      "inet_ntop returns error for address " + stringify(ip.address());

    perror(message.c_str());
    abort();
  }

  stream << addr;

  if (ip.prefix().isSome()) {
    stream << "/" << ip.prefix().get();
  }

  return stream;
}

// Returns the first available IPv4 address of a given link device.
// The link device is specified using its name (e.g., eth0). Returns
// error if the link device is not found. Returns none if the link
// device is found, but does not have an IPv4 address.
// TODO(jieyu): It is uncommon, but likely that a link device has
// multiple IPv4 addresses. In that case, consider returning the
// primary IP address instead of the first one.
inline Result<IP> ip(const std::string& name)
{
#if !defined(__linux__) && !defined(__APPLE__)
  return Error("Not implemented");
#else
  struct ifaddrs* ifaddr = NULL;
  if (getifaddrs(&ifaddr) == -1) {
    return ErrnoError();
  }

  // Indicates whether the link device is found or not.
  bool found = false;

  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
    if (ifa->ifa_name != NULL && !strcmp(ifa->ifa_name, name.c_str())) {
      found = true;

      if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_INET) {
        struct sockaddr_in* addr = (struct sockaddr_in*) ifa->ifa_addr;

        if (ifa->ifa_netmask != NULL &&
            ifa->ifa_netmask->sa_family == AF_INET) {
          struct sockaddr_in* netmask = (struct sockaddr_in*) ifa->ifa_netmask;

          IP ip((uint32_t) addr->sin_addr.s_addr,
                (uint32_t) netmask->sin_addr.s_addr);

          freeifaddrs(ifaddr);
          return ip;
        }

        // Note that this is the case where net mask is not specified.
        // We've seen such cases when VPN is used.
        IP ip((uint32_t) addr->sin_addr.s_addr);

        freeifaddrs(ifaddr);
        return ip;
      }
    }
  }

  freeifaddrs(ifaddr);

  if (!found) {
    return Error("Cannot find the link device");
  }

  return None();
#endif
}

} // namespace net {

#endif // __STOUT_NET_HPP__
<|endoftext|>


<commit_before>/*
 * MediaPlayer.cpp
 *
 *  Created on: 2016年12月5日
 *      Author: xzl
 */

#include <algorithm>
#include "MediaPlayer.h"
#include "Rtmp/RtmpPlayerImp.h"
#include "Rtsp/RtspPlayerImp.h"

using namespace ZL::Rtmp;
using namespace ZL::Rtsp;

namespace ZL {
namespace Player {

MediaPlayer::MediaPlayer() {
}

MediaPlayer::~MediaPlayer() {
	if(!EventPoller::Instance().isMainThread()){
		FatalL << "未在主线程释放";
	}
	teardown();
}

void MediaPlayer::play(const char* strUrl, const char* strUser, const char* strPwd, eRtpType eType) {
	string strPrefix = FindField(strUrl, NULL, "://");
	if ((strcasecmp(m_strPrefix.data(),strPrefix.data()) != 0) || strPrefix.empty()) {
		//协议切换
		m_strPrefix = strPrefix;
		m_parser = PlayerBase::createPlayer(strUrl);
		m_parser->setOnShutdown(m_shutdownCB);
		m_parser->setOnVideoCB(m_onGetVideoCB);
		m_parser->setOnAudioCB(m_onGetAudioCB);
	}
	m_parser->setOnPlayResult(m_playResultCB);
	m_parser->play(strUrl, strUser, strPwd, eType);
}

void MediaPlayer::pause(bool bPause) {
	if (m_parser) {
		m_parser->pause(bPause);
	}
}

void MediaPlayer::teardown() {
	if (m_parser) {
		m_parser->teardown();
	}
}

} /* namespace Player */
} /* namespace ZL */
<commit_msg>关闭log<commit_after>/*
 * MediaPlayer.cpp
 *
 *  Created on: 2016年12月5日
 *      Author: xzl
 */

#include <algorithm>
#include "MediaPlayer.h"
#include "Rtmp/RtmpPlayerImp.h"
#include "Rtsp/RtspPlayerImp.h"

using namespace ZL::Rtmp;
using namespace ZL::Rtsp;

namespace ZL {
namespace Player {

MediaPlayer::MediaPlayer() {
}

MediaPlayer::~MediaPlayer() {
	teardown();
}

void MediaPlayer::play(const char* strUrl, const char* strUser, const char* strPwd, eRtpType eType) {
	string strPrefix = FindField(strUrl, NULL, "://");
	if ((strcasecmp(m_strPrefix.data(),strPrefix.data()) != 0) || strPrefix.empty()) {
		//协议切换
		m_strPrefix = strPrefix;
		m_parser = PlayerBase::createPlayer(strUrl);
		m_parser->setOnShutdown(m_shutdownCB);
		m_parser->setOnVideoCB(m_onGetVideoCB);
		m_parser->setOnAudioCB(m_onGetAudioCB);
	}
	m_parser->setOnPlayResult(m_playResultCB);
	m_parser->play(strUrl, strUser, strPwd, eType);
}

void MediaPlayer::pause(bool bPause) {
	if (m_parser) {
		m_parser->pause(bPause);
	}
}

void MediaPlayer::teardown() {
	if (m_parser) {
		m_parser->teardown();
	}
}

} /* namespace Player */
} /* namespace ZL */
<|endoftext|>


<commit_before>#include "Players/Genetic_AI.h"

#include <iostream>
#include <fstream>
#include <cmath>
#include <algorithm>
#include <stdexcept>

#include "Moves/Move.h"
#include "Game/Board.h"
#include "Game/Clock.h"

#include "Exceptions/Checkmate_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"

#include "Utility.h"

int Genetic_AI::next_id = 0;

Genetic_AI::Genetic_AI() :
    genome(),
    id(next_id++)
{
}

// Sexual reproduction
Genetic_AI::Genetic_AI(const Genetic_AI& A, const Genetic_AI& B) :
    genome(A.genome, B.genome),
    id(next_id++)
{
}

Genetic_AI::~Genetic_AI()
{
}

Genetic_AI::Genetic_AI(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    read_from(ifs);
}

Genetic_AI::Genetic_AI(std::istream& is)
{
    read_from(is);
}

Genetic_AI::Genetic_AI(const std::string& file_name, int id_in) : id(id_in)
{
    if(id >= next_id)
    {
        next_id = id + 1;
    }

    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    std::string line;
    while(std::getline(ifs, line))
    {
        if( ! String::starts_with(line, "ID:"))
        {
            continue;
        }

        auto param_value = String::split(line, ":", 1);
        if(id_in == std::stoi(param_value[1]))
        {
            genome.read_from(ifs);
            return;
        }
    }

    throw std::runtime_error("Could not locate ID " + std::to_string(id_in) + " inside file " + file_name);
}

void Genetic_AI::read_from(std::istream& is)
{
    std::string line;
    id = -1;
    while(std::getline(is, line))
    {
        if(line.empty())
        {
            continue;
        }

        if(String::starts_with(line, "ID:"))
        {
            id = std::stoi(String::split(line)[1]);
            break;
        }
        else
        {
            throw std::runtime_error("Invalid Genetic_AI line: " + line);
        }
    }

    if( ! is)
    {
        throw std::runtime_error("Incomplete Genetic_AI spec in file for ID " + std::to_string(id));
    }

    if(id >= next_id)
    {
        next_id = id + 1;
    }

    genome.read_from(is);
}

const Complete_Move Genetic_AI::choose_move(const Board& board, const Clock& clock) const
{
    const auto& legal_moves = board.all_legal_moves();
    if(legal_moves.size() == 1)
    {
        if(principal_variation.size() > 2 && principal_variation[1] == board.get_game_record().back())
        {
            // search_game_tree() assumes the principal variation starts
            // with the previous move of this player. If a move was forced,
            // then the principal variation needs to be updated to start with
            // the next move of this side after checking that the immediately
            // preceding move was the expected one.
            principal_variation.erase(principal_variation.begin(),
                                      principal_variation.begin() + 2);
        }
        else
        {
            principal_variation.clear();
        }

        return legal_moves.front(); // If there's only one legal move, take it.
    }

    auto time_to_use = genome.time_to_examine(board, clock);

    // alpha = highest score found that opponent will allow
    Game_Tree_Node_Result alpha_start = {Complete_Move(),
                                         Math::lose_score,
                                         board.whose_turn(),
                                         0,
                                         ""};
    // beta = score that will cause opponent to choose a different prior move
    Game_Tree_Node_Result beta_start = {Complete_Move(),
                                        Math::win_score,
                                        board.whose_turn(),
                                        0,
                                        ""};

    auto result = search_game_tree(board,
                                   time_to_use,
                                   clock,
                                   0,
                                   alpha_start,
                                   beta_start);

    if(result.depth > 0)
    {
        board.add_commentary_to_next_move(result.commentary);
        principal_variation = String::split(result.commentary);
    }
    else
    {
        principal_variation.clear();
    }

    return result.move;
}

bool better_than(const Game_Tree_Node_Result& a, const Game_Tree_Node_Result& b, Color perspective)
{
    auto scoreA = a.corrected_score(perspective);
    auto scoreB = b.corrected_score(perspective);

    if(scoreA > scoreB)
    {
        return true;
    }

    if(scoreA < scoreB)
    {
        return false;
    }

    // scoreA == scoreB

    // Shorter path to winning is better
    if(scoreA == Math::win_score)
    {
        return a.depth < b.depth;
    }

    // Longer path to losing is better
    if(scoreA == Math::lose_score)
    {
        return a.depth > b.depth;
    }

    return false;
}

bool operator==(const Game_Tree_Node_Result& a, const Game_Tree_Node_Result& b)
{
    auto scoreA = a.corrected_score(WHITE);
    auto scoreB = b.corrected_score(WHITE);

    if(scoreA != scoreB)
    {
        return false;
    }

    // scoreA == scoreB

    if(std::abs(scoreA) == Math::win_score)
    {
        return a.depth == b.depth;
    }

    return true;
}

Game_Tree_Node_Result Genetic_AI::search_game_tree(const Board& board,
                                                   const double time_to_examine,
                                                   const Clock& clock,
                                                   const size_t depth,
                                                   Game_Tree_Node_Result alpha,
                                                   Game_Tree_Node_Result beta) const
{
    auto time_start = clock.time_left(clock.running_for());
    auto all_legal_moves = board.all_legal_moves();

    // The first item in the principal variation is the last move that
    // this player made. Since then, the opponent has also made a move,
    // so the first item in the principal variation corresponds to the
    // game record item at game_record.size() - 2. The depth of the game
    // tree search increments both the game_record index and the principal
    // variation index in step.
    bool still_on_principal_variation = false;
    if(principal_variation.size() > depth + 2)
    {
        auto principal_variation_start_index = board.get_game_record().size() - depth - 2;
        still_on_principal_variation = std::equal(board.get_game_record().begin() + principal_variation_start_index,
                                                  board.get_game_record().end(),
                                                  principal_variation.begin());

        if(still_on_principal_variation)
        {
            auto next_principal_variation_move = principal_variation[depth + 2];
            // remove non-move notation
            next_principal_variation_move = String::strip_comments(next_principal_variation_move, '+');
            next_principal_variation_move = String::strip_comments(next_principal_variation_move, '#');

            auto move_iter = std::find_if(all_legal_moves.begin(),
                                          all_legal_moves.end(),
                                          [&next_principal_variation_move, &board](const auto& legal_move)
                                          {
                                              return legal_move.game_record_item(board) == next_principal_variation_move;
                                          });

            // Make sure that the principal variation is actually a legal move.
            // This is purely for debugging as special circumstances (i.e., once
            // per several thousand games) cause the principal variation to be
            // invalidated without it being cleared.
            if(move_iter == all_legal_moves.end())
            {
                board.ascii_draw(WHITE);
                board.print_game_record("","","","Principal Variation error", 0);
                for(const auto& item : principal_variation)
                {
                    std::cout << item << " ";
                }
                std::cout << '\n' << "Depth: " << depth << '\n'
                          << "Next move in variation: " << next_principal_variation_move << std::endl;
                throw std::runtime_error("ERROR: bad variation code");
            }

            // Put principal variation move at start of list to allow
            // the most pruning later.
            std::iter_swap(all_legal_moves.begin(), move_iter);
        }
    }

    auto perspective = board.whose_turn();
    int moves_examined = 0;
    const auto current_legal_moves_count = all_legal_moves.size();

    Game_Tree_Node_Result best_result = {board.all_legal_moves().front(),
                                         Math::lose_score,
                                         perspective,
                                         depth,
                                         ""};

    for(const auto& move : all_legal_moves)
    {
        auto next_board = board;

        try
        {
            next_board.submit_move(move);
        }
        catch(const Checkmate_Exception&)
        {
            // Mate in one (try to pick the shortest path to checkmate)
            return {move,
                    genome.evaluate(next_board, perspective),
                    perspective,
                    depth,
                    next_board.get_game_record().back()};
        }
        catch(const Game_Ending_Exception&)
        {
            // Draws get scored like any other board position
        }

        int moves_left = current_legal_moves_count - moves_examined;
        double time_left = time_to_examine - (time_start - clock.time_left(clock.running_for()));
        double time_alloted_for_this_move = time_left/moves_left;

        bool recurse;
        if(next_board.game_has_ended())
        {
            recurse = false;
        }
        else if(next_board.all_legal_moves().size() == 1)
        {
            recurse = true;
        }
        else if(still_on_principal_variation)
        {
            recurse = true;
        }
        else if(time_alloted_for_this_move < genome.minimum_time_to_recurse(next_board))
        {
            recurse = false;
        }
        else
        {
            recurse = genome.good_enough_to_examine(board, next_board, perspective);
        }

        Game_Tree_Node_Result result;
        if(recurse)
        {
            result = search_game_tree(next_board,
                                      time_alloted_for_this_move,
                                      clock,
                                      depth + 1,
                                      beta,
                                      alpha);

            // Update last result with this game tree node's data
            result.move = move;
            result.commentary = next_board.get_game_record().back()
                                        + " "
                                        + result.commentary;
        }
        else
        {
            // Record immediate result without looking ahead further
            result = {move,
                      genome.evaluate(next_board, perspective),
                      perspective,
                      depth,
                      next_board.get_game_record().back()};
        }

        if(better_than(result, best_result, perspective))
        {
            best_result = result;
            if(better_than(best_result, alpha, perspective))
            {
                alpha = best_result;
                if(better_than(alpha, beta, perspective) || alpha == beta)
                {
                    break;
                }
            }
        }

        ++moves_examined;
        still_on_principal_variation = false; // only the first move is part of the principal variation

        if(clock.time_left(clock.running_for()) < 0)
        {
            break;
        }
    }

    return best_result;
}

void Genetic_AI::mutate()
{
    genome.mutate();
}

void Genetic_AI::print_genome(const std::string& file_name) const
{
    if(file_name.empty())
    {
        print_genome(std::cout);
    }
    else
    {
        auto dest = std::ofstream(file_name, std::ofstream::app);
        print_genome(dest);
    }
}

void Genetic_AI::print_genome(std::ostream& os) const
{
    os << "ID: " << get_id() << std::endl;
    genome.print(os);
    os << "END" << std::endl << std::endl;
}

std::string Genetic_AI::name() const
{
    return "Genetic AI " + std::to_string(get_id());
}

std::string Genetic_AI::author() const
{
    return "Mark Harrison";
}

int Genetic_AI::get_id() const
{
    return id;
}

bool Genetic_AI::operator<(const Genetic_AI& other) const
{
    return get_id() < other.get_id();
}

bool Genetic_AI::operator==(const Genetic_AI& other) const
{
    return get_id() == other.get_id();
}
<commit_msg>Simpler iterator math in principal variation review<commit_after>#include "Players/Genetic_AI.h"

#include <iostream>
#include <fstream>
#include <cmath>
#include <algorithm>
#include <stdexcept>

#include "Moves/Move.h"
#include "Game/Board.h"
#include "Game/Clock.h"

#include "Exceptions/Checkmate_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"

#include "Utility.h"

int Genetic_AI::next_id = 0;

Genetic_AI::Genetic_AI() :
    genome(),
    id(next_id++)
{
}

// Sexual reproduction
Genetic_AI::Genetic_AI(const Genetic_AI& A, const Genetic_AI& B) :
    genome(A.genome, B.genome),
    id(next_id++)
{
}

Genetic_AI::~Genetic_AI()
{
}

Genetic_AI::Genetic_AI(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    read_from(ifs);
}

Genetic_AI::Genetic_AI(std::istream& is)
{
    read_from(is);
}

Genetic_AI::Genetic_AI(const std::string& file_name, int id_in) : id(id_in)
{
    if(id >= next_id)
    {
        next_id = id + 1;
    }

    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    std::string line;
    while(std::getline(ifs, line))
    {
        if( ! String::starts_with(line, "ID:"))
        {
            continue;
        }

        auto param_value = String::split(line, ":", 1);
        if(id_in == std::stoi(param_value[1]))
        {
            genome.read_from(ifs);
            return;
        }
    }

    throw std::runtime_error("Could not locate ID " + std::to_string(id_in) + " inside file " + file_name);
}

void Genetic_AI::read_from(std::istream& is)
{
    std::string line;
    id = -1;
    while(std::getline(is, line))
    {
        if(line.empty())
        {
            continue;
        }

        if(String::starts_with(line, "ID:"))
        {
            id = std::stoi(String::split(line)[1]);
            break;
        }
        else
        {
            throw std::runtime_error("Invalid Genetic_AI line: " + line);
        }
    }

    if( ! is)
    {
        throw std::runtime_error("Incomplete Genetic_AI spec in file for ID " + std::to_string(id));
    }

    if(id >= next_id)
    {
        next_id = id + 1;
    }

    genome.read_from(is);
}

const Complete_Move Genetic_AI::choose_move(const Board& board, const Clock& clock) const
{
    const auto& legal_moves = board.all_legal_moves();
    if(legal_moves.size() == 1)
    {
        if(principal_variation.size() > 2 && principal_variation[1] == board.get_game_record().back())
        {
            // search_game_tree() assumes the principal variation starts
            // with the previous move of this player. If a move was forced,
            // then the principal variation needs to be updated to start with
            // the next move of this side after checking that the immediately
            // preceding move was the expected one.
            principal_variation.erase(principal_variation.begin(),
                                      principal_variation.begin() + 2);
        }
        else
        {
            principal_variation.clear();
        }

        return legal_moves.front(); // If there's only one legal move, take it.
    }

    auto time_to_use = genome.time_to_examine(board, clock);

    // alpha = highest score found that opponent will allow
    Game_Tree_Node_Result alpha_start = {Complete_Move(),
                                         Math::lose_score,
                                         board.whose_turn(),
                                         0,
                                         ""};
    // beta = score that will cause opponent to choose a different prior move
    Game_Tree_Node_Result beta_start = {Complete_Move(),
                                        Math::win_score,
                                        board.whose_turn(),
                                        0,
                                        ""};

    auto result = search_game_tree(board,
                                   time_to_use,
                                   clock,
                                   0,
                                   alpha_start,
                                   beta_start);

    if(result.depth > 0)
    {
        board.add_commentary_to_next_move(result.commentary);
        principal_variation = String::split(result.commentary);
    }
    else
    {
        principal_variation.clear();
    }

    return result.move;
}

bool better_than(const Game_Tree_Node_Result& a, const Game_Tree_Node_Result& b, Color perspective)
{
    auto scoreA = a.corrected_score(perspective);
    auto scoreB = b.corrected_score(perspective);

    if(scoreA > scoreB)
    {
        return true;
    }

    if(scoreA < scoreB)
    {
        return false;
    }

    // scoreA == scoreB

    // Shorter path to winning is better
    if(scoreA == Math::win_score)
    {
        return a.depth < b.depth;
    }

    // Longer path to losing is better
    if(scoreA == Math::lose_score)
    {
        return a.depth > b.depth;
    }

    return false;
}

bool operator==(const Game_Tree_Node_Result& a, const Game_Tree_Node_Result& b)
{
    auto scoreA = a.corrected_score(WHITE);
    auto scoreB = b.corrected_score(WHITE);

    if(scoreA != scoreB)
    {
        return false;
    }

    // scoreA == scoreB

    if(std::abs(scoreA) == Math::win_score)
    {
        return a.depth == b.depth;
    }

    return true;
}

Game_Tree_Node_Result Genetic_AI::search_game_tree(const Board& board,
                                                   const double time_to_examine,
                                                   const Clock& clock,
                                                   const size_t depth,
                                                   Game_Tree_Node_Result alpha,
                                                   Game_Tree_Node_Result beta) const
{
    auto time_start = clock.time_left(clock.running_for());
    auto all_legal_moves = board.all_legal_moves();

    // The first item in the principal variation is the last move that
    // this player made. Since then, the opponent has also made a move,
    // so the first item in the principal variation corresponds to the
    // game record item at game_record.size() - 2. The depth of the game
    // tree search increments both the game_record index and the principal
    // variation index in step.
    bool still_on_principal_variation = false;
    if(principal_variation.size() > depth + 2)
    {
        still_on_principal_variation = std::equal(board.get_game_record().end() - 2 - depth,
                                                  board.get_game_record().end(),
                                                  principal_variation.begin());

        if(still_on_principal_variation)
        {
            auto next_principal_variation_move = principal_variation[depth + 2];
            // remove non-move notation
            next_principal_variation_move = String::strip_comments(next_principal_variation_move, '+');
            next_principal_variation_move = String::strip_comments(next_principal_variation_move, '#');

            auto move_iter = std::find_if(all_legal_moves.begin(),
                                          all_legal_moves.end(),
                                          [&next_principal_variation_move, &board](const auto& legal_move)
                                          {
                                              return legal_move.game_record_item(board) == next_principal_variation_move;
                                          });

            // Make sure that the principal variation is actually a legal move.
            // This is purely for debugging as special circumstances (i.e., once
            // per several thousand games) cause the principal variation to be
            // invalidated without it being cleared.
            if(move_iter == all_legal_moves.end())
            {
                board.ascii_draw(WHITE);
                board.print_game_record("","","","Principal Variation error", 0);
                for(const auto& item : principal_variation)
                {
                    std::cout << item << " ";
                }
                std::cout << '\n' << "Depth: " << depth << '\n'
                          << "Next move in variation: " << next_principal_variation_move << std::endl;
                throw std::runtime_error("ERROR: bad variation code");
            }

            // Put principal variation move at start of list to allow
            // the most pruning later.
            std::iter_swap(all_legal_moves.begin(), move_iter);
        }
    }

    auto perspective = board.whose_turn();
    int moves_examined = 0;
    const auto current_legal_moves_count = all_legal_moves.size();

    Game_Tree_Node_Result best_result = {board.all_legal_moves().front(),
                                         Math::lose_score,
                                         perspective,
                                         depth,
                                         ""};

    for(const auto& move : all_legal_moves)
    {
        auto next_board = board;

        try
        {
            next_board.submit_move(move);
        }
        catch(const Checkmate_Exception&)
        {
            // Mate in one (try to pick the shortest path to checkmate)
            return {move,
                    genome.evaluate(next_board, perspective),
                    perspective,
                    depth,
                    next_board.get_game_record().back()};
        }
        catch(const Game_Ending_Exception&)
        {
            // Draws get scored like any other board position
        }

        int moves_left = current_legal_moves_count - moves_examined;
        double time_left = time_to_examine - (time_start - clock.time_left(clock.running_for()));
        double time_alloted_for_this_move = time_left/moves_left;

        bool recurse;
        if(next_board.game_has_ended())
        {
            recurse = false;
        }
        else if(next_board.all_legal_moves().size() == 1)
        {
            recurse = true;
        }
        else if(still_on_principal_variation)
        {
            recurse = true;
        }
        else if(time_alloted_for_this_move < genome.minimum_time_to_recurse(next_board))
        {
            recurse = false;
        }
        else
        {
            recurse = genome.good_enough_to_examine(board, next_board, perspective);
        }

        Game_Tree_Node_Result result;
        if(recurse)
        {
            result = search_game_tree(next_board,
                                      time_alloted_for_this_move,
                                      clock,
                                      depth + 1,
                                      beta,
                                      alpha);

            // Update last result with this game tree node's data
            result.move = move;
            result.commentary = next_board.get_game_record().back()
                                        + " "
                                        + result.commentary;
        }
        else
        {
            // Record immediate result without looking ahead further
            result = {move,
                      genome.evaluate(next_board, perspective),
                      perspective,
                      depth,
                      next_board.get_game_record().back()};
        }

        if(better_than(result, best_result, perspective))
        {
            best_result = result;
            if(better_than(best_result, alpha, perspective))
            {
                alpha = best_result;
                if(better_than(alpha, beta, perspective) || alpha == beta)
                {
                    break;
                }
            }
        }

        ++moves_examined;
        still_on_principal_variation = false; // only the first move is part of the principal variation

        if(clock.time_left(clock.running_for()) < 0)
        {
            break;
        }
    }

    return best_result;
}

void Genetic_AI::mutate()
{
    genome.mutate();
}

void Genetic_AI::print_genome(const std::string& file_name) const
{
    if(file_name.empty())
    {
        print_genome(std::cout);
    }
    else
    {
        auto dest = std::ofstream(file_name, std::ofstream::app);
        print_genome(dest);
    }
}

void Genetic_AI::print_genome(std::ostream& os) const
{
    os << "ID: " << get_id() << std::endl;
    genome.print(os);
    os << "END" << std::endl << std::endl;
}

std::string Genetic_AI::name() const
{
    return "Genetic AI " + std::to_string(get_id());
}

std::string Genetic_AI::author() const
{
    return "Mark Harrison";
}

int Genetic_AI::get_id() const
{
    return id;
}

bool Genetic_AI::operator<(const Genetic_AI& other) const
{
    return get_id() < other.get_id();
}

bool Genetic_AI::operator==(const Genetic_AI& other) const
{
    return get_id() == other.get_id();
}
<|endoftext|>


<commit_before>#include "ui_mainwindow.h"
#include "converter.h"
#include "utilities.h"
#include "window.h"

Converter::Converter(QObject *parent) : QObject(parent) {
}

void Converter::start() {
    utils.addToLog("Starting conversion.");
    utils.killProcesses();

    QStringList arguments;
    arguments << "-y" << "-hide_banner";
    arguments << "-i" << utils.getCurrentRawFilename();

    if (!win.ui->cutFromEdit->text().trimmed().isEmpty() && !win.ui->cutToEdit->text().trimmed().isEmpty()) {
        arguments << "-ss" << win.ui->cutFromEdit->text().trimmed();
        arguments << "-to" << win.ui->cutToEdit->text().trimmed();
        // TODO: logging
    }

    arguments << utils.getCurrentFilename();

    utils.conversionProcess = new QProcess;
    utils.conversionProcess->setProcessChannelMode(QProcess::MergedChannels);
    utils.conversionProcess->start(utils.ffmpegBinaryName(), arguments);

    connect(utils.conversionProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(read()));
    connect(utils.conversionProcess, SIGNAL(finished(int)), this, SLOT(complete(int)));
}

void Converter::read() {
    // TODO: when cutting, adjust time
    QString buffer = utils.conversionProcess->readAllStandardOutput();
    QString duration, progress;
    QTime durationTime, progressTime;
    QRegExp time("\\d\\d\\:\\d\\d\\:\\d\\d\\.\\d\\d");
    time.indexIn(buffer);
    if (buffer.contains("Duration: ")) {
        duration = time.capturedTexts()[0];
        durationTime = QTime::fromString(duration, "hh:mm:ss.z");
        utils.currentDuration = QTime(0,0).secsTo(durationTime);
    } else {
        if (buffer != "") {
            progress = time.capturedTexts()[0];
            progressTime = QTime::fromString(progress, "hh:mm:ss.z");
            int percent = double((QTime(0,0).secsTo(progressTime)) / double(utils.currentDuration))*100;
            win.ui->conversionProgressBar->setValue(percent);
        }
    }
    utils.addToLog(buffer);
}

void Converter::complete(int code) {
    utils.conversionProcess->deleteLater();
    utils.conversionProcess = NULL;
    win.toggleConversionButton();

    if (utils.killed) {
        utils.addToLog("Conversion canceled.");
        utils.killed = false;
        return;
    }
    if (code != 0) {
        utils.addToLog("Error on conversion. Check logs.");
        return;
    }

    // In case video is so short that ffmpeg do not display
    // conversion status
    win.ui->conversionProgressBar->setValue(100);

    win.ui->startConversion->toggle();
    win.toggleConversionButton();

    utils.addToLog("Conversion complete.");
    utils.addToLog("Saved to: " + utils.getCurrentFilename());
}
<commit_msg>fixed conversion progress bar issue on windows<commit_after>#include "ui_mainwindow.h"
#include "converter.h"
#include "utilities.h"
#include "window.h"

Converter::Converter(QObject *parent) : QObject(parent) {
}

void Converter::start() {
    utils.addToLog("Starting conversion.");
    utils.killProcesses();

    QStringList arguments;
    arguments << "-y" << "-hide_banner";
    arguments << "-i" << utils.getCurrentRawFilename();

    if (!win.ui->cutFromEdit->text().trimmed().isEmpty() && !win.ui->cutToEdit->text().trimmed().isEmpty()) {
        arguments << "-ss" << win.ui->cutFromEdit->text().trimmed();
        arguments << "-to" << win.ui->cutToEdit->text().trimmed();
        // TODO: logging
    }

    arguments << utils.getCurrentFilename();

    utils.conversionProcess = new QProcess;
    utils.conversionProcess->setProcessChannelMode(QProcess::MergedChannels);
    utils.conversionProcess->start(utils.ffmpegBinaryName(), arguments);

    connect(utils.conversionProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(read()));
    connect(utils.conversionProcess, SIGNAL(finished(int)), this, SLOT(complete(int)));
}

void Converter::read() {
    // TODO: when cutting, adjust time
    QString buffer = utils.conversionProcess->readAllStandardOutput();
    QString duration, progress;
    QTime durationTime, progressTime;
    QRegExp time("\\d\\d\\:\\d\\d\\:\\d\\d\\.\\d\\d");
    time.indexIn(buffer);
    if (buffer.contains("Duration: ")) {
        duration = time.capturedTexts()[0];
        durationTime = QTime::fromString(duration, "hh:mm:ss.z");
        utils.currentDuration = QTime(0,0).secsTo(durationTime);
    } else {
        if (buffer != "") {
            progress = time.capturedTexts()[0];
            if (progress != "") {
                progressTime = QTime::fromString(progress, "hh:mm:ss.z");
                int percent = double((QTime(0,0).secsTo(progressTime)) / double(utils.currentDuration))*100;
                win.ui->conversionProgressBar->setValue(percent);
            }
        }
    }
    utils.addToLog(buffer);
}

void Converter::complete(int code) {
    utils.conversionProcess->deleteLater();
    utils.conversionProcess = NULL;
    win.toggleConversionButton();

    if (utils.killed) {
        utils.addToLog("Conversion canceled.");
        utils.killed = false;
        return;
    }
    if (code != 0) {
        utils.addToLog("Error on conversion. Check logs.");
        return;
    }

    // In case video is so short that ffmpeg do not display
    // conversion status
    win.ui->conversionProgressBar->setValue(100);

    win.ui->startConversion->toggle();
    win.toggleConversionButton();

    utils.addToLog("Conversion complete.");
    utils.addToLog("Saved to: " + utils.getCurrentFilename());
}
<|endoftext|>