<commit_before>#include "misc_ui.hpp"
#include <wx/stdpaths.h>
#include <wx/msgdlg.h>
#include <wx/arrstr.h>

#include <exception>
#include <stdexcept>

namespace Slic3r { namespace GUI {

#ifdef SLIC3R_DEV
void check_version(bool manual)  {
}
#else
void check_version(bool manual)  {
}

#endif

const wxString var(const wxString& in) {
    // TODO replace center string with path to VAR in actual distribution later
    if (VAR_ABS) {
        return wxString(VAR_ABS_PATH) + "/" + in;
    } else {
        return bin() + wxString(VAR_REL) + "/" + in;
    }
}

const wxString bin() {
    wxFileName f(wxStandardPaths::Get().GetExecutablePath());
    wxString appPath(f.GetPath());
    return appPath;
}

/// Returns the path to Slic3r's default user data directory.
const wxString home(const wxString& in) {
    if (the_os == OS::Windows)
        return wxGetHomeDir() + "/" + in + "/";
    return wxGetHomeDir() + "/." + in + "/";
}

wxString decode_path(const wxString& in) {
    // TODO Stub
    return in;
}

wxString encode_path(const wxString& in) {
    // TODO Stub
    return in;
}

void show_error(wxWindow* parent, const wxString& message) {
    wxMessageDialog(parent, message, _("Error"), wxOK | wxICON_ERROR).ShowModal();
}

void show_info(wxWindow* parent, const wxString& message, const wxString& title = _("Notice")) {
    wxMessageDialog(parent, message, title, wxOK | wxICON_INFORMATION).ShowModal();
}

void fatal_error(wxWindow* parent, const wxString& message) {
    show_error(parent, message);
    throw std::runtime_error(message.ToStdString());
}

wxMenuItem* append_submenu(wxMenu* menu, const wxString& name, const wxString& help, wxMenu* submenu, int id, const wxString& icon) {
    auto* item {new wxMenuItem(menu, id, name, help)};

    set_menu_item_icon(item,icon);
    item->SetSubMenu(submenu);
    menu->Append(item);
    return item;
}

void set_menu_item_icon(wxMenuItem* item, const wxString& icon) {
    if (!icon.IsEmpty()) {
        wxBitmap ico;
        if(ico.LoadFile(var(icon), wxBITMAP_TYPE_PNG))
            item->SetBitmap(ico);
        else
            std::cerr<< var(icon) << " failed to load \n";
    }
}

/*
sub append_submenu {
    my ($self, $menu, $string, $description, $submenu, $id, $icon) = @_;

    $id //= &Wx::NewId();
    my $item = Wx::MenuItem->new($menu, $id, $string, $description // '');
    $self->set_menu_item_icon($item, $icon);
    $item->SetSubMenu($submenu);
    $menu->Append($item);

    return $item;
}
*/

/*
sub scan_serial_ports {
    my ($self) = @_;

    my @ports = ();

    if ($^O eq 'MSWin32') {
        # Windows
        if (eval "use Win32::TieRegistry; 1") {
            my $ts = Win32::TieRegistry->new("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM",
                { Access => 'KEY_READ' });
            if ($ts) {
                # when no serial ports are available, the registry key doesn't exist and
                # TieRegistry->new returns undef
                $ts->Tie(\my %reg);
                push @ports, sort values %reg;
            }
        }
    } else {
        # UNIX and OS X
        push @ports, glob '/dev/{ttyUSB,ttyACM,tty.,cu.,rfcomm}*';
    }

    return grep !/Bluetooth|FireFly/, @ports;
}
*/
/*
sub show_error {
    my ($parent, $message) = @_;
    Wx::MessageDialog->new($parent, $message, 'Error', wxOK | wxICON_ERROR)->ShowModal;
}
*/

std::vector<wxString> open_model(wxWindow* parent, const Settings& settings, wxWindow* top) {
    auto dialog {new wxFileDialog((parent != nullptr ? parent : top), _("Choose one or more files") + wxString(" (STL/OBJ/AMF/3MF):"), ".", "",
    MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST)};
    if (dialog->ShowModal() != wxID_OK) {
        dialog->Destroy();
        return std::vector<wxString>();
    }
    std::vector<wxString> tmp;
    wxArrayString tmpout;
    dialog->GetPaths(tmpout);
    for (const auto& i : tmpout) {
        tmp.push_back(i);
    }
    dialog->Destroy();
    return tmp;
}

}} // namespace Slic3r::GUI

<commit_msg>Refactoring Settings store.<commit_after>#include "misc_ui.hpp"
#include <wx/stdpaths.h>
#include <wx/msgdlg.h>
#include <wx/arrstr.h>

#include <exception>
#include <stdexcept>

namespace Slic3r { namespace GUI {

#ifdef SLIC3R_DEV
void check_version(bool manual)  {
}
#else
void check_version(bool manual)  {
}

#endif

const wxString var(const wxString& in) {
    // TODO replace center string with path to VAR in actual distribution later
    if (VAR_ABS) {
        return wxString(VAR_ABS_PATH) + "/" + in;
    } else {
        return bin() + wxString(VAR_REL) + "/" + in;
    }
}

const wxString bin() {
    wxFileName f(wxStandardPaths::Get().GetExecutablePath());
    wxString appPath(f.GetPath());
    return appPath;
}

/// Returns the path to Slic3r's default user data directory.
const wxString home(const wxString& in) {
    if (the_os == OS::Windows)
        return wxGetHomeDir() + "/" + in + "/";
    return wxGetHomeDir() + "/." + in + "/";
}

wxString decode_path(const wxString& in) {
    // TODO Stub
    return in;
}

wxString encode_path(const wxString& in) {
    // TODO Stub
    return in;
}

void show_error(wxWindow* parent, const wxString& message) {
    wxMessageDialog(parent, message, _("Error"), wxOK | wxICON_ERROR).ShowModal();
}

void show_info(wxWindow* parent, const wxString& message, const wxString& title = _("Notice")) {
    wxMessageDialog(parent, message, title, wxOK | wxICON_INFORMATION).ShowModal();
}

void fatal_error(wxWindow* parent, const wxString& message) {
    show_error(parent, message);
    throw std::runtime_error(message.ToStdString());
}

wxMenuItem* append_submenu(wxMenu* menu, const wxString& name, const wxString& help, wxMenu* submenu, int id, const wxString& icon) {
    auto* item {new wxMenuItem(menu, id, name, help)};

    set_menu_item_icon(item,icon);
    item->SetSubMenu(submenu);
    menu->Append(item);
    return item;
}

void set_menu_item_icon(wxMenuItem* item, const wxString& icon) {
    if (!icon.IsEmpty()) {
        wxBitmap ico;
        if(ico.LoadFile(var(icon), wxBITMAP_TYPE_PNG))
            item->SetBitmap(ico);
        else
            std::cerr<< var(icon) << " failed to load \n";
    }
}

/*
sub append_submenu {
    my ($self, $menu, $string, $description, $submenu, $id, $icon) = @_;

    $id //= &Wx::NewId();
    my $item = Wx::MenuItem->new($menu, $id, $string, $description // '');
    $self->set_menu_item_icon($item, $icon);
    $item->SetSubMenu($submenu);
    $menu->Append($item);

    return $item;
}
*/

/*
sub scan_serial_ports {
    my ($self) = @_;

    my @ports = ();

    if ($^O eq 'MSWin32') {
        # Windows
        if (eval "use Win32::TieRegistry; 1") {
            my $ts = Win32::TieRegistry->new("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM",
                { Access => 'KEY_READ' });
            if ($ts) {
                # when no serial ports are available, the registry key doesn't exist and
                # TieRegistry->new returns undef
                $ts->Tie(\my %reg);
                push @ports, sort values %reg;
            }
        }
    } else {
        # UNIX and OS X
        push @ports, glob '/dev/{ttyUSB,ttyACM,tty.,cu.,rfcomm}*';
    }

    return grep !/Bluetooth|FireFly/, @ports;
}
*/
/*
sub show_error {
    my ($parent, $message) = @_;
    Wx::MessageDialog->new($parent, $message, 'Error', wxOK | wxICON_ERROR)->ShowModal;
}
*/

std::vector<wxString> open_model(wxWindow* parent, wxWindow* top) {
    auto dialog {new wxFileDialog((parent != nullptr ? parent : top), _("Choose one or more files") + wxString(" (STL/OBJ/AMF/3MF):"), ".", "",
    MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST)};
    if (dialog->ShowModal() != wxID_OK) {
        dialog->Destroy();
        return std::vector<wxString>();
    }
    std::vector<wxString> tmp;
    wxArrayString tmpout;
    dialog->GetPaths(tmpout);
    for (const auto& i : tmpout) {
        tmp.push_back(i);
    }
    dialog->Destroy();
    return tmp;
}

}} // namespace Slic3r::GUI

<|endoftext|>


<commit_before>#include "Hearthstone.h"

#include <QFile>
#include <QDesktopServices>
#include <QSettings>
#include <QTextStream>
#include <QRegExp>

#include <QJsonDocument>
#include <QJsonObject>

#include <QDirIterator>
#include <QDateTime>

#ifdef Q_OS_MAC
#include "OSXWindowCapture.h"
#elif defined Q_OS_WIN
#include "WinWindowCapture.h"
#include "Shlobj.h"
#endif

DEFINE_SINGLETON_SCOPE( Hearthstone );

Hearthstone::Hearthstone()
 : mCapture( NULL ), mGameRunning( false ), mGameHasFocus( false )
{
#ifdef Q_OS_MAC
  mCapture = new OSXWindowCapture();
#elif defined Q_OS_WIN
  mCapture = new WinWindowCapture();
#endif

  // On OS X, WindowFound is quite CPU intensive
  // Starting time for HS is also long
  // So just check only once in a while
  mTimer = new QTimer( this );
  connect( mTimer, &QTimer::timeout, this, &Hearthstone::Update );
#ifdef Q_OS_MAC
  mTimer->start( 5000 );
#else
  mTimer->start( 250 );
#endif
}

Hearthstone::~Hearthstone() {
  if( mCapture != NULL )
    delete mCapture;
}

void Hearthstone::Update() {
  bool isRunning = mCapture->WindowFound();

  if( isRunning ) {
    bool hasFocus = mCapture->HasFocus();
    if( mGameHasFocus != hasFocus ) {
      mGameHasFocus = hasFocus;
      emit FocusChanged( hasFocus );
    }

    static int lastLeft = 0, lastTop = 0, lastWidth = 0, lastHeight = 0;
    if( lastLeft != mCapture->Left() || lastTop != mCapture->Top() ||
        lastWidth != mCapture->Width() || lastHeight != mCapture->Height() )
    {
      lastLeft = mCapture->Left(),
               lastTop = mCapture->Top(),
               lastWidth = mCapture->Width(),
               lastHeight = mCapture->Height();

      DBG( "HS window changed %d %d %d %d", lastLeft, lastTop, lastWidth, lastHeight );
      emit GameWindowChanged( lastLeft, lastTop, lastWidth, lastHeight );
    }
  }

  if( mGameRunning != isRunning ) {
    mGameRunning = isRunning;

    if( isRunning ) {
      LOG( "Hearthstone is running" );
      emit GameStarted();
    } else {
      LOG( "Hearthstone stopped" );
      emit GameStopped();
    }
  }
}

QString Hearthstone::ReadAgentAttribute( const char *attributeName ) const {
#ifdef Q_OS_MAC
  QString path = "/Users/Shared/Battle.net/Agent/agent.db";
#elif defined Q_OS_WIN
  wchar_t buffer[ MAX_PATH ];
  SHGetSpecialFolderPathW( NULL, buffer, CSIDL_COMMON_APPDATA, FALSE );
  QString programData = QString::fromWCharArray( buffer );
  QString path = programData + "\\Battle.net\\Agent\\agent.db";
#endif

  QFile file( path );
  if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
    DBG( "Couldn't open %s (%d)", qt2cstr( path ), file.error() );
    return "";
  }

  QString contents = file.readAll();
  QJsonDocument doc = QJsonDocument::fromJson( contents.toUtf8() );
  QJsonObject root = doc.object();

  QJsonObject hs = root["/game/hs_beta"].toObject()["resource"].toObject()["game"].toObject();
  return hs[ QString( attributeName ) ].toString();
}

bool Hearthstone::GameRunning() const {
  return mGameRunning;
}

#ifdef Q_OS_WIN
inline float roundf( float x ) {
   return x >= 0.0f ? floorf( x + 0.5f ) : ceilf( x - 0.5f );
}
#endif

bool Hearthstone::CaptureWholeScreen( QPixmap *screen ) {
  *screen = mCapture->Capture( 0, 0, Width(), Height() );
  return true;
}

QPixmap Hearthstone::Capture( int canvasWidth, int canvasHeight, int cx, int cy, int cw, int ch )
{
  UNUSED_ARG( canvasWidth );

  int x, y, w, h;

  int windowHeight = mCapture->Height();
  float scale = windowHeight / float( canvasHeight );

  x = roundf( cx * scale );
  y = roundf( cy * scale );

  w = roundf( cw * scale );
  h = roundf( ch * scale );

  return mCapture->Capture( x, y, w, h );
}

void Hearthstone::SetWindowCapture( WindowCapture *windowCapture ) {
  if( mCapture != NULL )
    delete mCapture;

  mCapture = windowCapture;
}

void Hearthstone::EnableLogging() {
  QString path = LogConfigPath();
  QFile file( path );

  bool logModified = false;

  // Read file contents
  QString contents;
  if( file.exists() ) {
    file.open( QIODevice::ReadOnly | QIODevice::Text );
    QTextStream in( &file );
    contents = in.readAll();
    file.close();
  }

  // Check what modules we have to activate
  QStringList modulesToActivate;
  for( int i = 0; i < NUM_LOG_MODULES; i++ ) {
    const char *moduleName = LOG_MODULE_NAMES[ i ];
    QString moduleLine = QString( "[%1]" ).arg( moduleName ) ;
    if( !contents.contains( moduleLine ) ) {
      contents += "\n";
      contents += moduleLine + "\n";
      contents += "LogLevel=1\n";
      contents += "FilePrinting=true\n";

      DBG( "Activate module %s", moduleName );
      logModified = true;
    }
  }

  QRegExp regexEnabledConsolePrinting( "ConsolePrinting\\s*=\\s*true",
      Qt::CaseInsensitive );
  QRegExp regexDisabledFilePrinting( "FilePrinting\\s*=\\s*false",
      Qt::CaseInsensitive );
  if( contents.contains( regexEnabledConsolePrinting ) ||
      contents.contains( regexDisabledFilePrinting ) )
  {
    contents.replace( regexEnabledConsolePrinting, "FilePrinting=true" );
    contents.replace( regexDisabledFilePrinting, "FilePrinting=true" );

    DBG( "FilePrinting enabled" );
    logModified = true;
  }

  // Finally write updated log.config
  if( logModified ) {
    DBG( "Log modified. Write new version" );

    if( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
      ERR( "Couldn't create file %s", qt2cstr( path ) );
    } else {
      QTextStream out( &file );
      out << contents;
    }
  }

  // Notify about restart if game is running
  Update();
  if( GameRunning() && logModified ) {
    emit GameRequiresRestart();
  }
}

void Hearthstone::DisableLogging() {
  QFile file( LogConfigPath() );
  if( file.exists() ) {
    file.remove();
    LOG( "Ingame log deactivated." );
  }
}

QString Hearthstone::LogConfigPath() const {
#ifdef Q_OS_MAC
  QString homeLocation = QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).first();
  QString configPath = homeLocation + "/Library/Preferences/Blizzard/Hearthstone/log.config";
#elif defined Q_OS_WIN
  wchar_t buffer[ MAX_PATH ];
  SHGetSpecialFolderPathW( NULL, buffer, CSIDL_LOCAL_APPDATA, FALSE );
  QString localAppData = QString::fromWCharArray( buffer );
  QString configPath = localAppData + "/Blizzard/Hearthstone/log.config";
#endif
  return configPath;
}

QString Hearthstone::DetectHearthstonePath() const {
  static QString hsPath;

  if( hsPath.isEmpty() ) {
#ifdef Q_OS_WIN
    QString hsPathByAgent = ReadAgentAttribute( "install_dir" );

    QSettings hsKey( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Hearthstone", QSettings::NativeFormat );
    QString hsPathByRegistry = hsKey.value( "InstallLocation" ).toString();

    if( hsPathByAgent.isEmpty() && hsPathByRegistry.isEmpty() ) {
      LOG( "Game folder not found. Fall back to default game path for now. You should set the path manually in the settings!" );
      hsPath = QString( getenv("PROGRAMFILES") ) + "/Hearthstone";
    } else if( !hsPathByRegistry.isEmpty() ) {
      hsPath = hsPathByRegistry;
    } else {
      hsPath = hsPathByAgent;
    }
#elif defined Q_OS_MAC
    hsPath = ReadAgentAttribute( "install_dir" );
    if( hsPath.isEmpty() ) {
      LOG( "Fall back to default game path. You should set the path manually in the settings!" );
      hsPath = QStandardPaths::standardLocations( QStandardPaths::ApplicationsLocation ).first() + "/Hearthstone";
    }
#endif
  }

  return hsPath;
}

QString Hearthstone::DetectRegion() const {
  QString region = "";

#ifdef Q_OS_MAC
  QString homeLocation = QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).first();
  QString path = homeLocation + "/Library/Application Support/Battle.net/";
#elif defined Q_OS_WIN
  wchar_t buffer[ MAX_PATH ];
  SHGetSpecialFolderPathW( NULL, buffer, CSIDL_LOCAL_APPDATA, FALSE );
  QString localAppData = QString::fromWCharArray( buffer );
  QString path = localAppData + "/Battle.net/";
#endif

  QDirIterator it( path, QStringList() << "*.config" );
  uint lastModifiedTime = 0;
  QString lastModifiedPath;
  while( it.hasNext() ) {
    it.next();

    uint modifiedTime = it.fileInfo().lastModified().toTime_t();
    if( modifiedTime > lastModifiedTime ) {
      lastModifiedPath = it.fileInfo().absoluteFilePath();
      lastModifiedTime = modifiedTime;
    }
  }

  if( !lastModifiedPath.isEmpty() ) {
    QFile file(lastModifiedPath);
    LOG( "File %s", qt2cstr( lastModifiedPath ) );
    if( file.open( QIODevice::ReadOnly ) ) {
      QByteArray data = file.readAll();
      QJsonDocument doc = QJsonDocument::fromJson( data );
      QJsonObject root = doc.object();

      region = root["User"].toObject()
        ["Client"].toObject()
        ["PlayScreen"].toObject()
        ["GameFamily"].toObject()
        ["WTCG"].toObject()
        ["LastSelectedGameRegion"].toString();
    } else {
      LOG( "Couldn't open config file %s", qt2cstr( lastModifiedPath ) );
    }
  }

  return region;
}

int Hearthstone::Width() const {
  return mCapture->Width();
}

int Hearthstone::Height() const {
  return mCapture->Height();
}

bool Hearthstone::HasFocus() const {
  return mGameHasFocus;
}
<commit_msg>Fix region detection on windows<commit_after>#include "Hearthstone.h"

#include <QFile>
#include <QDesktopServices>
#include <QSettings>
#include <QTextStream>
#include <QRegExp>

#include <QJsonDocument>
#include <QJsonObject>

#include <QDirIterator>
#include <QDateTime>

#ifdef Q_OS_MAC
#include "OSXWindowCapture.h"
#elif defined Q_OS_WIN
#include "WinWindowCapture.h"
#include "Shlobj.h"
#endif

DEFINE_SINGLETON_SCOPE( Hearthstone );

Hearthstone::Hearthstone()
 : mCapture( NULL ), mGameRunning( false ), mGameHasFocus( false )
{
#ifdef Q_OS_MAC
  mCapture = new OSXWindowCapture();
#elif defined Q_OS_WIN
  mCapture = new WinWindowCapture();
#endif

  // On OS X, WindowFound is quite CPU intensive
  // Starting time for HS is also long
  // So just check only once in a while
  mTimer = new QTimer( this );
  connect( mTimer, &QTimer::timeout, this, &Hearthstone::Update );
#ifdef Q_OS_MAC
  mTimer->start( 5000 );
#else
  mTimer->start( 250 );
#endif
}

Hearthstone::~Hearthstone() {
  if( mCapture != NULL )
    delete mCapture;
}

void Hearthstone::Update() {
  bool isRunning = mCapture->WindowFound();

  if( isRunning ) {
    bool hasFocus = mCapture->HasFocus();
    if( mGameHasFocus != hasFocus ) {
      mGameHasFocus = hasFocus;
      emit FocusChanged( hasFocus );
    }

    static int lastLeft = 0, lastTop = 0, lastWidth = 0, lastHeight = 0;
    if( lastLeft != mCapture->Left() || lastTop != mCapture->Top() ||
        lastWidth != mCapture->Width() || lastHeight != mCapture->Height() )
    {
      lastLeft = mCapture->Left(),
               lastTop = mCapture->Top(),
               lastWidth = mCapture->Width(),
               lastHeight = mCapture->Height();

      DBG( "HS window changed %d %d %d %d", lastLeft, lastTop, lastWidth, lastHeight );
      emit GameWindowChanged( lastLeft, lastTop, lastWidth, lastHeight );
    }
  }

  if( mGameRunning != isRunning ) {
    mGameRunning = isRunning;

    if( isRunning ) {
      LOG( "Hearthstone is running" );
      emit GameStarted();
    } else {
      LOG( "Hearthstone stopped" );
      emit GameStopped();
    }
  }
}

QString Hearthstone::ReadAgentAttribute( const char *attributeName ) const {
#ifdef Q_OS_MAC
  QString path = "/Users/Shared/Battle.net/Agent/agent.db";
#elif defined Q_OS_WIN
  wchar_t buffer[ MAX_PATH ];
  SHGetSpecialFolderPathW( NULL, buffer, CSIDL_COMMON_APPDATA, FALSE );
  QString programData = QString::fromWCharArray( buffer );
  QString path = programData + "\\Battle.net\\Agent\\agent.db";
#endif

  QFile file( path );
  if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
    DBG( "Couldn't open %s (%d)", qt2cstr( path ), file.error() );
    return "";
  }

  QString contents = file.readAll();
  QJsonDocument doc = QJsonDocument::fromJson( contents.toUtf8() );
  QJsonObject root = doc.object();

  QJsonObject hs = root["/game/hs_beta"].toObject()["resource"].toObject()["game"].toObject();
  return hs[ QString( attributeName ) ].toString();
}

bool Hearthstone::GameRunning() const {
  return mGameRunning;
}

#ifdef Q_OS_WIN
inline float roundf( float x ) {
   return x >= 0.0f ? floorf( x + 0.5f ) : ceilf( x - 0.5f );
}
#endif

bool Hearthstone::CaptureWholeScreen( QPixmap *screen ) {
  *screen = mCapture->Capture( 0, 0, Width(), Height() );
  return true;
}

QPixmap Hearthstone::Capture( int canvasWidth, int canvasHeight, int cx, int cy, int cw, int ch )
{
  UNUSED_ARG( canvasWidth );

  int x, y, w, h;

  int windowHeight = mCapture->Height();
  float scale = windowHeight / float( canvasHeight );

  x = roundf( cx * scale );
  y = roundf( cy * scale );

  w = roundf( cw * scale );
  h = roundf( ch * scale );

  return mCapture->Capture( x, y, w, h );
}

void Hearthstone::SetWindowCapture( WindowCapture *windowCapture ) {
  if( mCapture != NULL )
    delete mCapture;

  mCapture = windowCapture;
}

void Hearthstone::EnableLogging() {
  QString path = LogConfigPath();
  QFile file( path );

  bool logModified = false;

  // Read file contents
  QString contents;
  if( file.exists() ) {
    file.open( QIODevice::ReadOnly | QIODevice::Text );
    QTextStream in( &file );
    contents = in.readAll();
    file.close();
  }

  // Check what modules we have to activate
  QStringList modulesToActivate;
  for( int i = 0; i < NUM_LOG_MODULES; i++ ) {
    const char *moduleName = LOG_MODULE_NAMES[ i ];
    QString moduleLine = QString( "[%1]" ).arg( moduleName ) ;
    if( !contents.contains( moduleLine ) ) {
      contents += "\n";
      contents += moduleLine + "\n";
      contents += "LogLevel=1\n";
      contents += "FilePrinting=true\n";

      DBG( "Activate module %s", moduleName );
      logModified = true;
    }
  }

  QRegExp regexEnabledConsolePrinting( "ConsolePrinting\\s*=\\s*true",
      Qt::CaseInsensitive );
  QRegExp regexDisabledFilePrinting( "FilePrinting\\s*=\\s*false",
      Qt::CaseInsensitive );
  if( contents.contains( regexEnabledConsolePrinting ) ||
      contents.contains( regexDisabledFilePrinting ) )
  {
    contents.replace( regexEnabledConsolePrinting, "FilePrinting=true" );
    contents.replace( regexDisabledFilePrinting, "FilePrinting=true" );

    DBG( "FilePrinting enabled" );
    logModified = true;
  }

  // Finally write updated log.config
  if( logModified ) {
    DBG( "Log modified. Write new version" );

    if( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
      ERR( "Couldn't create file %s", qt2cstr( path ) );
    } else {
      QTextStream out( &file );
      out << contents;
    }
  }

  // Notify about restart if game is running
  Update();
  if( GameRunning() && logModified ) {
    emit GameRequiresRestart();
  }
}

void Hearthstone::DisableLogging() {
  QFile file( LogConfigPath() );
  if( file.exists() ) {
    file.remove();
    LOG( "Ingame log deactivated." );
  }
}

QString Hearthstone::LogConfigPath() const {
#ifdef Q_OS_MAC
  QString homeLocation = QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).first();
  QString configPath = homeLocation + "/Library/Preferences/Blizzard/Hearthstone/log.config";
#elif defined Q_OS_WIN
  wchar_t buffer[ MAX_PATH ];
  SHGetSpecialFolderPathW( NULL, buffer, CSIDL_LOCAL_APPDATA, FALSE );
  QString localAppData = QString::fromWCharArray( buffer );
  QString configPath = localAppData + "/Blizzard/Hearthstone/log.config";
#endif
  return configPath;
}

QString Hearthstone::DetectHearthstonePath() const {
  static QString hsPath;

  if( hsPath.isEmpty() ) {
#ifdef Q_OS_WIN
    QString hsPathByAgent = ReadAgentAttribute( "install_dir" );

    QSettings hsKey( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Hearthstone", QSettings::NativeFormat );
    QString hsPathByRegistry = hsKey.value( "InstallLocation" ).toString();

    if( hsPathByAgent.isEmpty() && hsPathByRegistry.isEmpty() ) {
      LOG( "Game folder not found. Fall back to default game path for now. You should set the path manually in the settings!" );
      hsPath = QString( getenv("PROGRAMFILES") ) + "/Hearthstone";
    } else if( !hsPathByRegistry.isEmpty() ) {
      hsPath = hsPathByRegistry;
    } else {
      hsPath = hsPathByAgent;
    }
#elif defined Q_OS_MAC
    hsPath = ReadAgentAttribute( "install_dir" );
    if( hsPath.isEmpty() ) {
      LOG( "Fall back to default game path. You should set the path manually in the settings!" );
      hsPath = QStandardPaths::standardLocations( QStandardPaths::ApplicationsLocation ).first() + "/Hearthstone";
    }
#endif
  }

  return hsPath;
}

QString Hearthstone::DetectRegion() const {
  QString region = "";

#ifdef Q_OS_MAC
  QString homeLocation = QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).first();
  QString path = homeLocation + "/Library/Application Support/Battle.net/";
#elif defined Q_OS_WIN
  wchar_t buffer[ MAX_PATH ];
  SHGetSpecialFolderPathW( NULL, buffer, CSIDL_APPDATA, FALSE );
  QString localAppData = QString::fromWCharArray( buffer );
  QString path = localAppData + "/Battle.net/";
#endif

  QDirIterator it( path, QStringList() << "*.config" );
  uint lastModifiedTime = 0;
  QString lastModifiedPath;
  while( it.hasNext() ) {
    it.next();

    uint modifiedTime = it.fileInfo().lastModified().toTime_t();
    if( modifiedTime > lastModifiedTime ) {
      lastModifiedPath = it.fileInfo().absoluteFilePath();
      lastModifiedTime = modifiedTime;
    }
  }

  if( !lastModifiedPath.isEmpty() ) {
    QFile file(lastModifiedPath);
    LOG( "File %s", qt2cstr( lastModifiedPath ) );
    if( file.open( QIODevice::ReadOnly ) ) {
      QByteArray data = file.readAll();
      QJsonDocument doc = QJsonDocument::fromJson( data );
      QJsonObject root = doc.object();

      region = root["User"].toObject()
        ["Client"].toObject()
        ["PlayScreen"].toObject()
        ["GameFamily"].toObject()
        ["WTCG"].toObject()
        ["LastSelectedGameRegion"].toString();
    } else {
      LOG( "Couldn't open config file %s", qt2cstr( lastModifiedPath ) );
    }
  }

  return region;
}

int Hearthstone::Width() const {
  return mCapture->Width();
}

int Hearthstone::Height() const {
  return mCapture->Height();
}

bool Hearthstone::HasFocus() const {
  return mGameHasFocus;
}
<|endoftext|>


<commit_before>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
 *                                                                                *
 *  This program is free software; you can redistribute it and/or                    *
 *  modify it under the terms of the GNU General Public License                      *
 *  as published by the Free Software Foundation; either version 2                   *
 *  of the License, or (at your option) any later version.                           *
 *                                                                                *
 *  This program 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 General Public License for more details.                                     *
 *                                                                                *
 *  You should have received a copy of the GNU General Public License                *
 *  along with this program; if not, write to the Free Software                      *
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
 *************************************************************************************/

#include "daemon.h"
#include "serializer.h"
#include "generator.h"
#include "device.h"

#include <QtCore/QTimer>
#include <QtCore/QDebug>

#include <kdemacros.h>
#include <kaction.h>
#include <KLocalizedString>
#include <KActionCollection>
#include <KPluginFactory>

#include <kscreen/config.h>
#include <kscreen/configmonitor.h>

K_PLUGIN_FACTORY(KScreenDaemonFactory, registerPlugin<KScreenDaemon>();)
K_EXPORT_PLUGIN(KScreenDaemonFactory("kscreen", "kscreen"))

KScreenDaemon::KScreenDaemon(QObject* parent, const QList< QVariant >& )
 : KDEDModule(parent)
 , m_monitoredConfig(0)
 , m_iteration(0)
 , m_pendingSave(false)
 , m_monitoring(false)
 , m_timer(new QTimer())
{
    setenv("KSCREEN_BACKEND", "XRandR", 1);
    KActionCollection *coll = new KActionCollection(this);
    KAction* action = coll->addAction("display");
    action->setText(i18n("Switch Display" ));
    action->setGlobalShortcut(KShortcut(Qt::Key_Display));

    connect(Device::self(), SIGNAL(lidIsClosedChanged(bool,bool)), SLOT(lidClosedChanged()));

    m_timer->setInterval(300);
    m_timer->setSingleShot(true);
    connect(m_timer, SIGNAL(timeout()), SLOT(applyGenericConfig()));
    connect(action, SIGNAL(triggered(bool)), SLOT(displayButton()));
    connect(Generator::self(), SIGNAL(ready()), SLOT(init()));
    monitorConnectedChange();
}

KScreenDaemon::~KScreenDaemon()
{
    Generator::destroy();
    Device::destroy();
}

void KScreenDaemon::init()
{
    applyConfig();
}

void KScreenDaemon::applyConfig()
{
    qDebug() << "Applying config";
    if (Serializer::configExists()) {
        applyKnownConfig();
        return;
    }

    applyIdealConfig();
}

void KScreenDaemon::applyKnownConfig()
{
    setMonitorForChanges(false);
    KScreen::Config::setConfig(Serializer::config(Serializer::currentId()));
    setMonitorForChanges(true);
}

void KScreenDaemon::applyIdealConfig()
{
    setMonitorForChanges(true);
    KScreen::Config::setConfig(Generator::self()->idealConfig());
}

void KScreenDaemon::configChanged()
{
    qDebug() << "Change detected";
    if (m_pendingSave) {
        return;
    }

    qDebug() << "Scheduling screen save";
    m_pendingSave = true;
    QMetaObject::invokeMethod(this, "saveCurrentConfig", Qt::QueuedConnection);
}

void KScreenDaemon::saveCurrentConfig()
{
    qDebug() << "Saving current config";
    m_pendingSave = false;
    Serializer::saveConfig(KScreen::Config::current());
}

void KScreenDaemon::displayButton()
{
    qDebug() << "displayBtn triggered";
    if (m_timer->isActive()) {
        qDebug() << "Too fast cowboy";
        return;
    }

    m_timer->start();
}

void KScreenDaemon::applyGenericConfig()
{
    if (m_iteration == 5) {
        m_iteration = 0;
    }

    setMonitorForChanges(true);
    m_iteration++;
    qDebug() << "displayButton: " << m_iteration;
    KScreen::Config::setConfig(Generator::self()->displaySwitch(m_iteration));
}

void KScreenDaemon::lidClosedChanged()
{
    applyIdealConfig();
}

void KScreenDaemon::monitorConnectedChange()
{
    if (!m_monitoredConfig) {
        m_monitoredConfig = KScreen::Config::current();
        KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);
    }

    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        connect(output, SIGNAL(isConnectedChanged()), SLOT(applyConfig()));
    }
}

void KScreenDaemon::setMonitorForChanges(bool enabled)
{
    if (m_monitoring == enabled) {
        return;
    }
    if (!m_monitoredConfig) {
        m_monitoredConfig = KScreen::Config::current();
        KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);
    }

    m_monitoring = enabled;

    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        if (m_monitoring) {
            enableMonitor(output);
        } else {
            disableMonitor(output);
        }
    }
}

void KScreenDaemon::enableMonitor(KScreen::Output* output)
{
    connect(output, SIGNAL(currentModeChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(isEnabledChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(isPrimaryChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(outputChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(clonesChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(posChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(rotationChanged()), SLOT(configChanged()));
}

void KScreenDaemon::disableMonitor(KScreen::Output* output)
{
    output->disconnect();
}<commit_msg>Set the changeForMonitor to true in the next loop<commit_after>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
 *                                                                                *
 *  This program is free software; you can redistribute it and/or                    *
 *  modify it under the terms of the GNU General Public License                      *
 *  as published by the Free Software Foundation; either version 2                   *
 *  of the License, or (at your option) any later version.                           *
 *                                                                                *
 *  This program 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 General Public License for more details.                                     *
 *                                                                                *
 *  You should have received a copy of the GNU General Public License                *
 *  along with this program; if not, write to the Free Software                      *
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
 *************************************************************************************/

#include "daemon.h"
#include "serializer.h"
#include "generator.h"
#include "device.h"

#include <QtCore/QTimer>
#include <QtCore/QDebug>

#include <kdemacros.h>
#include <kaction.h>
#include <KLocalizedString>
#include <KActionCollection>
#include <KPluginFactory>

#include <kscreen/config.h>
#include <kscreen/configmonitor.h>

K_PLUGIN_FACTORY(KScreenDaemonFactory, registerPlugin<KScreenDaemon>();)
K_EXPORT_PLUGIN(KScreenDaemonFactory("kscreen", "kscreen"))

KScreenDaemon::KScreenDaemon(QObject* parent, const QList< QVariant >& )
 : KDEDModule(parent)
 , m_monitoredConfig(0)
 , m_iteration(0)
 , m_pendingSave(false)
 , m_monitoring(false)
 , m_timer(new QTimer())
{
    setenv("KSCREEN_BACKEND", "XRandR", 1);
    KActionCollection *coll = new KActionCollection(this);
    KAction* action = coll->addAction("display");
    action->setText(i18n("Switch Display" ));
    action->setGlobalShortcut(KShortcut(Qt::Key_Display));

    connect(Device::self(), SIGNAL(lidIsClosedChanged(bool,bool)), SLOT(lidClosedChanged()));

    m_timer->setInterval(300);
    m_timer->setSingleShot(true);
    connect(m_timer, SIGNAL(timeout()), SLOT(applyGenericConfig()));
    connect(action, SIGNAL(triggered(bool)), SLOT(displayButton()));
    connect(Generator::self(), SIGNAL(ready()), SLOT(init()));
    monitorConnectedChange();
}

KScreenDaemon::~KScreenDaemon()
{
    Generator::destroy();
    Device::destroy();
}

void KScreenDaemon::init()
{
    applyConfig();
}

void KScreenDaemon::applyConfig()
{
    qDebug() << "Applying config";
    if (Serializer::configExists()) {
        applyKnownConfig();
        return;
    }

    applyIdealConfig();
}

void KScreenDaemon::applyKnownConfig()
{
    setMonitorForChanges(false);
    KScreen::Config::setConfig(Serializer::config(Serializer::currentId()));
    QMetaObject::invokeMethod(this, "setMonitorForChanges", Qt::QueuedConnection, Q_ARG(bool, true));
}

void KScreenDaemon::applyIdealConfig()
{
    setMonitorForChanges(true);
    KScreen::Config::setConfig(Generator::self()->idealConfig());
}

void KScreenDaemon::configChanged()
{
    qDebug() << "Change detected";
    if (m_pendingSave) {
        return;
    }

    qDebug() << "Scheduling screen save";
    m_pendingSave = true;
    QMetaObject::invokeMethod(this, "saveCurrentConfig", Qt::QueuedConnection);
}

void KScreenDaemon::saveCurrentConfig()
{
    qDebug() << "Saving current config";
    m_pendingSave = false;
    Serializer::saveConfig(KScreen::Config::current());
}

void KScreenDaemon::displayButton()
{
    qDebug() << "displayBtn triggered";
    if (m_timer->isActive()) {
        qDebug() << "Too fast cowboy";
        return;
    }

    m_timer->start();
}

void KScreenDaemon::applyGenericConfig()
{
    if (m_iteration == 5) {
        m_iteration = 0;
    }

    setMonitorForChanges(true);
    m_iteration++;
    qDebug() << "displayButton: " << m_iteration;
    KScreen::Config::setConfig(Generator::self()->displaySwitch(m_iteration));
}

void KScreenDaemon::lidClosedChanged()
{
    applyIdealConfig();
}

void KScreenDaemon::monitorConnectedChange()
{
    if (!m_monitoredConfig) {
        m_monitoredConfig = KScreen::Config::current();
        KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);
    }

    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        connect(output, SIGNAL(isConnectedChanged()), SLOT(applyConfig()));
    }
}

void KScreenDaemon::setMonitorForChanges(bool enabled)
{
    if (m_monitoring == enabled) {
        return;
    }
    if (!m_monitoredConfig) {
        m_monitoredConfig = KScreen::Config::current();
        KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);
    }

    m_monitoring = enabled;

    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        if (m_monitoring) {
            enableMonitor(output);
        } else {
            disableMonitor(output);
        }
    }
}

void KScreenDaemon::enableMonitor(KScreen::Output* output)
{
    connect(output, SIGNAL(currentModeChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(isEnabledChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(isPrimaryChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(outputChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(clonesChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(posChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(rotationChanged()), SLOT(configChanged()));
}

void KScreenDaemon::disableMonitor(KScreen::Output* output)
{
    output->disconnect();
}<|endoftext|>


<commit_before>
#include "CTimeManager.h"
#include <GLFW/glfw3.h>

f64 CTimeManager::CUpdateTick::GetTick() const
{
	return Tick;
}

f64 CTimeManager::CUpdateTick::GetElapsedTime() const
{
	return Tick;
}

f64 CTimeManager::CUpdateTick::GetMaxDuration() const
{
	return MaxDuration;
}

f64 CTimeManager::CUpdateTick::GetAccumulator() const
{
	return Accumulator;
}

CTimeManager::CUpdateTick::CUpdateTick(f64 const Duration, f64 const MaxDuration)
{
	this->Tick = Duration;
	this->MaxDuration = MaxDuration;
	this->Accumulator = 0;
}

void CTimeManager::CUpdateTick::Update(f64 const Elapsed)
{
	Accumulator = Min(Accumulator + Elapsed, MaxDuration);

	while (Accumulator > Tick)
	{
		Accumulator -= Tick;
		TriggerEvent(* this);
	}
}

void CTimeManager::Init()
{
	LastTime = glfwGetTime();
	RunTime = ElapsedTime = 0;
	TimeMultiplier = 1;
}

void CTimeManager::Update()
{
	f64 NewTime = glfwGetTime();
	ElapsedTime = (NewTime - LastTime) * TimeMultiplier;
	RunTime += ElapsedTime;
	LastTime = NewTime;

	for (auto & UpdateTick : UpdateTicks)
		UpdateTick->Update(ElapsedTime);
}

void CTimeManager::SkipElapsedTime()
{
	LastTime = glfwGetTime();
}

f64 CTimeManager::GetElapsedTime() const
{
	return ElapsedTime;
}

f64 CTimeManager::GetActualElapsedTime() const
{
	return ElapsedTime / TimeMultiplier;
}

f64 CTimeManager::GetRunTime() const
{
	return RunTime;
}

f64 CTimeManager::GetTimeMultiplier() const
{
	return TimeMultiplier;
}

void CTimeManager::SetTimeMultiplier(f64 const TimeMultiplier)
{
	this->TimeMultiplier = TimeMultiplier;
}

CTimeManager::CUpdateTick * CTimeManager::MakeUpdateTick(f64 const Tick, f32 const MaxDuration)
{
	UpdateTicks.push_back(new CUpdateTick{Tick, MaxDuration});
	return UpdateTicks.back();
}

CTimeManager::CTimeManager()
{
}
<commit_msg>Whitespace<commit_after>
#include "CTimeManager.h"
#include <GLFW/glfw3.h>

f64 CTimeManager::CUpdateTick::GetTick() const
{
	return Tick;
}

f64 CTimeManager::CUpdateTick::GetElapsedTime() const
{
	return Tick;
}

f64 CTimeManager::CUpdateTick::GetMaxDuration() const
{
	return MaxDuration;
}

f64 CTimeManager::CUpdateTick::GetAccumulator() const
{
	return Accumulator;
}

CTimeManager::CUpdateTick::CUpdateTick(f64 const Duration, f64 const MaxDuration)
{
	this->Tick = Duration;
	this->MaxDuration = MaxDuration;
	this->Accumulator = 0;
}

void CTimeManager::CUpdateTick::Update(f64 const Elapsed)
{
	Accumulator = Min(Accumulator + Elapsed, MaxDuration);

	while (Accumulator > Tick)
	{
		Accumulator -= Tick;
		TriggerEvent(* this);
	}
}

void CTimeManager::Init()
{
	LastTime = glfwGetTime();
	RunTime = ElapsedTime = 0;
	TimeMultiplier = 1;
}

void CTimeManager::Update()
{
	f64 NewTime = glfwGetTime();
	ElapsedTime = (NewTime - LastTime) * TimeMultiplier;
	RunTime += ElapsedTime;
	LastTime = NewTime;

	for (auto & UpdateTick : UpdateTicks)
		UpdateTick->Update(ElapsedTime);
}

void CTimeManager::SkipElapsedTime()
{
	LastTime = glfwGetTime();
}

f64 CTimeManager::GetElapsedTime() const
{
	return ElapsedTime;
}

f64 CTimeManager::GetActualElapsedTime() const
{
	return ElapsedTime / TimeMultiplier;
}

f64 CTimeManager::GetRunTime() const
{
	return RunTime;
}

f64 CTimeManager::GetTimeMultiplier() const
{
	return TimeMultiplier;
}

void CTimeManager::SetTimeMultiplier(f64 const TimeMultiplier)
{
	this->TimeMultiplier = TimeMultiplier;
}

CTimeManager::CUpdateTick * CTimeManager::MakeUpdateTick(f64 const Tick, f32 const MaxDuration)
{
	UpdateTicks.push_back(new CUpdateTick{Tick, MaxDuration});
	return UpdateTicks.back();
}

CTimeManager::CTimeManager()
{
}
<|endoftext|>


<commit_before>/*
  MobaTools.h - a library for model railroaders
  Author: fpm, fpm@mnet-mail.de
  Copyright (c) 2019 All right reserved.

  Functions for the stepper part of MobaTools
*/
#include <MobaTools.h>

// Global Data for all instances and classes  --------------------------------
extern uint8_t timerInitialized;

// variables for softLeds
static ledData_t* ledRootP = NULL; //start of ledData-chain
static uint8_t ledNextCyc = TIMERPERIODE  / CYCLETIME;     // next Cycle that is relevant for leds
static uint8_t ledCycleCnt = 0;    // count IRQ cycles within PWM cycle

static ledData_t*  ledDataP;              // pointer to active Led in ISR

void softledISR(uint8_t cyclesLastIRQ) {
    // ---------------------- softleds -----------------------------------------------
    SET_TP2;
    ledCycleCnt += cyclesLastIRQ;
    if ( ledCycleCnt >= ledNextCyc ) {
        // this IRQ is relevant for softleds
        ledNextCyc = LED_CYCLE_MAX; // there must be atleast one IRQ per PWM Cycle
        if ( ledCycleCnt >= LED_CYCLE_MAX ) {
            // start of a new PWM Cycle - switch all leds with rising/falling state to on
            ledCycleCnt = 0;
            for ( ledDataP=ledRootP; ledDataP!=NULL; ledDataP = ledDataP->nextLedDataP ) {
                //SET_TP1;
                // loop over led-objects
                switch ( ledDataP->state ) {
                  case INCBULB:
                  case INCLIN:
                    // switch on led with linear characteristic
                    if (ledDataP->invFlg  ) {
                        #ifdef FAST_PORTWRT
                        *ledDataP->portPin.Adr &= ~ledDataP->portPin.Mask;
                        #else
                        digitalWrite( ledDataP->pin, LOW );
                        #endif
                    } else {
                        #ifdef FAST_PORTWRT
                        *ledDataP->portPin.Adr |= ledDataP->portPin.Mask;
                        #else
                        digitalWrite( ledDataP->pin, HIGH );
                        #endif
                    }
                    // check if led on is reached
                    //if ( ledDataP->aStep >=  LED_STEP_MAX-1 ) {
                    if ( ledDataP->aCycle >=  LED_CYCLE_MAX ) {    // led is full on, remove from active-chain
                        SET_TP4;
                        ledDataP->state = STATE_ON;
                        *ledDataP->backLedDataPP = ledDataP->nextLedDataP;
                        if ( ledDataP->nextLedDataP ) ledDataP->nextLedDataP->backLedDataPP = ledDataP->backLedDataPP;
                        ledDataP->aCycle = 0;
                        CLR_TP4;
                    } else { // switch to next PWM step
                        //ledNextCyc = min( ledDataP->aCycle, ledNextCyc);
                        if ( ledNextCyc > ledDataP->aCycle ) ledNextCyc = ledDataP->aCycle;
                        ledDataP->actPulse = true;
                    }
                    break;
                  case DECBULB:
                  case DECLIN:
                    // switching off led -> next PWM-step
                    //if ( ledDataP->aStep >=  LED_STEP_MAX-1  ) {
                    /*if ( ledDataP->aCycle ==  0  ) {
                        // led is full off, remove from active-chain
                        SET_TP4;
                        ledDataP->state = STATE_OFF;
                        *ledDataP->backLedDataPP = ledDataP->nextLedDataP;
                        if ( ledDataP->nextLedDataP ) ledDataP->nextLedDataP->backLedDataPP = ledDataP->backLedDataPP;
                        CLR_TP4;
                        //ledDataP->aCycle = 0;
                    } else */{ // switch to next PWM step
                        if (ledDataP->invFlg  ) {
                            #ifdef FAST_PORTWRT
                            *ledDataP->portPin.Adr &= ~ledDataP->portPin.Mask;
                            #else
                            digitalWrite( ledDataP->pin, LOW );
                            #endif
                        } else {
                            #ifdef FAST_PORTWRT
                            *ledDataP->portPin.Adr |= ledDataP->portPin.Mask;
                            #else
                            digitalWrite( ledDataP->pin, HIGH );
                            #endif
                        }
                        if ( ledNextCyc > ledDataP->aCycle ) ledNextCyc = ledDataP->aCycle;
                        ledDataP->actPulse = true;
                    }
                    break;
                  default: ;
                } // end of 'switch'
                //CLR_TP1;
            } // end of led loop
        } else { // is switchofftime within PWM cycle
            SET_TP3;
            for ( ledDataP=ledRootP; ledDataP!=NULL; ledDataP = ledDataP->nextLedDataP ) {
                //SET_TP4;
                if ( ledDataP->actPulse ) {
                    // led is within PWM cycle with output high
                    if ( ledDataP->aCycle <= ledCycleCnt ) {
                        uint8_t tmpIx;
                        // End of ON-time is reached
                        SET_TP4;
                        if (ledDataP->invFlg  ) {
                            #ifdef FAST_PORTWRT
                            *ledDataP->portPin.Adr |= ledDataP->portPin.Mask;
                            #else
                            digitalWrite( ledDataP->pin, HIGH );
                            #endif
                        } else {
                            #ifdef FAST_PORTWRT
                            *ledDataP->portPin.Adr &= ~ledDataP->portPin.Mask;
                            #else
                            digitalWrite( ledDataP->pin, LOW );
                            #endif
                        }
                        CLR_TP4;
                        ledDataP->actPulse = false;
                        // determine length of next PWM Cyle
                        //SET_TP1;
                        SET_TP4;
                        ledDataP->aStep += ledDataP->speed;
                        tmpIx = (ledDataP->aStep/DELTASTEPS);
                        if ( tmpIx > LED_IX_MAX ) {
                            // the end is reached
                            CLR_TP4;
                            switch ( ledDataP->state ) {
                              case DECBULB:
                              case DECLIN:
                                // led is off -> remove from chain
                                ledDataP->state = STATE_OFF;
                                *ledDataP->backLedDataPP = ledDataP->nextLedDataP;
                                if ( ledDataP->nextLedDataP ) ledDataP->nextLedDataP->backLedDataPP = ledDataP->backLedDataPP;
                                break;
                              case INCBULB:
                              case INCLIN:
                                // switch permanetly on wirh next cycle
                                ledDataP->aCycle = LED_CYCLE_MAX;
                                break;
                              default:
                                ;
                            }
                            SET_TP4;
                        } else {
                            // we are still in up/down
                            CLR_TP4;
                            switch ( ledDataP->state ) {
                              case INCBULB:
                                ledDataP->aCycle = pgm_read_byte(&(iSteps[tmpIx]));
                                break;
                              case DECBULB:
                                //CLR_TP1;
                                ledDataP->aCycle = LED_CYCLE_MAX-pgm_read_byte(&(iSteps[tmpIx]));
                                //SET_TP1;
                                break;
                              case INCLIN:
                                ledDataP->aCycle = tmpIx;
                                break;
                              case DECLIN:
                                ledDataP->aCycle = LED_CYCLE_MAX - tmpIx;
                                break;
                              default:
                                // no action if state is one of NOTATTACHED, STATE_ON, STATE_OFF
                                break;
                            }
                            SET_TP4;
                        }
                        CLR_TP4;
                    } else {
                       // End of ON-time not yet reached, compute next necessary step
                       CLR_TP3;
                       ledNextCyc = min( ledDataP->aCycle, ledNextCyc);
                       SET_TP3;
                    }
                }
                //CLR_TP4;
            }
            CLR_TP3;
        }
        //CLR_TP3;
     } // end of softleds
    //CLR_TP3;
    nextCycle = min( nextCycle, ( ledNextCyc-ledCycleCnt ) );
    //SET_TP3;
    CLR_TP2;
} //=============================== End of softledISR ========================================
/////////////////////////////////////////////////////////////////////////////
//Class SoftLed - for Led with soft on / soft off ---------------------------
// Version with Software PWM
SoftLed::SoftLed() {
    ledData.speed    = 0;           // defines rising/falling timer
    ledData.aStep    = DELTASTEPS ;          // actual PWM step
    ledData.aCycle   = 0;           // actual cycle ( =length of PWM pule )
    ledData.actPulse = false;       // PWM pulse is active
    ledData.state    = NOTATTACHED; // initialize
    setpoint = OFF ;                // initialize to off
    ledType = LINEAR;
    ledData.nextLedDataP = NULL;    // don't put in ISR chain
    ledData.invFlg = false;
}

void SoftLed::mount( LedStats_t stateVal ) {
    // mount softLed to ISR chain ( if not already in )
    // new active Softleds are always inserted at the beginning of the chain
    // only leds in the ISR chain are processed in ISR
    noInterrupts();
    SET_TP2;
    // check if it's not already active (mounted)
    // Leds must not be mounted twice!
    if ( ledData.state < ACTIVE ) {
        // write backward reference into the existing first entry
        // only if the chain is not empty
        if ( ledRootP ) ledRootP->backLedDataPP = &ledData.nextLedDataP;
        CLR_TP2;
        ledData.nextLedDataP = ledRootP;
        ledRootP = &ledData;
        ledData.backLedDataPP = &ledRootP;
        SET_TP2;
    }
    ledData.state = stateVal;
    CLR_TP2;
    interrupts();
}

uint8_t SoftLed::attach(uint8_t pinArg, uint8_t invArg ){
    // Led-Ausgang mit Softstart.

    ledData.invFlg  = invArg;
    pinMode( pinArg, OUTPUT );
    //DB_PRINT( "Led attached, ledIx = 0x%x, Count = %d", ledIx, ledCount );
    ledData.state   = STATE_OFF ;   // initialize
    riseTime( LED_DEFAULT_RISETIME );
    if ( ledData.invFlg ) {
        digitalWrite( pinArg, HIGH );
    } else {
        digitalWrite( pinArg, LOW );
    }

    #ifdef FAST_PORTWRT
    ledData.portPin.Adr = (byte *) pgm_read_word_near(&port_to_output_PGM[pgm_read_byte_near(&digital_pin_to_port_PGM[pinArg])]);
    ledData.portPin.Mask = pgm_read_byte_near(&digital_pin_to_bit_mask_PGM[pinArg]);
    #else
    ledData.pin=pinArg ;      // Pin-Nbr
    #endif

    if ( !timerInitialized ) seizeTimer1();
    // enable compareB- interrupt
    #if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
        TIMSK |= ( _BV(OCIExB) );    // enable compare interrupts
    #elif defined __AVR_MEGA__
        TIMSKx |= _BV(OCIExB) ;
    #elif defined __STM32F1__
        timer_cc_enable(MT_TIMER, STEP_CHN);
    #endif
    DB_PRINT("IX_MAX=%d, CYCLE_MAX=%d, STEP_MAX=%d, PWMTIME=%d", LED_IX_MAX, LED_CYCLE_MAX, LED_STEP_MAX, LED_PWMTIME );
    return true;
}

void SoftLed::on(){
    if ( ledData.state ==  NOTATTACHED ) return;  // this is not a valid instance
    LedStats_t stateT;
    // Don't do anything if its already ON
    if ( setpoint != ON  ) {
        setpoint        = ON ;
        ledData.aStep   = DELTASTEPS;
        ledData.speed   = ledSpeed;
        if ( ledType == LINEAR ) {
            stateT          = INCLIN;
            ledData.aCycle  = 1;
        } else { // is bulb simulation
            stateT          = INCBULB;
            ledData.aCycle  = iSteps[1];
        }
        mount(stateT);
    }
    //DB_PRINT( "Led %d On, state=%d", ledIx, ledData.state);
}

void SoftLed::off(){
    if ( ledData.state ==  NOTATTACHED ) return; // this is not a valid instance
    LedStats_t stateT;
    // Dont do anything if its already OFF
    if ( setpoint != OFF ) {
        //SET_TP3;
        setpoint            = OFF;
        ledData.aStep       = DELTASTEPS;
        ledData.speed   = ledSpeed;
        if ( ledType == LINEAR ) {
            stateT          = DECLIN;
            ledData.aCycle  = LED_IX_MAX;
        } else { // is bulb simulation
            //CLR_TP3;
            stateT = DECBULB;
            ledData.aCycle = LED_CYCLE_MAX  - iSteps[1];
        }
        //CLR_TP3;
        mount(stateT);
    }
    //DB_PRINT( "Led %d Off, state=%d", ledIx, ledData.state);
}

void SoftLed::toggle( void ) {
    if ( ledData.state ==  NOTATTACHED ) return; // this is not a valid instance
    if ( setpoint == ON  ) off();
    else on();
}

void SoftLed::write( uint8_t setpntVal, uint8_t ledPar ){
    if ( ledData.state ==  NOTATTACHED ) return; // this is not a valid instance
    ledType = ledPar;
    write( setpntVal ) ;
}

void SoftLed::write( uint8_t setpntVal ){
    //DB_PRINT( "LedWrite ix= %d, valid= 0x%x, sp=%d, lT=%d", ledIx, ledValid, setpntVal, ledType );
    if ( ledData.state ==  NOTATTACHED ) return; // this is not a valid instance
    if ( setpntVal == ON ) on(); else off();
    #ifdef debug
    // im Debugmode hier die Led-Daten ausgeben
    //DB_PRINT( "LedData[%d]\n\speed=%d, Type=%d, aStep=%d, stpCnt=%d, state=%d, setpoint= %d", ledValid, ledSpeed, ledType, ledData.aStep, ledData.stpCnt, ledData.state, setpoint);
    //DB_PRINT( "ON=%d, NextCyc=%d, CycleCnt=%d, StepIx=%d, NextStep=%d",
    //         ON, ledNextCyc, ledCycleCnt, ledStepIx, ledNextStep);
    #endif
}

void SoftLed::riseTime( uint16_t riseTime ) {
    if ( ledData.state ==  NOTATTACHED ) return;
    // length of startphase in ms (min 20ms, max 10240ms )
    // The max value ist slower, if CYCLETIME is reduced.
    // risetime is computed to a 'speed' Value with 16 beeing the slowest
    // with speed value = 16 means risetime is (LED_CYCLE_MAX * LED_PWMTIME * DELTATIME / 16)
    // risetime = (LED_CYCLE_MAX * LED_PWMTIME * DELTATIME) / speed
    //
    long riseMax = ((long) LED_CYCLE_MAX * DELTASTEPS * LED_PWMTIME );
    if ( riseTime <= 20 ) riseTime = 20;
    if ( riseTime >= riseMax/16 ) riseTime = riseMax/16;
    int tmp = ( ((long)riseMax  *10) / ( riseTime  ) +5 ) /10;
    ledSpeed = tmp;
    DB_PRINT( "ledSpeed[%d] = %d ( risetime=%d, riseMax=%d, PWMTIME=%d )", ledIx, ledSpeed, riseTime, riseMax, LED_PWMTIME );
}
<commit_msg>Update MoToSoftled.cpp<commit_after>/*
  MobaTools.h - a library for model railroaders
  Author: fpm, fpm@mnet-mail.de
  Copyright (c) 2019 All right reserved.

  Functions for the stepper part of MobaTools
*/
#include <MobaTools.h>

// Global Data for all instances and classes  --------------------------------
extern uint8_t timerInitialized;

// variables for softLeds
static ledData_t* ledRootP = NULL; //start of ledData-chain
static uint8_t ledNextCyc = TIMERPERIODE  / CYCLETIME;     // next Cycle that is relevant for leds
static uint8_t ledCycleCnt = 0;    // count IRQ cycles within PWM cycle

static ledData_t*  ledDataP;              // pointer to active Led in ISR

void softledISR(uint8_t cyclesLastIRQ) {
    // ---------------------- softleds -----------------------------------------------
    SET_TP2;
    ledCycleCnt += cyclesLastIRQ;
    if ( ledCycleCnt >= ledNextCyc ) {
        // this IRQ is relevant for softleds
        ledNextCyc = LED_CYCLE_MAX; // there must be atleast one IRQ per PWM Cycle
        if ( ledCycleCnt >= LED_CYCLE_MAX ) {
            // start of a new PWM Cycle - switch all leds with rising/falling state to on
            ledCycleCnt = 0;
            for ( ledDataP=ledRootP; ledDataP!=NULL; ledDataP = ledDataP->nextLedDataP ) {
                //SET_TP1;
                // loop over led-objects
                switch ( ledDataP->state ) {
                  case INCBULB:
                  case INCLIN:
                    // switch on led with linear characteristic
                    if (ledDataP->invFlg  ) {
                        #ifdef FAST_PORTWRT
                        *ledDataP->portPin.Adr &= ~ledDataP->portPin.Mask;
                        #else
                        digitalWrite( ledDataP->pin, LOW );
                        #endif
                    } else {
                        #ifdef FAST_PORTWRT
                        *ledDataP->portPin.Adr |= ledDataP->portPin.Mask;
                        #else
                        digitalWrite( ledDataP->pin, HIGH );
                        #endif
                    }
                    // check if led on is reached
                    //if ( ledDataP->aStep >=  LED_STEP_MAX-1 ) {
                    if ( ledDataP->aCycle >=  LED_CYCLE_MAX ) {    // led is full on, remove from active-chain
                        SET_TP4;
                        ledDataP->state = STATE_ON;
                        *ledDataP->backLedDataPP = ledDataP->nextLedDataP;
                        if ( ledDataP->nextLedDataP ) ledDataP->nextLedDataP->backLedDataPP = ledDataP->backLedDataPP;
                        ledDataP->aCycle = 0;
                        CLR_TP4;
                    } else { // switch to next PWM step
                        //ledNextCyc = min( ledDataP->aCycle, ledNextCyc);
                        if ( ledNextCyc > ledDataP->aCycle ) ledNextCyc = ledDataP->aCycle;
                        ledDataP->actPulse = true;
                    }
                    break;
                  case DECBULB:
                  case DECLIN:
                    // switching off led -> next PWM-step
                    //if ( ledDataP->aStep >=  LED_STEP_MAX-1  ) {
                    /*if ( ledDataP->aCycle ==  0  ) {
                        // led is full off, remove from active-chain
                        SET_TP4;
                        ledDataP->state = STATE_OFF;
                        *ledDataP->backLedDataPP = ledDataP->nextLedDataP;
                        if ( ledDataP->nextLedDataP ) ledDataP->nextLedDataP->backLedDataPP = ledDataP->backLedDataPP;
                        CLR_TP4;
                        //ledDataP->aCycle = 0;
                    } else */{ // switch to next PWM step
                        if (ledDataP->invFlg  ) {
                            #ifdef FAST_PORTWRT
                            *ledDataP->portPin.Adr &= ~ledDataP->portPin.Mask;
                            #else
                            digitalWrite( ledDataP->pin, LOW );
                            #endif
                        } else {
                            #ifdef FAST_PORTWRT
                            *ledDataP->portPin.Adr |= ledDataP->portPin.Mask;
                            #else
                            digitalWrite( ledDataP->pin, HIGH );
                            #endif
                        }
                        if ( ledNextCyc > ledDataP->aCycle ) ledNextCyc = ledDataP->aCycle;
                        ledDataP->actPulse = true;
                    }
                    break;
                  default: ;
                } // end of 'switch'
                //CLR_TP1;
            } // end of led loop
        } else { // is switchofftime within PWM cycle
            SET_TP3;
            for ( ledDataP=ledRootP; ledDataP!=NULL; ledDataP = ledDataP->nextLedDataP ) {
                //SET_TP4;
                if ( ledDataP->actPulse ) {
                    // led is within PWM cycle with output high
                    if ( ledDataP->aCycle <= ledCycleCnt ) {
                        uint8_t tmpIx;
                        // End of ON-time is reached
                        SET_TP4;
                        if (ledDataP->invFlg  ) {
                            #ifdef FAST_PORTWRT
                            *ledDataP->portPin.Adr |= ledDataP->portPin.Mask;
                            #else
                            digitalWrite( ledDataP->pin, HIGH );
                            #endif
                        } else {
                            #ifdef FAST_PORTWRT
                            *ledDataP->portPin.Adr &= ~ledDataP->portPin.Mask;
                            #else
                            digitalWrite( ledDataP->pin, LOW );
                            #endif
                        }
                        CLR_TP4;
                        ledDataP->actPulse = false;
                        // determine length of next PWM Cyle
                        //SET_TP1;
                        SET_TP4;
                        ledDataP->aStep += ledDataP->speed;
                        tmpIx = (ledDataP->aStep/DELTASTEPS);
                        if ( tmpIx > LED_IX_MAX ) {
                            // the end is reached
                            CLR_TP4;
                            switch ( ledDataP->state ) {
                              case DECBULB:
                              case DECLIN:
                                // led is off -> remove from chain
                                ledDataP->state = STATE_OFF;
                                *ledDataP->backLedDataPP = ledDataP->nextLedDataP;
                                if ( ledDataP->nextLedDataP ) ledDataP->nextLedDataP->backLedDataPP = ledDataP->backLedDataPP;
                                break;
                              case INCBULB:
                              case INCLIN:
                                // switch permanetly on wirh next cycle
                                ledDataP->aCycle = LED_CYCLE_MAX;
                                break;
                              default:
                                ;
                            }
                            SET_TP4;
                        } else {
                            // we are still in up/down
                            CLR_TP4;
                            switch ( ledDataP->state ) {
                              case INCBULB:
                                ledDataP->aCycle = pgm_read_byte(&(iSteps[tmpIx]));
                                break;
                              case DECBULB:
                                //CLR_TP1;
                                ledDataP->aCycle = LED_CYCLE_MAX-pgm_read_byte(&(iSteps[tmpIx]));
                                //SET_TP1;
                                break;
                              case INCLIN:
                                ledDataP->aCycle = tmpIx;
                                break;
                              case DECLIN:
                                ledDataP->aCycle = LED_CYCLE_MAX - tmpIx;
                                break;
                              default:
                                // no action if state is one of NOTATTACHED, STATE_ON, STATE_OFF
                                break;
                            }
                            SET_TP4;
                        }
                        CLR_TP4;
                    } else {
                       // End of ON-time not yet reached, compute next necessary step
                       CLR_TP3;
                       ledNextCyc = min( ledDataP->aCycle, ledNextCyc);
                       SET_TP3;
                    }
                }
                //CLR_TP4;
            }
            CLR_TP3;
        }
        //CLR_TP3;
     } // end of softleds
    //CLR_TP3;
    nextCycle = min( nextCycle, ( ledNextCyc-ledCycleCnt ) );
    //SET_TP3;
    CLR_TP2;
} //=============================== End of softledISR ========================================
/////////////////////////////////////////////////////////////////////////////
//Class SoftLed - for Led with soft on / soft off ---------------------------
// Version with Software PWM
SoftLed::SoftLed() {
    ledData.speed    = 0;           // defines rising/falling timer
    ledData.aStep    = DELTASTEPS ;          // actual PWM step
    ledData.aCycle   = 0;           // actual cycle ( =length of PWM pule )
    ledData.actPulse = false;       // PWM pulse is active
    ledData.state    = NOTATTACHED; // initialize
    setpoint = OFF ;                // initialize to off
    ledType = LINEAR;
    ledData.nextLedDataP = NULL;    // don't put in ISR chain
    ledData.invFlg = false;
}

void SoftLed::mount( LedStats_t stateVal ) {
    // mount softLed to ISR chain ( if not already in )
    // new active Softleds are always inserted at the beginning of the chain
    // only leds in the ISR chain are processed in ISR
    noInterrupts();
    SET_TP2;
    // check if it's not already active (mounted)
    // Leds must not be mounted twice!
    if ( ledData.state < ACTIVE ) {
        // write backward reference into the existing first entry
        // only if the chain is not empty
        if ( ledRootP ) ledRootP->backLedDataPP = &ledData.nextLedDataP;
        CLR_TP2;
        ledData.nextLedDataP = ledRootP;
        ledRootP = &ledData;
        ledData.backLedDataPP = &ledRootP;
        SET_TP2;
    }
    ledData.state = stateVal;
    CLR_TP2;
    interrupts();
}

uint8_t SoftLed::attach(uint8_t pinArg, uint8_t invArg ){
    // Led-Ausgang mit Softstart.

    ledData.invFlg  = invArg;
    pinMode( pinArg, OUTPUT );
    //DB_PRINT( "Led attached, ledIx = 0x%x, Count = %d", ledIx, ledCount );
    ledData.state   = STATE_OFF ;   // initialize
    riseTime( LED_DEFAULT_RISETIME );
    if ( ledData.invFlg ) {
        digitalWrite( pinArg, HIGH );
    } else {
        digitalWrite( pinArg, LOW );
    }

    #ifdef FAST_PORTWRT
    ledData.portPin.Adr = (byte *) pgm_read_word_near(&port_to_output_PGM[pgm_read_byte_near(&digital_pin_to_port_PGM[pinArg])]);
    ledData.portPin.Mask = pgm_read_byte_near(&digital_pin_to_bit_mask_PGM[pinArg]);
    #else
    ledData.pin=pinArg ;      // Pin-Nbr
    #endif

    if ( !timerInitialized ) seizeTimer1();
    // enable compareB- interrupt
    #if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
        TIMSK |= ( _BV(OCIExB) );    // enable compare interrupts
    #elif defined __AVR_MEGA__
        TIMSKx |= _BV(OCIExB) ;
    #elif defined __STM32F1__
        timer_cc_enable(MT_TIMER, STEP_CHN);
    #endif
    DB_PRINT("IX_MAX=%d, CYCLE_MAX=%d, PWMTIME=%d", LED_IX_MAX, LED_CYCLE_MAX, LED_PWMTIME );
    return true;
}

void SoftLed::on(){
    if ( ledData.state ==  NOTATTACHED ) return;  // this is not a valid instance
    LedStats_t stateT;
    // Don't do anything if its already ON
    if ( setpoint != ON  ) {
        setpoint        = ON ;
        ledData.aStep   = DELTASTEPS;
        ledData.speed   = ledSpeed;
        if ( ledType == LINEAR ) {
            stateT          = INCLIN;
            ledData.aCycle  = 1;
        } else { // is bulb simulation
            stateT          = INCBULB;
            ledData.aCycle  = iSteps[1];
        }
        mount(stateT);
    }
    //DB_PRINT( "Led %d On, state=%d", ledIx, ledData.state);
}

void SoftLed::off(){
    if ( ledData.state ==  NOTATTACHED ) return; // this is not a valid instance
    LedStats_t stateT;
    // Dont do anything if its already OFF
    if ( setpoint != OFF ) {
        //SET_TP3;
        setpoint            = OFF;
        ledData.aStep       = DELTASTEPS;
        ledData.speed   = ledSpeed;
        if ( ledType == LINEAR ) {
            stateT          = DECLIN;
            ledData.aCycle  = LED_IX_MAX;
        } else { // is bulb simulation
            //CLR_TP3;
            stateT = DECBULB;
            ledData.aCycle = LED_CYCLE_MAX  - iSteps[1];
        }
        //CLR_TP3;
        mount(stateT);
    }
    //DB_PRINT( "Led %d Off, state=%d", ledIx, ledData.state);
}

void SoftLed::toggle( void ) {
    if ( ledData.state ==  NOTATTACHED ) return; // this is not a valid instance
    if ( setpoint == ON  ) off();
    else on();
}

void SoftLed::write( uint8_t setpntVal, uint8_t ledPar ){
    if ( ledData.state ==  NOTATTACHED ) return; // this is not a valid instance
    ledType = ledPar;
    write( setpntVal ) ;
}

void SoftLed::write( uint8_t setpntVal ){
    //DB_PRINT( "LedWrite ix= %d, valid= 0x%x, sp=%d, lT=%d", ledIx, ledValid, setpntVal, ledType );
    if ( ledData.state ==  NOTATTACHED ) return; // this is not a valid instance
    if ( setpntVal == ON ) on(); else off();
    #ifdef debug
    // im Debugmode hier die Led-Daten ausgeben
    //DB_PRINT( "LedData[%d]\n\speed=%d, Type=%d, aStep=%d, stpCnt=%d, state=%d, setpoint= %d", ledValid, ledSpeed, ledType, ledData.aStep, ledData.stpCnt, ledData.state, setpoint);
    //DB_PRINT( "ON=%d, NextCyc=%d, CycleCnt=%d, StepIx=%d, NextStep=%d",
    //         ON, ledNextCyc, ledCycleCnt, ledStepIx, ledNextStep);
    #endif
}

void SoftLed::riseTime( uint16_t riseTime ) {
    if ( ledData.state ==  NOTATTACHED ) return;
    // length of startphase in ms (min 20ms, max 10240ms )
    // The max value ist slower, if CYCLETIME is reduced.
    // risetime is computed to a 'speed' Value with 16 beeing the slowest
    // with speed value = 16 means risetime is (LED_CYCLE_MAX * LED_PWMTIME * DELTATIME / 16)
    // risetime = (LED_CYCLE_MAX * LED_PWMTIME * DELTATIME) / speed
    //
    long riseMax = ((long) LED_CYCLE_MAX * DELTASTEPS * LED_PWMTIME );
    if ( riseTime <= 20 ) riseTime = 20;
    if ( riseTime >= riseMax/16 ) riseTime = riseMax/16;
    int tmp = ( ((long)riseMax  *10) / ( riseTime  ) +5 ) /10;
    ledSpeed = tmp;
    DB_PRINT( "ledSpeed = %d ( risetime=%d, riseMax=%d, PWMTIME=%d )", ledSpeed, riseTime, riseMax, LED_PWMTIME );
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee++ Internals --- Hash Tests
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 **/

#include <ironbeepp/hash.hpp>

#include "gtest/gtest.h"

#include <string>

#include <boost/foreach.hpp>

using namespace std;
using namespace IronBee;

class TestHash : public ::testing::Test
{
public:
    TestHash() :
        m_pool(m_scoped_pool)
    {
        // nop
    }

protected:
    ScopedMemoryPool m_scoped_pool;
    MemoryPool m_pool;
};

TEST_F(TestHash, pointer_hash_const_iterator)
{
    static const char* a = "a";
    static const char* b = "b";
    static const char* c = "c";

    namespace I = Internal;
    ib_hash_t* h;

    ASSERT_EQ(IB_OK, ib_hash_create(&h, m_pool.ib()));

    ib_hash_set(h, "key_a", (void *)a);
    ib_hash_set(h, "key_b", (void *)b);
    ib_hash_set(h, "key_c", (void *)c);

    I::pointer_hash_const_iterator<const char*> b_i(h);
    I::pointer_hash_const_iterator<const char*> e_i;

    EXPECT_TRUE(b_i != e_i);

    multiset<string> found_keys;
    multiset<const char*> found_values;

    found_keys.insert(string(b_i->first.first, b_i->first.second));
    found_values.insert(b_i->second);

    I::pointer_hash_const_iterator<const char*> n_i = b_i;
    EXPECT_TRUE(b_i == n_i);
    ++n_i;
    EXPECT_TRUE(b_i != n_i);
    EXPECT_TRUE(e_i != n_i);

    found_keys.insert(string(n_i->first.first, n_i->first.second));
    found_values.insert(n_i->second);

    ++n_i;
    EXPECT_TRUE(b_i != n_i);
    EXPECT_TRUE(e_i != n_i);

    found_keys.insert(string(n_i->first.first, n_i->first.second));
    found_values.insert(n_i->second);

    ++n_i;
    EXPECT_TRUE(e_i == n_i);

    EXPECT_EQ(3UL, found_keys.size());
    EXPECT_EQ(3UL, found_values.size());
    EXPECT_EQ(1UL, found_keys.count("key_a"));
    EXPECT_EQ(1UL, found_keys.count("key_b"));
    EXPECT_EQ(1UL, found_keys.count("key_c"));
    EXPECT_EQ(1UL, found_values.count(a));
    EXPECT_EQ(1UL, found_values.count(b));
    EXPECT_EQ(1UL, found_values.count(c));
}

TEST_F(TestHash, hash_const_iterator)
{
    static const ConstByteString a = ByteString::create(m_pool, "a");
    static const ConstByteString b = ByteString::create(m_pool, "b");
    static const ConstByteString c = ByteString::create(m_pool, "c");

    namespace I = Internal;
    ib_hash_t* h;

    ASSERT_EQ(IB_OK, ib_hash_create(&h, m_pool.ib()));

    ib_hash_set(h, "key_a", (void *)a.ib());
    ib_hash_set(h, "key_b", (void *)b.ib());
    ib_hash_set(h, "key_c", (void *)c.ib());

    I::hash_const_iterator<ConstByteString> b_i(h);
    I::hash_const_iterator<ConstByteString> e_i;

    EXPECT_TRUE(b_i != e_i);

    multiset<string> found_keys;
    multiset<ConstByteString> found_values;

    found_keys.insert(string(b_i->first.first, b_i->first.second));
    found_values.insert(b_i->second);

    I::hash_const_iterator<ConstByteString> n_i = b_i;
    EXPECT_TRUE(b_i == n_i);
    ++n_i;
    EXPECT_TRUE(b_i != n_i);
    EXPECT_TRUE(e_i != n_i);

    found_keys.insert(string(n_i->first.first, n_i->first.second));
    found_values.insert(n_i->second);

    ++n_i;
    EXPECT_TRUE(b_i != n_i);
    EXPECT_TRUE(e_i != n_i);

    found_keys.insert(string(n_i->first.first, n_i->first.second));
    found_values.insert(n_i->second);

    ++n_i;
    EXPECT_TRUE(e_i == n_i);

    EXPECT_EQ(3UL, found_keys.size());
    EXPECT_EQ(3UL, found_values.size());
    EXPECT_EQ(1UL, found_keys.count("key_a"));
    EXPECT_EQ(1UL, found_keys.count("key_b"));
    EXPECT_EQ(1UL, found_keys.count("key_c"));
    EXPECT_EQ(1UL, found_values.count(a));
    EXPECT_EQ(1UL, found_values.count(b));
    EXPECT_EQ(1UL, found_values.count(c));
}

TEST_F(TestHash, ConstHash)
{
    static const char* a = "a";
    static const char* b = "b";
    static const char* c = "c";

    ib_hash_t* h;

    ASSERT_EQ(IB_OK, ib_hash_create(&h, m_pool.ib()));

    ib_hash_set(h, "key_a", (void *)a);
    ib_hash_set(h, "key_b", (void *)b);
    ib_hash_set(h, "key_c", (void *)c);

    ConstHash<const char*> hash(h);

    EXPECT_EQ(h, hash.ib());

    multiset<string> found_keys;
    multiset<const char*> found_values;
    BOOST_FOREACH(ConstHash<const char*>::const_reference v, hash) {
        found_keys.insert(string(v.first.first, v.first.second));
        found_values.insert(v.second);
    }
    EXPECT_EQ(3UL, found_keys.size());
    EXPECT_EQ(3UL, found_values.size());
    EXPECT_EQ(1UL, found_keys.count("key_a"));
    EXPECT_EQ(1UL, found_keys.count("key_b"));
    EXPECT_EQ(1UL, found_keys.count("key_c"));
    EXPECT_EQ(1UL, found_values.count(a));
    EXPECT_EQ(1UL, found_values.count(b));
    EXPECT_EQ(1UL, found_values.count(c));

    EXPECT_FALSE(hash.empty());
    EXPECT_EQ(3UL, hash.size());
    EXPECT_EQ(m_pool, hash.memory_pool());

    EXPECT_EQ(a, hash.get("key_a", 5));
    EXPECT_EQ(a, hash.get(string("key_a")));
    EXPECT_EQ(a, hash.get(ByteString::create(m_pool, "key_a")));
    EXPECT_EQ(a, hash[string("key_a")]);
    EXPECT_EQ(a, hash[ByteString::create(m_pool, "key_a")]);

    List<const char*> l = List<const char*>::create(m_pool);
    hash.get_all(l);

    EXPECT_EQ(3, l.size());
}

TEST_F(TestHash, PointerHash)
{
    typedef Hash<const char*> hash_t;
    hash_t h = hash_t::create(m_pool);

    ASSERT_TRUE(h);
    EXPECT_TRUE(h.empty());
    EXPECT_EQ(0UL, h.size());

    static const char* a = "a";
    static const char* b = "b";
    static const char* c = "c";

    h.set("key_a", 5, a);
    h.set("key_b", 5, b);
    h.set("key_c", 5, c);

    EXPECT_EQ(3UL, h.size());

    EXPECT_EQ(a, h.get("key_a"));
    EXPECT_EQ(b, h.remove("key_b"));
    EXPECT_EQ(2UL, h.size());
    EXPECT_THROW(h.get("key_b"), enoent);
    h.clear();
    EXPECT_TRUE(h.empty());
    EXPECT_THROW(h.get("key_a"), enoent);
}

TEST_F(TestHash, IBHash)
{
    typedef Hash<ConstByteString> hash_t;
    hash_t h = hash_t::create(m_pool);

    ASSERT_TRUE(h);
    EXPECT_TRUE(h.empty());
    EXPECT_EQ(0UL, h.size());

    static const ConstByteString a = ByteString::create(m_pool, "a");
    static const ConstByteString b = ByteString::create(m_pool, "b");
    static const ConstByteString c = ByteString::create(m_pool, "c");

    h.set("key_a", 5, a);
    h.set("key_b", 5, b);
    h.set("key_c", 5, c);

    EXPECT_EQ(3UL, h.size());

    EXPECT_EQ(a, h.get("key_a"));
    EXPECT_EQ(b, h.remove("key_b"));
    EXPECT_EQ(2UL, h.size());
    EXPECT_THROW(h.get("key_b"), enoent);
    h.clear();
    EXPECT_TRUE(h.empty());
    EXPECT_THROW(h.get("key_a"), enoent);
}
<commit_msg>ironbee++/tests/test_hash: Fix issue with signed vs unsigned.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee++ Internals --- Hash Tests
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 **/

#include <ironbeepp/hash.hpp>

#include "gtest/gtest.h"

#include <string>

#include <boost/foreach.hpp>

using namespace std;
using namespace IronBee;

class TestHash : public ::testing::Test
{
public:
    TestHash() :
        m_pool(m_scoped_pool)
    {
        // nop
    }

protected:
    ScopedMemoryPool m_scoped_pool;
    MemoryPool m_pool;
};

TEST_F(TestHash, pointer_hash_const_iterator)
{
    static const char* a = "a";
    static const char* b = "b";
    static const char* c = "c";

    namespace I = Internal;
    ib_hash_t* h;

    ASSERT_EQ(IB_OK, ib_hash_create(&h, m_pool.ib()));

    ib_hash_set(h, "key_a", (void *)a);
    ib_hash_set(h, "key_b", (void *)b);
    ib_hash_set(h, "key_c", (void *)c);

    I::pointer_hash_const_iterator<const char*> b_i(h);
    I::pointer_hash_const_iterator<const char*> e_i;

    EXPECT_TRUE(b_i != e_i);

    multiset<string> found_keys;
    multiset<const char*> found_values;

    found_keys.insert(string(b_i->first.first, b_i->first.second));
    found_values.insert(b_i->second);

    I::pointer_hash_const_iterator<const char*> n_i = b_i;
    EXPECT_TRUE(b_i == n_i);
    ++n_i;
    EXPECT_TRUE(b_i != n_i);
    EXPECT_TRUE(e_i != n_i);

    found_keys.insert(string(n_i->first.first, n_i->first.second));
    found_values.insert(n_i->second);

    ++n_i;
    EXPECT_TRUE(b_i != n_i);
    EXPECT_TRUE(e_i != n_i);

    found_keys.insert(string(n_i->first.first, n_i->first.second));
    found_values.insert(n_i->second);

    ++n_i;
    EXPECT_TRUE(e_i == n_i);

    EXPECT_EQ(3UL, found_keys.size());
    EXPECT_EQ(3UL, found_values.size());
    EXPECT_EQ(1UL, found_keys.count("key_a"));
    EXPECT_EQ(1UL, found_keys.count("key_b"));
    EXPECT_EQ(1UL, found_keys.count("key_c"));
    EXPECT_EQ(1UL, found_values.count(a));
    EXPECT_EQ(1UL, found_values.count(b));
    EXPECT_EQ(1UL, found_values.count(c));
}

TEST_F(TestHash, hash_const_iterator)
{
    static const ConstByteString a = ByteString::create(m_pool, "a");
    static const ConstByteString b = ByteString::create(m_pool, "b");
    static const ConstByteString c = ByteString::create(m_pool, "c");

    namespace I = Internal;
    ib_hash_t* h;

    ASSERT_EQ(IB_OK, ib_hash_create(&h, m_pool.ib()));

    ib_hash_set(h, "key_a", (void *)a.ib());
    ib_hash_set(h, "key_b", (void *)b.ib());
    ib_hash_set(h, "key_c", (void *)c.ib());

    I::hash_const_iterator<ConstByteString> b_i(h);
    I::hash_const_iterator<ConstByteString> e_i;

    EXPECT_TRUE(b_i != e_i);

    multiset<string> found_keys;
    multiset<ConstByteString> found_values;

    found_keys.insert(string(b_i->first.first, b_i->first.second));
    found_values.insert(b_i->second);

    I::hash_const_iterator<ConstByteString> n_i = b_i;
    EXPECT_TRUE(b_i == n_i);
    ++n_i;
    EXPECT_TRUE(b_i != n_i);
    EXPECT_TRUE(e_i != n_i);

    found_keys.insert(string(n_i->first.first, n_i->first.second));
    found_values.insert(n_i->second);

    ++n_i;
    EXPECT_TRUE(b_i != n_i);
    EXPECT_TRUE(e_i != n_i);

    found_keys.insert(string(n_i->first.first, n_i->first.second));
    found_values.insert(n_i->second);

    ++n_i;
    EXPECT_TRUE(e_i == n_i);

    EXPECT_EQ(3UL, found_keys.size());
    EXPECT_EQ(3UL, found_values.size());
    EXPECT_EQ(1UL, found_keys.count("key_a"));
    EXPECT_EQ(1UL, found_keys.count("key_b"));
    EXPECT_EQ(1UL, found_keys.count("key_c"));
    EXPECT_EQ(1UL, found_values.count(a));
    EXPECT_EQ(1UL, found_values.count(b));
    EXPECT_EQ(1UL, found_values.count(c));
}

TEST_F(TestHash, ConstHash)
{
    static const char* a = "a";
    static const char* b = "b";
    static const char* c = "c";

    ib_hash_t* h;

    ASSERT_EQ(IB_OK, ib_hash_create(&h, m_pool.ib()));

    ib_hash_set(h, "key_a", (void *)a);
    ib_hash_set(h, "key_b", (void *)b);
    ib_hash_set(h, "key_c", (void *)c);

    ConstHash<const char*> hash(h);

    EXPECT_EQ(h, hash.ib());

    multiset<string> found_keys;
    multiset<const char*> found_values;
    BOOST_FOREACH(ConstHash<const char*>::const_reference v, hash) {
        found_keys.insert(string(v.first.first, v.first.second));
        found_values.insert(v.second);
    }
    EXPECT_EQ(3UL, found_keys.size());
    EXPECT_EQ(3UL, found_values.size());
    EXPECT_EQ(1UL, found_keys.count("key_a"));
    EXPECT_EQ(1UL, found_keys.count("key_b"));
    EXPECT_EQ(1UL, found_keys.count("key_c"));
    EXPECT_EQ(1UL, found_values.count(a));
    EXPECT_EQ(1UL, found_values.count(b));
    EXPECT_EQ(1UL, found_values.count(c));

    EXPECT_FALSE(hash.empty());
    EXPECT_EQ(3UL, hash.size());
    EXPECT_EQ(m_pool, hash.memory_pool());

    EXPECT_EQ(a, hash.get("key_a", 5));
    EXPECT_EQ(a, hash.get(string("key_a")));
    EXPECT_EQ(a, hash.get(ByteString::create(m_pool, "key_a")));
    EXPECT_EQ(a, hash[string("key_a")]);
    EXPECT_EQ(a, hash[ByteString::create(m_pool, "key_a")]);

    List<const char*> l = List<const char*>::create(m_pool);
    hash.get_all(l);

    EXPECT_EQ(3UL, l.size());
}

TEST_F(TestHash, PointerHash)
{
    typedef Hash<const char*> hash_t;
    hash_t h = hash_t::create(m_pool);

    ASSERT_TRUE(h);
    EXPECT_TRUE(h.empty());
    EXPECT_EQ(0UL, h.size());

    static const char* a = "a";
    static const char* b = "b";
    static const char* c = "c";

    h.set("key_a", 5, a);
    h.set("key_b", 5, b);
    h.set("key_c", 5, c);

    EXPECT_EQ(3UL, h.size());

    EXPECT_EQ(a, h.get("key_a"));
    EXPECT_EQ(b, h.remove("key_b"));
    EXPECT_EQ(2UL, h.size());
    EXPECT_THROW(h.get("key_b"), enoent);
    h.clear();
    EXPECT_TRUE(h.empty());
    EXPECT_THROW(h.get("key_a"), enoent);
}

TEST_F(TestHash, IBHash)
{
    typedef Hash<ConstByteString> hash_t;
    hash_t h = hash_t::create(m_pool);

    ASSERT_TRUE(h);
    EXPECT_TRUE(h.empty());
    EXPECT_EQ(0UL, h.size());

    static const ConstByteString a = ByteString::create(m_pool, "a");
    static const ConstByteString b = ByteString::create(m_pool, "b");
    static const ConstByteString c = ByteString::create(m_pool, "c");

    h.set("key_a", 5, a);
    h.set("key_b", 5, b);
    h.set("key_c", 5, c);

    EXPECT_EQ(3UL, h.size());

    EXPECT_EQ(a, h.get("key_a"));
    EXPECT_EQ(b, h.remove("key_b"));
    EXPECT_EQ(2UL, h.size());
    EXPECT_THROW(h.get("key_b"), enoent);
    h.clear();
    EXPECT_TRUE(h.empty());
    EXPECT_THROW(h.get("key_a"), enoent);
}
<|endoftext|>