<commit_before>// @(#)alimdc:$Name$:$Id$
// Author: Fons Rademakers  26/11/99

/**************************************************************************
 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// AliRunDB                                                             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <TSystem.h>
#include <TFile.h>
#include <TString.h>
#include <TDatime.h>
#include <TSQLServer.h>
#include <TSQLResult.h>
#include <TGrid.h>

#include "AliStats.h"
#include "AliRawDB.h"

#include "AliRunDB.h"

ClassImp(AliRunDB)

//______________________________________________________________________________
AliRunDB::AliRunDB(const char* localFS, Bool_t rdbms,
		   const char* alienHost, const char* alienDir) :
  fRunDB(NULL),
  fRDBMS(rdbms),
  fAlienHost(alienHost),
  fAlienDir(alienDir)
{
   // Open run database, and get or create tree.

   if (!localFS) return;

   // Get hostname
   char hostname[64], filename[64];

   // check that fs exists (crude check fails if fs is a file)
   gSystem->MakeDirectory(localFS);

   strcpy(hostname, gSystem->HostName());

   char *s;
   if ((s = strchr(hostname, '.')))
      *s = 0;

   sprintf(filename, "%s/%s_rundb.root", localFS, hostname);

   if (!gSystem->AccessPathName(filename, kFileExists))
      fRunDB = new TFile(filename, "UPDATE");
   else
      fRunDB = new TFile(filename, "CREATE", Form("ALICE MDC%d Run DB", AliRawDB::kMDC));
}

//______________________________________________________________________________
AliRunDB::AliRunDB(const AliRunDB& runDB): TObject(runDB)
{
// copy constructor

  Fatal("AliRunDB", "copy constructor not implemented");
}

//______________________________________________________________________________
AliRunDB& AliRunDB::operator = (const AliRunDB& /*runDB*/)
{
// assignment operator

  Fatal("operator =", "assignment operator not implemented");
  return *this;
}

//______________________________________________________________________________
void AliRunDB::Update(AliStats *stats)
{
  UpdateLocal(stats);
  UpdateRDBMS(stats);
  UpdateAliEn(stats);
}

//______________________________________________________________________________
void AliRunDB::UpdateLocal(AliStats *stats)
{
   // Add stats object to database.

   if (!stats || !fRunDB) return;

   TDirectory *ds = gDirectory;
   fRunDB->cd();

   char sname[64];
   char *s = (char*)strrchr(stats->GetFileName(), '/');
   if (s) {
      s++;
      strcpy(sname, s);
   } else
      strcpy(sname, stats->GetFileName());
   s = strchr(sname, '.');
   if (s) *s = 0;

   stats->Write(sname);

   ds->cd();
}

//______________________________________________________________________________
void AliRunDB::UpdateRDBMS(AliStats *stats)
{
   // Add stats object to central MySQL DB.

   if (!stats || !fRDBMS) return;

   char sql[4096];
   char bt[25], et[25];

   strcpy(bt, stats->GetBeginTime().AsSQLString());
   strcpy(et, stats->GetEndTime().AsSQLString());

   sprintf(sql, "INSERT INTO mdc%dcatalog VALUES (0, '%s', %d, "
           "%d, %d, %d, %d, %d, %d, %.2f, '%s', '%s', '%s')", AliRawDB::kMDC,
           stats->GetFileName(), (int)stats->GetFileSize(), stats->GetEvents(),
           stats->GetFirstRun(), stats->GetFirstEvent(), stats->GetLastRun(),
           stats->GetLastEvent(), stats->GetCompressionMode(),
           stats->GetCompressionFactor(), stats->GetFilterState() ? "on" : "off",
           bt, et);

   // open connection to MySQL server on pcsalo
   TSQLServer *db = TSQLServer::Connect("mysql://pcsalo.cern.ch/mdc", "alice", "amdc");

   if (!db || db->IsZombie()) {
      Error("UpdateRDBMS", "failed to connect to MySQL server on pcsalo");
      printf("%s\n", sql);
      delete db;
      return;
   }

   TSQLResult *res = db->Query(sql);

   if (!res) {
      Error("UpdateRDBMS", Form("insert into mdc%dcatalog failed", AliRawDB::kMDC));
      printf("%s\n", sql);
   }

   delete res;
   delete db;
}

//______________________________________________________________________________
void AliRunDB::UpdateAliEn(AliStats *stats)
{
   // Record file in AliEn catalog.

   if (!stats || fAlienHost.IsNull()) return;

   TGrid *g = TGrid::Connect(fAlienHost, "");

   TString lfn = fAlienDir;
   TDatime dt;

   // make a subdirectory for each day
   lfn += "/adc-";
   lfn += dt.GetDate();

   // check if directory exists, if not create it
   Grid_ResultHandle_t res = 0;
   if (!(res = g->OpenDir(lfn))) {
      // directory does not exist, create it
      if (g->Mkdir(lfn) == -1) {
         Error("UpdateAliEn", "cannot create directory %s", lfn.Data());
         lfn = fAlienDir;
      }
   }
   if (res) g->CloseResult(res);

   lfn += "/";
   lfn += gSystem->BaseName(stats->GetFileName());

   Int_t result = g->AddFile(lfn, stats->GetFileName(),
			     (int)stats->GetFileSize());

   if (result == -1) {
      Error("UpdateAliEn", "error adding file to AliEn catalog");
      printf("AliEn: AddFile(%s, %s, %d)\n", lfn.Data(), stats->GetFileName(),
             (int)stats->GetFileSize());
   }

   delete g;
}

//______________________________________________________________________________
void AliRunDB::Close()
{
   // Close run database.

   if (fRunDB) fRunDB->Close();
   delete fRunDB;
}

<commit_msg>Additional protection in case ROOT is compiled without AliEn support<commit_after>// @(#)alimdc:$Name$:$Id$
// Author: Fons Rademakers  26/11/99

/**************************************************************************
 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// AliRunDB                                                             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <TSystem.h>
#include <TFile.h>
#include <TString.h>
#include <TDatime.h>
#include <TSQLServer.h>
#include <TSQLResult.h>
#include <TGrid.h>

#include "AliStats.h"
#include "AliRawDB.h"

#include "AliRunDB.h"

ClassImp(AliRunDB)

//______________________________________________________________________________
AliRunDB::AliRunDB(const char* localFS, Bool_t rdbms,
		   const char* alienHost, const char* alienDir) :
  fRunDB(NULL),
  fRDBMS(rdbms),
  fAlienHost(alienHost),
  fAlienDir(alienDir)
{
   // Open run database, and get or create tree.

   if (!localFS) return;

   // Get hostname
   char hostname[64], filename[64];

   // check that fs exists (crude check fails if fs is a file)
   gSystem->MakeDirectory(localFS);

   strcpy(hostname, gSystem->HostName());

   char *s;
   if ((s = strchr(hostname, '.')))
      *s = 0;

   sprintf(filename, "%s/%s_rundb.root", localFS, hostname);

   if (!gSystem->AccessPathName(filename, kFileExists))
      fRunDB = new TFile(filename, "UPDATE");
   else
      fRunDB = new TFile(filename, "CREATE", Form("ALICE MDC%d Run DB", AliRawDB::kMDC));
}

//______________________________________________________________________________
AliRunDB::AliRunDB(const AliRunDB& runDB): TObject(runDB)
{
// copy constructor

  Fatal("AliRunDB", "copy constructor not implemented");
}

//______________________________________________________________________________
AliRunDB& AliRunDB::operator = (const AliRunDB& /*runDB*/)
{
// assignment operator

  Fatal("operator =", "assignment operator not implemented");
  return *this;
}

//______________________________________________________________________________
void AliRunDB::Update(AliStats *stats)
{
  UpdateLocal(stats);
  UpdateRDBMS(stats);
  UpdateAliEn(stats);
}

//______________________________________________________________________________
void AliRunDB::UpdateLocal(AliStats *stats)
{
   // Add stats object to database.

   if (!stats || !fRunDB) return;

   TDirectory *ds = gDirectory;
   fRunDB->cd();

   char sname[64];
   char *s = (char*)strrchr(stats->GetFileName(), '/');
   if (s) {
      s++;
      strcpy(sname, s);
   } else
      strcpy(sname, stats->GetFileName());
   s = strchr(sname, '.');
   if (s) *s = 0;

   stats->Write(sname);

   ds->cd();
}

//______________________________________________________________________________
void AliRunDB::UpdateRDBMS(AliStats *stats)
{
   // Add stats object to central MySQL DB.

   if (!stats || !fRDBMS) return;

   char sql[4096];
   char bt[25], et[25];

   strcpy(bt, stats->GetBeginTime().AsSQLString());
   strcpy(et, stats->GetEndTime().AsSQLString());

   sprintf(sql, "INSERT INTO mdc%dcatalog VALUES (0, '%s', %d, "
           "%d, %d, %d, %d, %d, %d, %.2f, '%s', '%s', '%s')", AliRawDB::kMDC,
           stats->GetFileName(), (int)stats->GetFileSize(), stats->GetEvents(),
           stats->GetFirstRun(), stats->GetFirstEvent(), stats->GetLastRun(),
           stats->GetLastEvent(), stats->GetCompressionMode(),
           stats->GetCompressionFactor(), stats->GetFilterState() ? "on" : "off",
           bt, et);

   // open connection to MySQL server on pcsalo
   TSQLServer *db = TSQLServer::Connect("mysql://pcsalo.cern.ch/mdc", "alice", "amdc");

   if (!db || db->IsZombie()) {
      Error("UpdateRDBMS", "failed to connect to MySQL server on pcsalo");
      printf("%s\n", sql);
      delete db;
      return;
   }

   TSQLResult *res = db->Query(sql);

   if (!res) {
      Error("UpdateRDBMS", Form("insert into mdc%dcatalog failed", AliRawDB::kMDC));
      printf("%s\n", sql);
   }

   delete res;
   delete db;
}

//______________________________________________________________________________
void AliRunDB::UpdateAliEn(AliStats *stats)
{
   // Record file in AliEn catalog.

   if (!stats || fAlienHost.IsNull()) return;

   TGrid *g = TGrid::Connect(fAlienHost, "");

   //Protection in case root is compiled without AliEn support
   if(!g) {
      Error("UpdateAliEn", "ROOT compiled without AliEn support");
      return;
   }

   TString lfn = fAlienDir;
   TDatime dt;

   // make a subdirectory for each day
   lfn += "/adc-";
   lfn += dt.GetDate();

   // check if directory exists, if not create it
   Grid_ResultHandle_t res = 0;
   if (!(res = g->OpenDir(lfn))) {
      // directory does not exist, create it
      if (g->Mkdir(lfn) == -1) {
         Error("UpdateAliEn", "cannot create directory %s", lfn.Data());
         lfn = fAlienDir;
      }
   }
   if (res) g->CloseResult(res);

   lfn += "/";
   lfn += gSystem->BaseName(stats->GetFileName());

   Int_t result = g->AddFile(lfn, stats->GetFileName(),
			     (int)stats->GetFileSize());

   if (result == -1) {
      Error("UpdateAliEn", "error adding file to AliEn catalog");
      printf("AliEn: AddFile(%s, %s, %d)\n", lfn.Data(), stats->GetFileName(),
             (int)stats->GetFileSize());
   }

   delete g;
}

//______________________________________________________________________________
void AliRunDB::Close()
{
   // Close run database.

   if (fRunDB) fRunDB->Close();
   delete fRunDB;
}

<|endoftext|>


<commit_before><commit_msg>iox-#25 Add further info to todo and disable unimplemented tests (again)<commit_after><|endoftext|>


<commit_before>#include "ShelfPlayback.h"

void ShelfPlayback::begin() {

  if (AMP_POWER > 0) {
    // Disable amp
    pinMode(AMP_POWER, OUTPUT);
    digitalWrite(AMP_POWER, LOW);
    Serial.println(F("Amp powered down"));
  }

  // initialise the music player
  if (!_musicPlayer.begin()) { // initialise the music player
    Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    while (1) delay(500);
  }
  Serial.println(F("VS1053 found"));

  /* Fix for the design fuckup of the cheap LC Technology MP3 shield
    see http://www.bajdi.com/lcsoft-vs1053-mp3-module/#comment-33773
    Doesn't hurt for other shields
  */
  _musicPlayer.sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_DDR);
  _musicPlayer.sciWrite(VS1053_REG_WRAM, 0x0003);
  _musicPlayer.GPIO_digitalWrite(0x0000);
  _musicPlayer.softReset();

  Serial.println(F("VS1053 soft reset done"));

  if (patchVS1053()) {
#ifdef USE_DIFFERENTIAL_OUTPUT
    // Enable differential output
    uint16_t mode = VS1053_MODE_SM_DIFF | VS1053_MODE_SM_SDINEW;
    _musicPlayer.sciWrite(VS1053_REG_MODE, mode);
#else
    // Enable Mono Output
    _musicPlayer.sciWrite(VS1053_REG_WRAMADDR, 0x1e09);
    _musicPlayer.sciWrite(VS1053_REG_WRAM, 0x0001);
#endif
    Serial.println(F("VS1053 patch installed"));
  } else {
    Serial.println(F("Could not load patch"));
  }

  Serial.print(F("SampleRate "));
  Serial.println(_musicPlayer.sciRead(VS1053_REG_AUDATA));

  _musicPlayer.setVolume(_volume, _volume);

  setBassAndTreble(TREBLE_AMPLITUDE, TREBLE_FREQLIMIT, BASS_AMPLITUDE, BASS_FREQLIMIT);

  _musicPlayer.dumpRegs();

  Serial.println(F("VS1053 found"));
}

bool ShelfPlayback::switchFolder(const char *folder) {
  Serial.print(F("Switching folder to "));
  Serial.println(folder);

  if (!_SD.exists(folder)) {
    Serial.println(F("Folder does not exist"));
    return false;
  }
  stopPlayback();
  _SD.chdir(folder);
  _SD.vwd()->rewind();
  _currentFile = "";
  return true;
}

void ShelfPlayback::resumePlayback() {
  if(_playing == PLAYBACK_PAUSED) {
    _musicPlayer.pausePlaying(false);
    _playing = PLAYBACK_FILE;
  }
}

void ShelfPlayback::pausePlayback() {
  if(_playing == PLAYBACK_FILE) {
    _musicPlayer.pausePlaying(false);
    _playing = PLAYBACK_PAUSED;
  }
}

void ShelfPlayback::stopPlayback() {
  Serial.println(F("Stopping playback"));
  if(_playing == PLAYBACK_NO) {
    Serial.println(F("Already stopped"));
    return;
  }

  if (AMP_POWER > 0) {
    digitalWrite(AMP_POWER, LOW);
  }
  if(_playing == PLAYBACK_FILE) {
    _musicPlayer.stopPlaying();
  }
  _playing = PLAYBACK_NO;
  if(isNight()) {
    _lastNightActivity = millis();
  }
}

void ShelfPlayback::startPlayback() {
  // IO takes time, reset watchdog timer so it does not kill us
  ESP.wdtFeed();
  SdFile file;
  _SD.vwd()->rewind();

  char filenameChar[100];
  _SD.vwd()->getName(filenameChar, 100);
  String dirname = "/" + String(filenameChar) + "/";

  String nextFile = "";

  while (file.openNext(_SD.vwd(), O_READ))
  {

    file.getName(filenameChar, 100);
    file.close();

    if (file.isDir() || !_musicPlayer.isMP3File(filenameChar)) {
      Serial.print(F("Ignoring ")); Serial.println(filenameChar);
      continue;
    }

    String tmpFile = String(filenameChar);
    if (_currentFile < tmpFile && (tmpFile < nextFile || nextFile == "")) {
      nextFile = tmpFile;
    }
  }

  // Start folder from the beginning
  if (nextFile == "" && _currentFile != "") {
    _currentFile = "";
    startPlayback();
    return;
  }

  // No _currentFile && no nextFile => Nothing to play!
  if (nextFile == "") {
    Serial.print(F("No mp3 files in ")); Serial.println(dirname);
    stopPlayback();
    return;
  }

  startFilePlayback((char *)dirname.c_str(), (char *)nextFile.c_str());
}

void ShelfPlayback::startFilePlayback(const char* folder, const char* nextFile) {
  Serial.print(F("Playing ")); Serial.print(folder); Serial.println(nextFile);

  _playing = PLAYBACK_FILE;
  _currentFile = nextFile;

  char fullPath[116] = "";
  strcat(fullPath, folder);
  strcat(fullPath, nextFile);
  _musicPlayer.startPlayingFile(fullPath);

  if (AMP_POWER > 0) {
    digitalWrite(AMP_POWER, HIGH);
  }
}

void ShelfPlayback::skipFile() {
  _musicPlayer.stopPlaying();
  startPlayback();
}

void ShelfPlayback::volume(uint8_t volume) {
  if(volume > 50) {
    _volume = 50;
  } else {
    _volume = volume;
  }

  uint8_t calcVolume = volume;

  if(isNight()) {
    calcVolume = 50 - (NIGHT_FACTOR * (50 - _volume));
  }
  _musicPlayer.setVolume(calcVolume, calcVolume);
}

void ShelfPlayback::volumeUp() {
  if(_volume < 5) {
    volume(0);
  } else {
    volume(_volume - 5);
  }
}

void ShelfPlayback::volumeDown() {
  volume(_volume + 5);
}

void ShelfPlayback::setBassAndTreble(uint8_t trebleAmplitude, uint8_t trebleFreqLimit, uint8_t bassAmplitude, uint8_t bassFreqLimit) {
  uint16_t bassReg = 0;
  bassReg |= trebleAmplitude;
  bassReg <<= 4;
  bassReg |= trebleFreqLimit;
  bassReg <<= 4;
  bassReg |= bassAmplitude;
  bassReg <<= 4;
  bassReg |= bassFreqLimit;
  Serial.printf(F("bass value: %04x\n"), bassReg);
  _musicPlayer.sciWrite(VS1053_REG_BASS, bassReg);
}

bool ShelfPlayback::patchVS1053() {
  Serial.println(F("Installing patch to VS1053"));

  SdFile file;
  if (!file.open("patches.053", O_READ)) return false;

  uint16_t addr, n, val, i = 0;

  while (file.read(&addr, 2) && file.read(&n, 2)) {
    i += 2;
    if (n & 0x8000U) {
      n &= 0x7FFF;
      if (!file.read(&val, 2)) {
        file.close();
        return false;
      }
      while (n--) {
        _musicPlayer.sciWrite(addr, val);
      }
    } else {
      while (n--) {
        if (!file.read(&val, 2)) {
          file.close();
          return false;
        }
        i++;
        _musicPlayer.sciWrite(addr, val);
      }
    }
  }
  file.close();

  Serial.print(F("Number of bytes: ")); Serial.println(i);
  return true;
}

void ShelfPlayback::work() {
  if (_playing == PLAYBACK_FILE) {
    if (_musicPlayer.playingMusic) {
      _musicPlayer.feedBuffer();
    } else {
      startPlayback();
    }
    return;
  }

  if ((_playing == PLAYBACK_NO || _playing == PLAYBACK_PAUSED) && isNight() && (millis() - _lastNightActivity > NIGHT_TIMEOUT)) {
    stopNight();
  }
}

void ShelfPlayback::startNight() {
  _lastNightActivity = millis();
  _nightMode = true;
  volume(_volume);
}

bool ShelfPlayback::isNight() {
  return _nightMode;
}

void ShelfPlayback::stopNight() {
  _nightMode = false;
  volume(_volume);
}
<commit_msg>Fix pause/nightmode bugs<commit_after>#include "ShelfPlayback.h"

void ShelfPlayback::begin() {

  if (AMP_POWER > 0) {
    // Disable amp
    pinMode(AMP_POWER, OUTPUT);
    digitalWrite(AMP_POWER, LOW);
    Serial.println(F("Amp powered down"));
  }

  // initialise the music player
  if (!_musicPlayer.begin()) { // initialise the music player
    Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    while (1) delay(500);
  }
  Serial.println(F("VS1053 found"));

  /* Fix for the design fuckup of the cheap LC Technology MP3 shield
    see http://www.bajdi.com/lcsoft-vs1053-mp3-module/#comment-33773
    Doesn't hurt for other shields
  */
  _musicPlayer.sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_DDR);
  _musicPlayer.sciWrite(VS1053_REG_WRAM, 0x0003);
  _musicPlayer.GPIO_digitalWrite(0x0000);
  _musicPlayer.softReset();

  Serial.println(F("VS1053 soft reset done"));

  if (patchVS1053()) {
#ifdef USE_DIFFERENTIAL_OUTPUT
    // Enable differential output
    uint16_t mode = VS1053_MODE_SM_DIFF | VS1053_MODE_SM_SDINEW;
    _musicPlayer.sciWrite(VS1053_REG_MODE, mode);
#else
    // Enable Mono Output
    _musicPlayer.sciWrite(VS1053_REG_WRAMADDR, 0x1e09);
    _musicPlayer.sciWrite(VS1053_REG_WRAM, 0x0001);
#endif
    Serial.println(F("VS1053 patch installed"));
  } else {
    Serial.println(F("Could not load patch"));
  }

  Serial.print(F("SampleRate "));
  Serial.println(_musicPlayer.sciRead(VS1053_REG_AUDATA));

  _musicPlayer.setVolume(_volume, _volume);

  setBassAndTreble(TREBLE_AMPLITUDE, TREBLE_FREQLIMIT, BASS_AMPLITUDE, BASS_FREQLIMIT);

  _musicPlayer.dumpRegs();

  Serial.println(F("VS1053 found"));
}

bool ShelfPlayback::switchFolder(const char *folder) {
  Serial.print(F("Switching folder to "));
  Serial.println(folder);

  if (!_SD.exists(folder)) {
    Serial.println(F("Folder does not exist"));
    return false;
  }
  stopPlayback();
  _SD.chdir(folder);
  _SD.vwd()->rewind();
  _currentFile = "";
  return true;
}

void ShelfPlayback::resumePlayback() {
  if(_playing == PLAYBACK_PAUSED) {
    _musicPlayer.pausePlaying(false);
    _playing = PLAYBACK_FILE;
  }
}

void ShelfPlayback::pausePlayback() {
  if(_playing == PLAYBACK_FILE) {
    _musicPlayer.pausePlaying(true);
    _playing = PLAYBACK_PAUSED;
    if(isNight()) {
      _lastNightActivity = millis();
    }
  }
}

void ShelfPlayback::stopPlayback() {
  Serial.println(F("Stopping playback"));
  if(_playing == PLAYBACK_NO) {
    Serial.println(F("Already stopped"));
    return;
  }

  if (AMP_POWER > 0) {
    digitalWrite(AMP_POWER, LOW);
  }
  if(_playing == PLAYBACK_FILE) {
    _musicPlayer.stopPlaying();
  }
  _playing = PLAYBACK_NO;
  if(isNight()) {
    _lastNightActivity = millis();
  }
}

void ShelfPlayback::startPlayback() {
  // IO takes time, reset watchdog timer so it does not kill us
  ESP.wdtFeed();
  SdFile file;
  _SD.vwd()->rewind();

  char filenameChar[100];
  _SD.vwd()->getName(filenameChar, 100);
  String dirname = "/" + String(filenameChar) + "/";

  String nextFile = "";

  while (file.openNext(_SD.vwd(), O_READ))
  {

    file.getName(filenameChar, 100);
    file.close();

    if (file.isDir() || !_musicPlayer.isMP3File(filenameChar)) {
      Serial.print(F("Ignoring ")); Serial.println(filenameChar);
      continue;
    }

    String tmpFile = String(filenameChar);
    if (_currentFile < tmpFile && (tmpFile < nextFile || nextFile == "")) {
      nextFile = tmpFile;
    }
  }

  // Start folder from the beginning
  if (nextFile == "" && _currentFile != "") {
    _currentFile = "";
    startPlayback();
    return;
  }

  // No _currentFile && no nextFile => Nothing to play!
  if (nextFile == "") {
    Serial.print(F("No mp3 files in ")); Serial.println(dirname);
    stopPlayback();
    return;
  }

  startFilePlayback((char *)dirname.c_str(), (char *)nextFile.c_str());
}

void ShelfPlayback::startFilePlayback(const char* folder, const char* nextFile) {
  Serial.print(F("Playing ")); Serial.print(folder); Serial.println(nextFile);

  _playing = PLAYBACK_FILE;
  _currentFile = nextFile;

  char fullPath[116] = "";
  strcat(fullPath, folder);
  strcat(fullPath, nextFile);
  _musicPlayer.startPlayingFile(fullPath);

  if (AMP_POWER > 0) {
    digitalWrite(AMP_POWER, HIGH);
  }
}

void ShelfPlayback::skipFile() {
  _musicPlayer.stopPlaying();
  startPlayback();
}

void ShelfPlayback::volume(uint8_t volume) {
  if(volume > 50) {
    _volume = 50;
  } else {
    _volume = volume;
  }

  uint8_t calcVolume = volume;

  if(isNight()) {
    calcVolume = 50 - (NIGHT_FACTOR * (50 - _volume));
  }
  _musicPlayer.setVolume(calcVolume, calcVolume);
}

void ShelfPlayback::volumeUp() {
  if(_volume < 5) {
    volume(0);
  } else {
    volume(_volume - 5);
  }
}

void ShelfPlayback::volumeDown() {
  volume(_volume + 5);
}

void ShelfPlayback::setBassAndTreble(uint8_t trebleAmplitude, uint8_t trebleFreqLimit, uint8_t bassAmplitude, uint8_t bassFreqLimit) {
  uint16_t bassReg = 0;
  bassReg |= trebleAmplitude;
  bassReg <<= 4;
  bassReg |= trebleFreqLimit;
  bassReg <<= 4;
  bassReg |= bassAmplitude;
  bassReg <<= 4;
  bassReg |= bassFreqLimit;
  Serial.printf(F("bass value: %04x\n"), bassReg);
  _musicPlayer.sciWrite(VS1053_REG_BASS, bassReg);
}

bool ShelfPlayback::patchVS1053() {
  Serial.println(F("Installing patch to VS1053"));

  SdFile file;
  if (!file.open("patches.053", O_READ)) return false;

  uint16_t addr, n, val, i = 0;

  while (file.read(&addr, 2) && file.read(&n, 2)) {
    i += 2;
    if (n & 0x8000U) {
      n &= 0x7FFF;
      if (!file.read(&val, 2)) {
        file.close();
        return false;
      }
      while (n--) {
        _musicPlayer.sciWrite(addr, val);
      }
    } else {
      while (n--) {
        if (!file.read(&val, 2)) {
          file.close();
          return false;
        }
        i++;
        _musicPlayer.sciWrite(addr, val);
      }
    }
  }
  file.close();

  Serial.print(F("Number of bytes: ")); Serial.println(i);
  return true;
}

void ShelfPlayback::work() {
  if (_playing == PLAYBACK_FILE) {
    if (_musicPlayer.playingMusic) {
      _musicPlayer.feedBuffer();
    } else {
      startPlayback();
    }
    return;
  }

  if ((_playing == PLAYBACK_NO || _playing == PLAYBACK_PAUSED) && isNight() && (millis() - _lastNightActivity > NIGHT_TIMEOUT)) {
    stopNight();
  }
}

void ShelfPlayback::startNight() {
  _lastNightActivity = millis();
  _nightMode = true;
  volume(_volume);
}

bool ShelfPlayback::isNight() {
  return _nightMode;
}

void ShelfPlayback::stopNight() {
  _nightMode = false;
  volume(_volume);
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "ut_mpannableviewport.h"
#include <mtheme.h>
#include <mpositionindicator.h>
#include "mpannableviewport.h"
#include "mpannableviewport_p.h"
#include <QGraphicsWidget>
#include <QGraphicsLinearLayout>
#include <QTest>
#include <mapplication.h>
#include <mwidgetview.h>

MApplication *app;

void Ut_MPannableViewport::initTestCase()
{
    static int argc = 1;
    static char *app_name[] = { (char *) "./ut_mpannableviewport" };

    app = new MApplication(argc, app_name);
}

void Ut_MPannableViewport::cleanupTestCase()
{
    // We do not delete the app on purpose. Due to some weird (toolchain?) problem
    // this can cause a crash when libraries are unregistered later.
    //delete app;
}

void Ut_MPannableViewport::init()
{
    subject = new MPannableViewport();
}

void Ut_MPannableViewport::cleanup()
{
    delete subject;
    subject = 0;
}

void Ut_MPannableViewport::constructor()
{
    QCOMPARE(subject->flags(), QGraphicsItem::ItemClipsChildrenToShape);
}

void Ut_MPannableViewport::setWidget()
{
    QGraphicsWidget *widget = new QGraphicsWidget();
    subject->setWidget(widget);

    widget->setZValue(1);
    QCOMPARE(widget->zValue(), 1.0);

    QCOMPARE(static_cast<MPannableViewportPrivate *>(subject->d_ptr)->pannedWidget, widget);
    QCOMPARE(static_cast<MPannableViewportPrivate *>(subject->d_ptr)->pannedWidget->parentItem(), subject);

}

void Ut_MPannableViewport::setGeometry_data()
{
    QTest::addColumn< QSizeF >("viewportSize");
    QTest::addColumn< QSizeF >("pannedSize");
    QTest::addColumn< QSizeF >("physicsRange");

    QTest::newRow("set 1") << QSizeF(100, 50) << QSizeF(400, 200) << QSizeF(300, 150);
    QTest::newRow("set 2") << QSizeF(400, 50) << QSizeF(100, 200) << QSizeF(0, 150);
    QTest::newRow("set 3") << QSizeF(100, 200) << QSizeF(400, 50) << QSizeF(300, 0);
}

void Ut_MPannableViewport::setGeometry()
{
    QFETCH(QSizeF, viewportSize);
    QFETCH(QSizeF, pannedSize);
    QFETCH(QSizeF, physicsRange);

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setMinimumSize(pannedSize);
    widget->setMaximumSize(pannedSize);

    subject->setWidget(widget);
    subject->setGeometry(QRectF(QPointF(), viewportSize));

    QCOMPARE(subject->physics()->range().size(), physicsRange);
}

void Ut_MPannableViewport::event_data()
{
    QTest::addColumn< QSizeF >("viewportSize");
    QTest::addColumn< QSizeF >("pannedSize");
    QTest::addColumn< QSizeF >("physicsRange");

    QTest::newRow("set 1") << QSizeF(100, 50) << QSizeF(400, 200) << QSizeF(300, 150);
    QTest::newRow("set 2") << QSizeF(400, 50) << QSizeF(100, 200) << QSizeF(0, 150);
    QTest::newRow("set 3") << QSizeF(100, 200) << QSizeF(400, 50) << QSizeF(300, 0);
}

void Ut_MPannableViewport::event()
{
    QEvent *event = new QEvent(QEvent::LayoutRequest);

    QFETCH(QSizeF, viewportSize);
    QFETCH(QSizeF, pannedSize);
    QFETCH(QSizeF, physicsRange);

    QGraphicsWidget *widget = new QGraphicsWidget();
    // Forcing the size of panned widget
    widget->setMinimumSize(pannedSize);
    widget->setPreferredSize(pannedSize);
    widget->setMaximumSize(pannedSize);

    // Forcing the size of subject
    subject->setMinimumSize(viewportSize);
    subject->setPreferredSize(viewportSize);
    subject->setMaximumSize(viewportSize);

    subject->setWidget(widget);

    subject->event(event);

    QCOMPARE(subject->physics()->range().size(), physicsRange);
}

void Ut_MPannableViewport::updatePosition()
{

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setMinimumSize(QSizeF(10,10));
    widget->setMaximumSize(QSizeF(10,10));
    subject->setWidget(widget);

    // Forcing the size of subject to some value
    subject->setMinimumSize(QSizeF(500, 300));
    subject->setMaximumSize(QSizeF(500, 300));
    subject->adjustSize();

    QSignalSpy spy(subject, SIGNAL(positionChanged(QPointF)));

    subject->physics()->setPosition(QPointF(0,75));

    QCOMPARE(static_cast<MPannableViewportPrivate *>(subject->d_ptr)->pannedWidget->pos(), -QPointF(0, 75));

    QCOMPARE(spy.count(), 1);

}

void Ut_MPannableViewport::updateSamePosition()
{
    QGraphicsWidget *mainWidget = new QGraphicsWidget();
    QPointF point(0.0, 0.0);

    subject->setMinimumSize(100, 480);
    subject->setPreferredSize(100, 480);
    subject->setMaximumSize(100, 480);

    mainWidget->setMinimumSize(100, 1000);
    mainWidget->setPreferredSize(100, 1000);
    mainWidget->setMaximumSize(100, 1000);

    subject->setWidget(mainWidget);

    subject->updatePosition(point);

    QSignalSpy spy(subject,
                   SIGNAL(positionChanged(QPointF)));

    subject->updatePosition(point);

    // Should not have emitted anything since nothing changed
    QCOMPARE(spy.count(), 0);
}

/*
 * While the pannedWidget is populated, sizePosChanged() signal should be
 * emitted only once for each actual change in pannedWidget's size.
 *
 * See NB#143428
 */
void Ut_MPannableViewport::sizePosChangedAfterPopulatingPannedWidget()
{
    QGraphicsWidget *mainWidget = new QGraphicsWidget();
    QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
    QGraphicsWidget *childWidget;

    //Settle initial layout position
    subject->adjustSize();

    mainWidget->setLayout(layout);

    subject->setWidget(mainWidget);

    QSignalSpy spyRange(subject,
                   SIGNAL(rangeChanged(QRectF)));
    QSignalSpy spyViewportSize(subject,
                   SIGNAL(viewportSizeChanged(QSizeF)));
    QSignalSpy spyPosition(subject,
                   SIGNAL(positionChanged(QPointF)));

    for (int i = 0; i < 30; i++) {
        childWidget = new QGraphicsWidget;

        childWidget->setMinimumSize(100, 200);
        childWidget->setPreferredSize(100, 200);

        layout->addItem(childWidget);
    }

    // Force layout to work.
    subject->adjustSize();

    // Check consecutive signals (if any), are different from each other.
    // We don't want to send out the very same event twice.
    for (int i = 1; i < spyRange.size(); i++) {
        QVERIFY(spyRange.at(i) != spyRange.at(i - 1));
    }
    for (int i = 1; i < spyPosition.size(); i++) {
        QVERIFY(spyPosition.at(i) != spyPosition.at(i - 1));
    }
    for (int i = 1; i < spyViewportSize.size(); i++) {
        QVERIFY(spyViewportSize.at(i) != spyViewportSize.at(i - 1));
    }
}

void Ut_MPannableViewport::settingNewPositionIndicator()
{
    MPositionIndicator* newPositionIndicator = new MPositionIndicator();
    subject->setPositionIndicator(newPositionIndicator);

    QVERIFY(subject->positionIndicator() == newPositionIndicator);
}

void Ut_MPannableViewport::settingNULLPositionIndicatorShouldNotBeAccepted()
{
    subject->setPositionIndicator(NULL);

    QVERIFY(subject->positionIndicator() != NULL);
}

void Ut_MPannableViewport::disabledViewportShouldNotAllowWigetToBeBiggerThanViewport()
{
    subject->setVerticalPanningPolicy(MPannableWidget::PanningAlwaysOff);
    subject->setHorizontalPanningPolicy(MPannableWidget::PanningAlwaysOff);

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setPreferredSize(1000,1000);
    subject->setWidget(widget);

    // Forcing the size of subject to some value
    subject->setMinimumSize(QSizeF(500, 300));
    subject->setMaximumSize(QSizeF(500, 300));

    subject->adjustSize();

    QCOMPARE(widget->size(), QSizeF(500,300));
    subject->setVerticalPanningPolicy(MPannableWidget::PanningAlwaysOn);
    subject->setHorizontalPanningPolicy(MPannableWidget::PanningAlwaysOff);

}

void Ut_MPannableViewport::rangeOfViewportShouldBeSizeOfPannedWidgetMinusViewportSize()
{
    // Forcing the size of subject to some value
    subject->setMinimumSize(QSizeF(500, 300));
    subject->setMaximumSize(QSizeF(500, 300));

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setMinimumSize(1000,1000);
    subject->setWidget(widget);

    subject->adjustSize();

    QCOMPARE(subject->range(), QRectF(0,0,500,700));
}

void Ut_MPannableViewport::testSetClipping()
{
    subject->setClipping(true);
    QCOMPARE(subject->hasClipping(), true);
    subject->setClipping(false);
    QCOMPARE(subject->hasClipping(), false);
}

void Ut_MPannableViewport::testRangeSetting()
{
    subject->setAutoRange(false);
    QCOMPARE(subject->autoRange(), false);

    subject->setRange(QRectF(0,0,100,100));
    QCOMPARE(subject->range(), QRectF(0,0,100,100));
}

void Ut_MPannableViewport::testExtendedRange_data()
{
    QTest::addColumn<qreal>("autoScrollHeightExtension");
    QTest::addColumn<qreal>("sipHeightExtension");
    QTest::addColumn<qreal>("verticalRange");
    QTest::addColumn<qreal>("expectedVerticalRange");

    QTest::newRow("Zero range") << 0.0 << 0.0 << 0.0 << 0.0;
    QTest::newRow("autoscroll extension") << 1.0 << 0.0 << 0.0 << 1.0;
    QTest::newRow("sip extension") << 0.0 << 1.0 << 0.0 << 1.0;
    QTest::newRow("autoscroll & sip #1") << 1.0 << 1.0 << 0.0 << 1.0;
    QTest::newRow("autoscroll & sip #2") << 5.0 << 1.0 << 0.0 << 5.0;
    QTest::newRow("autoscroll & sip #3") << 1.0 << 5.0 << 0.0 << 5.0;
    QTest::newRow("autoscroll & sip #4") << 1.0 << 5.0 << 2.0 << 7.0;
}

void Ut_MPannableViewport::testExtendedRange()
{
    QFETCH(qreal, autoScrollHeightExtension);
    QFETCH(qreal, sipHeightExtension);
    QFETCH(qreal, verticalRange);
    QFETCH(qreal, expectedVerticalRange);

    QGraphicsScene scene;
    scene.addItem(subject);

    const QSizeF viewportSize(100, 100);
    subject->resize(viewportSize);
    subject->setMinimumSize(viewportSize);
    subject->setMaximumSize(viewportSize);
    subject->setAutoRange(false);

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setMinimumSize(1000,1000);
    subject->setWidget(widget);

    subject->adjustSize();

    subject->setRange(QRectF(QPointF(), QSizeF(0, verticalRange)));

    // Set autoscrolling extension
    subject->d_func()->setAutoScrollingExtension(autoScrollHeightExtension);

    // Set area occupied by input method area.
    const QRect imArea(subject->geometry().adjusted(0, (viewportSize.height() - sipHeightExtension),
                                                    0, 0).toRect());
    subject->d_func()->setInputMethodArea(imArea);

    const qreal actualVerticalRange = subject->range().height();

    // Remove from scene before possible return/fail from QCOMPARE.
    scene.removeItem(subject);

    QCOMPARE(actualVerticalRange, expectedVerticalRange);
}

QTEST_APPLESS_MAIN(Ut_MPannableViewport)
<commit_msg>Fixes: ut_mpannableviewport on arm<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "ut_mpannableviewport.h"
#include <mtheme.h>
#include <mpositionindicator.h>
#include "mpannableviewport.h"
#include "mpannableviewport_p.h"
#include <QGraphicsWidget>
#include <QGraphicsLinearLayout>
#include <QTest>
#include <mapplication.h>
#include <mwidgetview.h>

MApplication *app;

void Ut_MPannableViewport::initTestCase()
{
    static int argc = 1;
    static char *app_name[] = { (char *) "./ut_mpannableviewport" };

    app = new MApplication(argc, app_name);
}

void Ut_MPannableViewport::cleanupTestCase()
{
    // We do not delete the app on purpose. Due to some weird (toolchain?) problem
    // this can cause a crash when libraries are unregistered later.
    //delete app;
}

void Ut_MPannableViewport::init()
{
    subject = new MPannableViewport();
}

void Ut_MPannableViewport::cleanup()
{
    delete subject;
    subject = 0;
}

void Ut_MPannableViewport::constructor()
{
    QCOMPARE(subject->flags(), QGraphicsItem::ItemClipsChildrenToShape);
}

void Ut_MPannableViewport::setWidget()
{
    QGraphicsWidget *widget = new QGraphicsWidget();
    subject->setWidget(widget);

    widget->setZValue(1);
    QCOMPARE(widget->zValue(), 1.0);

    QCOMPARE(static_cast<MPannableViewportPrivate *>(subject->d_ptr)->pannedWidget, widget);
    QCOMPARE(static_cast<MPannableViewportPrivate *>(subject->d_ptr)->pannedWidget->parentItem(), subject);

}

void Ut_MPannableViewport::setGeometry_data()
{
    QTest::addColumn< QSizeF >("viewportSize");
    QTest::addColumn< QSizeF >("pannedSize");
    QTest::addColumn< QSizeF >("physicsRange");

    QTest::newRow("set 1") << QSizeF(100, 50) << QSizeF(400, 200) << QSizeF(300, 150);
    QTest::newRow("set 2") << QSizeF(400, 50) << QSizeF(100, 200) << QSizeF(0, 150);
    QTest::newRow("set 3") << QSizeF(100, 200) << QSizeF(400, 50) << QSizeF(300, 0);
}

void Ut_MPannableViewport::setGeometry()
{
    QFETCH(QSizeF, viewportSize);
    QFETCH(QSizeF, pannedSize);
    QFETCH(QSizeF, physicsRange);

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setMinimumSize(pannedSize);
    widget->setMaximumSize(pannedSize);

    subject->setWidget(widget);
    subject->setGeometry(QRectF(QPointF(), viewportSize));

    QCOMPARE(subject->physics()->range().size(), physicsRange);
}

void Ut_MPannableViewport::event_data()
{
    QTest::addColumn< QSizeF >("viewportSize");
    QTest::addColumn< QSizeF >("pannedSize");
    QTest::addColumn< QSizeF >("physicsRange");

    QTest::newRow("set 1") << QSizeF(100, 50) << QSizeF(400, 200) << QSizeF(300, 150);
    QTest::newRow("set 2") << QSizeF(400, 50) << QSizeF(100, 200) << QSizeF(0, 150);
    QTest::newRow("set 3") << QSizeF(100, 200) << QSizeF(400, 50) << QSizeF(300, 0);
}

void Ut_MPannableViewport::event()
{
    QEvent *event = new QEvent(QEvent::LayoutRequest);

    QFETCH(QSizeF, viewportSize);
    QFETCH(QSizeF, pannedSize);
    QFETCH(QSizeF, physicsRange);

    QGraphicsWidget *widget = new QGraphicsWidget();
    // Forcing the size of panned widget
    widget->setMinimumSize(pannedSize);
    widget->setPreferredSize(pannedSize);
    widget->setMaximumSize(pannedSize);

    // Forcing the size of subject
    subject->setMinimumSize(viewportSize);
    subject->setPreferredSize(viewportSize);
    subject->setMaximumSize(viewportSize);

    subject->setWidget(widget);

    subject->event(event);

    QCOMPARE(subject->physics()->range().size(), physicsRange);
}

void Ut_MPannableViewport::updatePosition()
{

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setMinimumSize(QSizeF(10,10));
    widget->setMaximumSize(QSizeF(10,10));
    subject->setWidget(widget);

    // Forcing the size of subject to some value
    subject->setMinimumSize(QSizeF(500, 300));
    subject->setMaximumSize(QSizeF(500, 300));
    subject->adjustSize();

    QSignalSpy spy(subject, SIGNAL(positionChanged(QPointF)));

    subject->physics()->setPosition(QPointF(0,75));

    QCOMPARE(static_cast<MPannableViewportPrivate *>(subject->d_ptr)->pannedWidget->pos(), -QPointF(0, 75));

    QCOMPARE(spy.count(), 1);

}

void Ut_MPannableViewport::updateSamePosition()
{
    QGraphicsWidget *mainWidget = new QGraphicsWidget();
    QPointF point(0.0, 0.0);

    subject->setMinimumSize(100, 480);
    subject->setPreferredSize(100, 480);
    subject->setMaximumSize(100, 480);

    mainWidget->setMinimumSize(100, 1000);
    mainWidget->setPreferredSize(100, 1000);
    mainWidget->setMaximumSize(100, 1000);

    subject->setWidget(mainWidget);

    subject->updatePosition(point);

    QSignalSpy spy(subject,
                   SIGNAL(positionChanged(QPointF)));

    subject->updatePosition(point);

    // Should not have emitted anything since nothing changed
    QCOMPARE(spy.count(), 0);
}

/*
 * While the pannedWidget is populated, sizePosChanged() signal should be
 * emitted only once for each actual change in pannedWidget's size.
 *
 * See NB#143428
 */
void Ut_MPannableViewport::sizePosChangedAfterPopulatingPannedWidget()
{
    QGraphicsWidget *mainWidget = new QGraphicsWidget();
    QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
    QGraphicsWidget *childWidget;

    //Settle initial layout position
    subject->adjustSize();

    mainWidget->setLayout(layout);

    subject->setWidget(mainWidget);

    QSignalSpy spyRange(subject,
                   SIGNAL(rangeChanged(QRectF)));
    QSignalSpy spyViewportSize(subject,
                   SIGNAL(viewportSizeChanged(QSizeF)));
    QSignalSpy spyPosition(subject,
                   SIGNAL(positionChanged(QPointF)));

    for (int i = 0; i < 30; i++) {
        childWidget = new QGraphicsWidget;

        childWidget->setMinimumSize(100, 200);
        childWidget->setPreferredSize(100, 200);

        layout->addItem(childWidget);
    }

    // Force layout to work.
    subject->adjustSize();

    // Check consecutive signals (if any), are different from each other.
    // We don't want to send out the very same event twice.
    for (int i = 1; i < spyRange.size(); i++) {
        QVERIFY(spyRange.at(i) != spyRange.at(i - 1));
    }
    for (int i = 1; i < spyPosition.size(); i++) {
        QVERIFY(spyPosition.at(i) != spyPosition.at(i - 1));
    }
    for (int i = 1; i < spyViewportSize.size(); i++) {
        QVERIFY(spyViewportSize.at(i) != spyViewportSize.at(i - 1));
    }
}

void Ut_MPannableViewport::settingNewPositionIndicator()
{
    MPositionIndicator* newPositionIndicator = new MPositionIndicator();
    subject->setPositionIndicator(newPositionIndicator);

    QVERIFY(subject->positionIndicator() == newPositionIndicator);
}

void Ut_MPannableViewport::settingNULLPositionIndicatorShouldNotBeAccepted()
{
    subject->setPositionIndicator(NULL);

    QVERIFY(subject->positionIndicator() != NULL);
}

void Ut_MPannableViewport::disabledViewportShouldNotAllowWigetToBeBiggerThanViewport()
{
    subject->setVerticalPanningPolicy(MPannableWidget::PanningAlwaysOff);
    subject->setHorizontalPanningPolicy(MPannableWidget::PanningAlwaysOff);

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setPreferredSize(1000,1000);
    subject->setWidget(widget);

    // Forcing the size of subject to some value
    subject->setMinimumSize(QSizeF(500, 300));
    subject->setMaximumSize(QSizeF(500, 300));

    subject->adjustSize();

    QCOMPARE(widget->size(), QSizeF(500,300));
    subject->setVerticalPanningPolicy(MPannableWidget::PanningAlwaysOn);
    subject->setHorizontalPanningPolicy(MPannableWidget::PanningAlwaysOff);

}

void Ut_MPannableViewport::rangeOfViewportShouldBeSizeOfPannedWidgetMinusViewportSize()
{
    // Forcing the size of subject to some value
    subject->setMinimumSize(QSizeF(500, 300));
    subject->setMaximumSize(QSizeF(500, 300));

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setMinimumSize(1000,1000);
    subject->setWidget(widget);

    subject->adjustSize();

    QCOMPARE(subject->range(), QRectF(0,0,500,700));
}

void Ut_MPannableViewport::testSetClipping()
{
    subject->setClipping(true);
    QCOMPARE(subject->hasClipping(), true);
    subject->setClipping(false);
    QCOMPARE(subject->hasClipping(), false);
}

void Ut_MPannableViewport::testRangeSetting()
{
    subject->setAutoRange(false);
    QCOMPARE(subject->autoRange(), false);

    subject->setRange(QRectF(0,0,100,100));
    QCOMPARE(subject->range(), QRectF(0,0,100,100));
}

void Ut_MPannableViewport::testExtendedRange_data()
{
    QTest::addColumn<qreal>("autoScrollHeightExtension");
    QTest::addColumn<qreal>("sipHeightExtension");
    QTest::addColumn<qreal>("verticalRange");
    QTest::addColumn<qreal>("expectedVerticalRange");

    QTest::newRow("Zero range") << (qreal)0.0 << (qreal)0.0 << (qreal)0.0 << (qreal)0.0;
    QTest::newRow("autoscroll extension") << (qreal)1.0 << (qreal)0.0 << (qreal)0.0 << (qreal)1.0;
    QTest::newRow("sip extension") << (qreal)0.0 << (qreal)1.0 << (qreal)0.0 << (qreal)1.0;
    QTest::newRow("autoscroll & sip #1") << (qreal)1.0 << (qreal)1.0 << (qreal)0.0 << (qreal)1.0;
    QTest::newRow("autoscroll & sip #2") << (qreal)5.0 << (qreal)1.0 << (qreal)0.0 << (qreal)5.0;
    QTest::newRow("autoscroll & sip #3") << (qreal)1.0 << (qreal)5.0 << (qreal)0.0 << (qreal)5.0;
    QTest::newRow("autoscroll & sip #4") << (qreal)1.0 << (qreal)5.0 << (qreal)2.0 << (qreal)7.0;
}

void Ut_MPannableViewport::testExtendedRange()
{
    QFETCH(qreal, autoScrollHeightExtension);
    QFETCH(qreal, sipHeightExtension);
    QFETCH(qreal, verticalRange);
    QFETCH(qreal, expectedVerticalRange);

    QGraphicsScene scene;
    scene.addItem(subject);

    const QSizeF viewportSize(100, 100);
    subject->resize(viewportSize);
    subject->setMinimumSize(viewportSize);
    subject->setMaximumSize(viewportSize);
    subject->setAutoRange(false);

    QGraphicsWidget *widget = new QGraphicsWidget();
    widget->setMinimumSize(1000,1000);
    subject->setWidget(widget);

    subject->adjustSize();

    subject->setRange(QRectF(QPointF(), QSizeF(0, verticalRange)));

    // Set autoscrolling extension
    subject->d_func()->setAutoScrollingExtension(autoScrollHeightExtension);

    // Set area occupied by input method area.
    const QRect imArea(subject->geometry().adjusted(0, (viewportSize.height() - sipHeightExtension),
                                                    0, 0).toRect());
    subject->d_func()->setInputMethodArea(imArea);

    const qreal actualVerticalRange = subject->range().height();

    // Remove from scene before possible return/fail from QCOMPARE.
    scene.removeItem(subject);

    QCOMPARE(actualVerticalRange, expectedVerticalRange);
}

QTEST_APPLESS_MAIN(Ut_MPannableViewport)
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdlib>

#include <readline/readline.h>
#include <readline/history.h>

#include "shared.hh"
#include "eval.hh"
#include "eval-inline.hh"
#include "store-api.hh"

using namespace std;
using namespace nix;

string programId = "nix-repl";

struct NixRepl
{
    string curDir;
    EvalState state;

    StaticEnv staticEnv;
    Env * env;
    int displ;

    NixRepl();
    void mainLoop();
    void processLine(string line);
    void addVar(const Symbol & name, Value * v);
    Expr * parseString(string s);
    void evalString(string s, Value & v);
};

void printHelp()
{
    std::cout << "Usage: nix-repl\n";
}

bool getLine(string & line)
{
    char * s = readline("nix-repl> ");
    if (!s) return false;
    line = chomp(string(s));
    free(s);
    if (line != "") add_history(line.c_str());
    return true;
}

NixRepl::NixRepl()
    : staticEnv(false, &state.staticBaseEnv)
{
    curDir = absPath(".");

    env = &state.allocEnv(32768);
    env->up = &state.baseEnv;
    displ = 0;

    store = openStore();
}

void NixRepl::mainLoop()
{
    std::cerr << "Welcome to Nix version " << NIX_VERSION << ". Type :? for help." << std::endl << std::endl;

    while (true) {
        string line;
        if (!getLine(line)) break;

        /* Remove preceeding whitespace. */
        size_t n = line.find_first_not_of(" \n\r\t");
        if (n != string::npos) line = string(line, n);

        try {
            processLine(line);
        } catch (Error & e) {
            printMsg(lvlError, e.msg());
        }

        std::cout << std::endl;
    }

    std::cout << std::endl;
}

void NixRepl::processLine(string line)
{
    if (string(line, 0, 2) == ":a") {
        Value v;
        evalString(string(line, 2), v);
        state.forceAttrs(v);
        foreach (Bindings::iterator, i, *v.attrs)
            addVar(i->name, i->value);
    }

    else if (string(line, 0, 2) == ":t") {
        Value v;
        evalString(string(line, 2), v);
        std::cout << showType(v) << std::endl;
    }

    else if (string(line, 0, 1) == ":") {
        throw Error(format("unknown command ‘%1%’") % string(line, 0, 2));
    }

    else {
        Value v;
        evalString(line, v);
        state.strictForceValue(v);
        std::cout << v << std::endl;
    }
}

void NixRepl::addVar(const Symbol & name, Value * v)
{
    staticEnv.vars[name] = displ;
    env->values[displ++] = v;
}

Expr * NixRepl::parseString(string s)
{
    Expr * e = state.parseExprFromString(s, curDir, staticEnv);
    return e;
}

void NixRepl::evalString(string s, Value & v)
{
    Expr * e = parseString(s);
    e->eval(state, *env, v);
    state.forceValue(v);
}

void run(nix::Strings args)
{
    NixRepl repl;
    repl.mainLoop();
}
<commit_msg>Add a command :l for loading a file into scope<commit_after>#include <iostream>
#include <cstdlib>

#include <readline/readline.h>
#include <readline/history.h>

#include "shared.hh"
#include "eval.hh"
#include "eval-inline.hh"
#include "store-api.hh"
#include "common-opts.hh"

using namespace std;
using namespace nix;

string programId = "nix-repl";

struct NixRepl
{
    string curDir;
    EvalState state;

    StaticEnv staticEnv;
    Env * env;
    int displ;

    NixRepl();
    void mainLoop();
    void processLine(string line);
    void addAttrsToScope(Value & attrs);
    void addVarToScope(const Symbol & name, Value * v);
    Expr * parseString(string s);
    void evalString(string s, Value & v);
};

void printHelp()
{
    std::cout << "Usage: nix-repl\n";
}

bool getLine(string & line)
{
    char * s = readline("nix-repl> ");
    if (!s) return false;
    line = chomp(string(s));
    free(s);
    if (line != "") add_history(line.c_str());
    return true;
}

string removeWhitespace(string s)
{
    s = chomp(s);
    size_t n = s.find_first_not_of(" \n\r\t");
    if (n != string::npos) s = string(s, n);
    return s;
}

NixRepl::NixRepl()
    : staticEnv(false, &state.staticBaseEnv)
{
    curDir = absPath(".");

    env = &state.allocEnv(32768);
    env->up = &state.baseEnv;
    displ = 0;

    store = openStore();
}

void NixRepl::mainLoop()
{
    std::cerr << "Welcome to Nix version " << NIX_VERSION << ". Type :? for help." << std::endl << std::endl;

    while (true) {
        string line;
        if (!getLine(line)) break;

        try {
            processLine(removeWhitespace(line));
        } catch (Error & e) {
            printMsg(lvlError, e.msg());
        }

        std::cout << std::endl;
    }

    std::cout << std::endl;
}

void NixRepl::processLine(string line)
{
    if (string(line, 0, 2) == ":a") {
        Value v;
        evalString(string(line, 2), v);
        addAttrsToScope(v);
    }

    else if (string(line, 0, 2) == ":l") {
        state.resetFileCache();
        Path path = lookupFileArg(state, removeWhitespace(string(line, 2)));
        Value v, v2;
        state.evalFile(path, v);
        Bindings bindings;
        state.autoCallFunction(bindings, v, v2);
        addAttrsToScope(v2);
    }

    else if (string(line, 0, 2) == ":t") {
        Value v;
        evalString(string(line, 2), v);
        std::cout << showType(v) << std::endl;
    }

    else if (string(line, 0, 1) == ":") {
        throw Error(format("unknown command ‘%1%’") % string(line, 0, 2));
    }

    else {
        Value v;
        evalString(line, v);
        state.strictForceValue(v);
        std::cout << v << std::endl;
    }
}

void NixRepl::addAttrsToScope(Value & attrs)
{
    state.forceAttrs(attrs);
    foreach (Bindings::iterator, i, *attrs.attrs)
        addVarToScope(i->name, i->value);
}

void NixRepl::addVarToScope(const Symbol & name, Value * v)
{
    staticEnv.vars[name] = displ;
    env->values[displ++] = v;
}

Expr * NixRepl::parseString(string s)
{
    Expr * e = state.parseExprFromString(s, curDir, staticEnv);
    return e;
}

void NixRepl::evalString(string s, Value & v)
{
    Expr * e = parseString(s);
    e->eval(state, *env, v);
    state.forceValue(v);
}

void run(nix::Strings args)
{
    NixRepl repl;
    repl.mainLoop();
}
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 Scott Moreau
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <plugin.hpp>
#include <output.hpp>
#include <opengl.hpp>
#include <debug.hpp>
#include <animation.hpp>
#include <render-manager.hpp>

static const char* vertex_shader =
R"(
#version 100

attribute mediump vec2 position;

void main() {

    gl_Position = vec4(position.xy, 0.0, 1.0);
}
)";

static const char* fragment_shader =
R"(
#version 100
precision mediump float;

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_radius;
uniform float u_zoom;
uniform sampler2D u_texture;

const float PI = 3.1415926535;

void main()
{
        float radius = u_radius;

        float zoom = u_zoom;
        float pw = 1.0 / u_resolution.x;
        float ph = 1.0 / u_resolution.y;

        vec4 p0 = vec4(u_mouse.x, u_resolution.y - u_mouse.y, 1.0 / radius, 0.0);
        vec4 p1 = vec4(pw, ph, PI / radius, (zoom - 1.0) * zoom);
        vec4 p2 = vec4(0, 0, -PI / 2.0, 0.0);

        vec4 t0, t1, t2, t3;

        vec3 tc = vec3(1.0, 0.0, 0.0);
        vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y);

        t1 = p0.xyww - vec4(uv, 0.0, 0.0);
        t2.x = t2.y = t2.z = t2.w = 1.0 / sqrt(dot(t1.xyz, t1.xyz));
        t0 = t2 - p0;

        t3.x = t3.y = t3.z = t3.w = 1.0 / t2.x;
        t3 = t3 * p1.z + p2.z;
        t3.x = t3.y = t3.z = t3.w = cos(t3.x);

        t3 = t3 * p1.w;

        t1 = t2 * t1;
        t1 = t1 * t3 + vec4(uv, 0.0, 0.0);

        if (t0.z < 0.0) {
                t1.x = uv.x;
                t1.y = uv.y;
        }

        t1 = t1 * p1 + p2;

        tc = texture2D(u_texture, t1.xy).rgb;

        gl_FragColor = vec4(tc, 1.0);
}
)";

class wayfire_fisheye : public wayfire_plugin_t
{

    post_hook_t hook;
    key_callback toggle_cb;
    wf_duration duration;
    float target_zoom;
    bool active, hook_set;
    wf_option radius, zoom;

    GLuint program, posID, mouseID, resID, radiusID, zoomID;

    public:
        void init(wayfire_config *config)
        {
            auto section = config->get_section("fisheye");
            auto toggle_key = section->get_option("toggle", "<super> KEY_F");
            radius = section->get_option("radius", "300");
            zoom = section->get_option("zoom", "7");

            if (!toggle_key->as_key().valid())
                return;

            target_zoom = zoom->as_double();

            hook = [=] (uint32_t fb, uint32_t tex, uint32_t target)
            {
                render(fb, tex, target);
            };

            toggle_cb = [=] (uint32_t key)
            {
                    if (active)
                    {
                        active = false;
                        duration.start(duration.progress(), 0);
                    } else
                    {
                        active = true;
                        duration.start(duration.progress(), target_zoom);

                        if (!hook_set)
                        {
                            hook_set = true;
                            output->render->add_post(&hook);
                        }
                    }
            };

            auto vs = OpenGL::compile_shader(vertex_shader, GL_VERTEX_SHADER);
            auto fs = OpenGL::compile_shader(fragment_shader, GL_FRAGMENT_SHADER);

            program = GL_CALL(glCreateProgram());
            GL_CALL(glAttachShader(program, vs));
            GL_CALL(glAttachShader(program, fs));
            GL_CALL(glLinkProgram(program));

            posID = GL_CALL(glGetAttribLocation(program, "position"));
            mouseID  = GL_CALL(glGetUniformLocation(program, "u_mouse"));
            resID  = GL_CALL(glGetUniformLocation(program, "u_resolution"));
            radiusID  = GL_CALL(glGetUniformLocation(program, "u_radius"));
            zoomID  = GL_CALL(glGetUniformLocation(program, "u_zoom"));

            duration = wf_duration(new_static_option("700"));
            duration.start(0, 0); // so that the first value we get is correct

            output->add_key(toggle_key, &toggle_cb);
        }

        void render(uint32_t fb, uint32_t tex, uint32_t target)
        {
            GetTuple(x, y, output->get_cursor_position());
            GL_CALL(glUseProgram(program));
            GL_CALL(glBindTexture(GL_TEXTURE_2D, tex));
            GL_CALL(glActiveTexture(GL_TEXTURE0));

            static const float vertexData[] = {
                -1.0f, -1.0f,
                 1.0f, -1.0f,
                 1.0f,  1.0f,
                -1.0f,  1.0f
            };

            auto current_zoom = duration.progress();
            target_zoom = zoom->as_double();

            glUniform2f(mouseID, x, y);
            glUniform2f(resID, output->handle->width, output->handle->height);
            glUniform1f(radiusID, radius->as_double());
            glUniform1f(zoomID, current_zoom);

            GL_CALL(glVertexAttribPointer(posID, 2, GL_FLOAT, GL_FALSE, 0, vertexData));
            GL_CALL(glEnableVertexAttribArray(posID));

            GL_CALL(glDisable(GL_BLEND));
            GL_CALL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target));
            GL_CALL(glDrawArrays (GL_TRIANGLE_FAN, 0, 4));
            GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));

            GL_CALL(glDisableVertexAttribArray(posID));
            GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));

            if (active)
            {
                /* Reset animation in case target_zoom
                 * was changed via config */
                duration.start(current_zoom, target_zoom);
            } else if (!duration.running())
            {
                output->render->rem_post(&hook);
                hook_set = false;
            }
        }
};

extern "C"
{
    wayfire_plugin_t *newInstance()
    {
        return new wayfire_fisheye();
    }
}
<commit_msg>Transform mouse coordinates<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 Scott Moreau
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <plugin.hpp>
#include <output.hpp>
#include <opengl.hpp>
#include <debug.hpp>
#include <animation.hpp>
#include <render-manager.hpp>

static const char* vertex_shader =
R"(
#version 100

attribute mediump vec2 position;

void main() {

    gl_Position = vec4(position.xy, 0.0, 1.0);
}
)";

static const char* fragment_shader =
R"(
#version 100
precision mediump float;

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_radius;
uniform float u_zoom;
uniform sampler2D u_texture;

const float PI = 3.1415926535;

void main()
{
        float radius = u_radius;

        float zoom = u_zoom;
        float pw = 1.0 / u_resolution.x;
        float ph = 1.0 / u_resolution.y;

        vec4 p0 = vec4(u_mouse.x, u_resolution.y - u_mouse.y, 1.0 / radius, 0.0);
        vec4 p1 = vec4(pw, ph, PI / radius, (zoom - 1.0) * zoom);
        vec4 p2 = vec4(0, 0, -PI / 2.0, 0.0);

        vec4 t0, t1, t2, t3;

        vec3 tc = vec3(1.0, 0.0, 0.0);
        vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y);

        t1 = p0.xyww - vec4(uv, 0.0, 0.0);
        t2.x = t2.y = t2.z = t2.w = 1.0 / sqrt(dot(t1.xyz, t1.xyz));
        t0 = t2 - p0;

        t3.x = t3.y = t3.z = t3.w = 1.0 / t2.x;
        t3 = t3 * p1.z + p2.z;
        t3.x = t3.y = t3.z = t3.w = cos(t3.x);

        t3 = t3 * p1.w;

        t1 = t2 * t1;
        t1 = t1 * t3 + vec4(uv, 0.0, 0.0);

        if (t0.z < 0.0) {
                t1.x = uv.x;
                t1.y = uv.y;
        }

        t1 = t1 * p1 + p2;

        tc = texture2D(u_texture, t1.xy).rgb;

        gl_FragColor = vec4(tc, 1.0);
}
)";

class wayfire_fisheye : public wayfire_plugin_t
{

    post_hook_t hook;
    key_callback toggle_cb;
    wf_duration duration;
    float target_zoom;
    bool active, hook_set;
    wf_option radius, zoom;

    GLuint program, posID, mouseID, resID, radiusID, zoomID;

    public:
        void init(wayfire_config *config)
        {
            auto section = config->get_section("fisheye");
            auto toggle_key = section->get_option("toggle", "<super> KEY_F");
            radius = section->get_option("radius", "300");
            zoom = section->get_option("zoom", "7");

            if (!toggle_key->as_key().valid())
                return;

            target_zoom = zoom->as_double();

            hook = [=] (uint32_t fb, uint32_t tex, uint32_t target)
            {
                render(fb, tex, target);
            };

            toggle_cb = [=] (uint32_t key)
            {
                    if (active)
                    {
                        active = false;
                        duration.start(duration.progress(), 0);
                    } else
                    {
                        active = true;
                        duration.start(duration.progress(), target_zoom);

                        if (!hook_set)
                        {
                            hook_set = true;
                            output->render->add_post(&hook);
                        }
                    }
            };

            auto vs = OpenGL::compile_shader(vertex_shader, GL_VERTEX_SHADER);
            auto fs = OpenGL::compile_shader(fragment_shader, GL_FRAGMENT_SHADER);

            program = GL_CALL(glCreateProgram());
            GL_CALL(glAttachShader(program, vs));
            GL_CALL(glAttachShader(program, fs));
            GL_CALL(glLinkProgram(program));

            posID = GL_CALL(glGetAttribLocation(program, "position"));
            mouseID  = GL_CALL(glGetUniformLocation(program, "u_mouse"));
            resID  = GL_CALL(glGetUniformLocation(program, "u_resolution"));
            radiusID  = GL_CALL(glGetUniformLocation(program, "u_radius"));
            zoomID  = GL_CALL(glGetUniformLocation(program, "u_zoom"));

            duration = wf_duration(new_static_option("700"));
            duration.start(0, 0); // so that the first value we get is correct

            output->add_key(toggle_key, &toggle_cb);
        }

        void render(uint32_t fb, uint32_t tex, uint32_t target)
        {
            GetTuple(x, y, output->get_cursor_position());
            wlr_box box = {x, y, 1, 1};
            box = output_transform_box(output, box);
            x = box.x;
            y = box.y;

            GL_CALL(glUseProgram(program));
            GL_CALL(glBindTexture(GL_TEXTURE_2D, tex));
            GL_CALL(glActiveTexture(GL_TEXTURE0));

            static const float vertexData[] = {
                -1.0f, -1.0f,
                 1.0f, -1.0f,
                 1.0f,  1.0f,
                -1.0f,  1.0f
            };

            auto current_zoom = duration.progress();
            target_zoom = zoom->as_double();

            glUniform2f(mouseID, x, y);
            glUniform2f(resID, output->handle->width, output->handle->height);
            glUniform1f(radiusID, radius->as_double());
            glUniform1f(zoomID, current_zoom);

            GL_CALL(glVertexAttribPointer(posID, 2, GL_FLOAT, GL_FALSE, 0, vertexData));
            GL_CALL(glEnableVertexAttribArray(posID));

            GL_CALL(glDisable(GL_BLEND));
            GL_CALL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target));
            GL_CALL(glDrawArrays (GL_TRIANGLE_FAN, 0, 4));
            GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));

            GL_CALL(glDisableVertexAttribArray(posID));
            GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));

            if (active)
            {
                /* Reset animation in case target_zoom
                 * was changed via config */
                duration.start(current_zoom, target_zoom);
            } else if (!duration.running())
            {
                output->render->rem_post(&hook);
                hook_set = false;
            }
        }
};

extern "C"
{
    wayfire_plugin_t *newInstance()
    {
        return new wayfire_fisheye();
    }
}
<|endoftext|>


<commit_before>/* This code is subject to the terms of the Mozilla Public License, v.2.0. http://mozilla.org/MPL/2.0/. */
#include "UdtServer.h"

#include "UdtSocket.h"
#include "socket/IpAddress.h"
#include <iostream>

#include "udt4/src/udt.h"
#include <arpa/inet.h>
//#include <netinet/in.h>
#include <string.h>
//#include <unistd.h>

namespace
{
	int _epollEventFlag = EPOLLOpt::UDT_EPOLL_IN ^ EPOLLOpt::UDT_EPOLL_ERR;
}

// TODO: investigate delays/unreliabiliy when using concurrent UDT::epoll_wait(), e.g. numThreads > 1?
UdtServer::UdtServer(short port, std::function<void(const IIpSocket&, const std::string&)> onPacket, unsigned numThreads/*=1*/, unsigned maxPacketSize)
	: _running(false)
	, _sock(-1)
	, _port(port)
	, _numThreads(numThreads)
	, _maxPacketSize(maxPacketSize)
	, _onPacket(onPacket)
{
}

UdtServer::~UdtServer()
{
	stop();
}

bool UdtServer::start()
{
	if (_running)
		return true;

	_running = true;
	_sock = UDT::socket(AF_INET, SOCK_DGRAM, 0);
	if (_sock == UDT::INVALID_SOCK)
	{
		fatalError("couldn't create socket!");
		return _running = false;
	}

	struct sockaddr_in si_me;
	memset((char*)&si_me, 0, sizeof(si_me));

	si_me.sin_family = AF_INET;
	si_me.sin_port = htons(_port);
	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
	if (UDT::bind(_sock, (struct sockaddr*)&si_me, sizeof(si_me)) == UDT::ERROR)
	{
		fatalError("couldn't bind to port: " + std::string(UDT::getlasterror().getErrorMessage()));
		return _running = false;
	}
	if (UDT::listen(_sock, 20) == UDT::ERROR)
	{
		fatalError("couldn't get udt socket to listen: " + std::string(UDT::getlasterror().getErrorMessage()));
		UDT::close(_sock);
		return _running = false;
	}

	_pollPackets = UDT::epoll_create();
	if (_pollPackets < 0)
	{
		fatalError("couldn't get udt epoll to work: " + std::string(UDT::getlasterror().getErrorMessage()));
		UDT::close(_sock);
		return _running = false;
	}

	_acceptor = std::thread( std::bind(&UdtServer::accept, this) );
	for (unsigned i = 0; i < _numThreads; ++i)
		_runners.push_back( std::thread(std::bind(&UdtServer::run, this)) );
	_started.wait();
	return _running;
}

void UdtServer::stop()
{
	_running = false;
	UDT::epoll_release(_pollPackets);
	UDT::close(_sock);
	for (tbb::concurrent_unordered_map<std::string,int>::iterator it = _connections.begin(); it != _connections.end(); ++it)
		UDT::close(it->second);

	for (std::list<std::thread>::iterator it = _runners.begin(); it != _runners.end(); ++it)
	{
		 if (it->joinable())
			it->join();
	}
	_runners.clear();
	if (_acceptor.joinable())
		_acceptor.join();
}

// TODO: probably eventually want two epoll groups.
// one for new connections,
// and one for known (good) peers.
// that way we can safely do a LRU scheme for good peers...
void UdtServer::accept()
{
	_started.shutdown();

	struct sockaddr_in their_addr;
	int addr_sz = sizeof(their_addr);
	memset((char*)&their_addr, 0, addr_sz);

	while (_running)
	{
		UDTSOCKET conn = UDT::accept(_sock, (sockaddr*)&their_addr, &addr_sz);
		if (conn == UDT::INVALID_SOCK)
			continue;

		if (UDT::epoll_add_usock(_pollPackets, conn, &_epollEventFlag) < 0)
		{
			std::cout << "UDT::epoll_add_usock error." << std::endl;
			continue;
		}
	}
}

void UdtServer::run()
{
	std::string buffer;
	std::set<UDTSOCKET> irrelevant;
	std::set<UDTSOCKET> reads;
	while (_running)
	{
		reads.clear();
		irrelevant.clear();

		int waiters;
		if ((waiters = UDT::epoll_wait(_pollPackets, &reads, &irrelevant, 5000)) < 0)
		{
			std::cout << "epoll_wait did an error! :( " << waiters << std::endl;
			continue;
		}
		std::cout << "epoll says there are " << waiters << " guys ready. Yes, " << reads.size() << " ... ? " << irrelevant.size() << std::endl;

		for (std::set<UDTSOCKET>::const_iterator it = reads.begin(); it != reads.end(); ++it)
		{
			UdtSocket sock(*it);
			std::cout << "udt read: " << sock.getTarget().toString() << std::endl;

			buffer.resize(_maxPacketSize);
			if (sock.recv(buffer) <= 0)
			{
				std::cout << "badness. :(" << std::endl;
				UDT::epoll_remove_usock(_pollPackets, *it);
				UDT::close(*it);
			}

			_onPacket(sock, buffer);
			_connections[sock.getTarget().toString()] = *it;
		}
	}
}

bool UdtServer::isRunning() const
{
	return _running;
}

std::string UdtServer::lastError() const
{
	return _lastError;
}

void UdtServer::fatalError(const std::string& error)
{
	_lastError = error;
}

std::shared_ptr<IIpSocket> UdtServer::sock(const IpAddress& addr)
{
	// concurrent unordered map or something
	std::shared_ptr<IIpSocket> res;
	std::pair< tbb::concurrent_unordered_map<std::string, int>::iterator, bool> pear = _connections.insert( {addr.toString(), -1} );
	if (pear.first->second < 0)
	{
		UDTSOCKET handle = UDT::socket(AF_INET, SOCK_DGRAM, 0);
		if (handle == UDT::INVALID_SOCK)
			return NULL;

		UdtSocket* sock = new UdtSocket(handle);
		res.reset(sock);
		if (!sock->connect(addr))
			return NULL;
		pear.first->second = handle;

		if (UDT::epoll_add_usock(_pollPackets, handle, &_epollEventFlag) < 0)
			std::cout << "UDT::epoll_add_usock error for client sock." << std::endl;
	}
	else
		res.reset(new UdtSocket(pear.first->second));
	return std::shared_ptr<IIpSocket>(res);
}
<commit_msg>Less noisyness from the udt server...<commit_after>/* This code is subject to the terms of the Mozilla Public License, v.2.0. http://mozilla.org/MPL/2.0/. */
#include "UdtServer.h"

#include "UdtSocket.h"
#include "socket/IpAddress.h"
#include <iostream>

#include "udt4/src/udt.h"
#include <arpa/inet.h>
//#include <netinet/in.h>
#include <string.h>
//#include <unistd.h>

namespace
{
	int _epollEventFlag = EPOLLOpt::UDT_EPOLL_IN ^ EPOLLOpt::UDT_EPOLL_ERR;
}

// TODO: investigate delays/unreliabiliy when using concurrent UDT::epoll_wait(), e.g. numThreads > 1?
UdtServer::UdtServer(short port, std::function<void(const IIpSocket&, const std::string&)> onPacket, unsigned numThreads/*=1*/, unsigned maxPacketSize)
	: _running(false)
	, _sock(-1)
	, _port(port)
	, _numThreads(numThreads)
	, _maxPacketSize(maxPacketSize)
	, _onPacket(onPacket)
{
}

UdtServer::~UdtServer()
{
	stop();
}

bool UdtServer::start()
{
	if (_running)
		return true;

	_running = true;
	_sock = UDT::socket(AF_INET, SOCK_DGRAM, 0);
	if (_sock == UDT::INVALID_SOCK)
	{
		fatalError("couldn't create socket!");
		return _running = false;
	}

	struct sockaddr_in si_me;
	memset((char*)&si_me, 0, sizeof(si_me));

	si_me.sin_family = AF_INET;
	si_me.sin_port = htons(_port);
	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
	if (UDT::bind(_sock, (struct sockaddr*)&si_me, sizeof(si_me)) == UDT::ERROR)
	{
		fatalError("couldn't bind to port: " + std::string(UDT::getlasterror().getErrorMessage()));
		return _running = false;
	}
	if (UDT::listen(_sock, 20) == UDT::ERROR)
	{
		fatalError("couldn't get udt socket to listen: " + std::string(UDT::getlasterror().getErrorMessage()));
		UDT::close(_sock);
		return _running = false;
	}

	_pollPackets = UDT::epoll_create();
	if (_pollPackets < 0)
	{
		fatalError("couldn't get udt epoll to work: " + std::string(UDT::getlasterror().getErrorMessage()));
		UDT::close(_sock);
		return _running = false;
	}

	_acceptor = std::thread( std::bind(&UdtServer::accept, this) );
	for (unsigned i = 0; i < _numThreads; ++i)
		_runners.push_back( std::thread(std::bind(&UdtServer::run, this)) );
	_started.wait();
	return _running;
}

void UdtServer::stop()
{
	_running = false;
	UDT::epoll_release(_pollPackets);
	UDT::close(_sock);
	for (tbb::concurrent_unordered_map<std::string,int>::iterator it = _connections.begin(); it != _connections.end(); ++it)
		UDT::close(it->second);

	for (std::list<std::thread>::iterator it = _runners.begin(); it != _runners.end(); ++it)
	{
		 if (it->joinable())
			it->join();
	}
	_runners.clear();
	if (_acceptor.joinable())
		_acceptor.join();
}

// TODO: probably eventually want two epoll groups.
// one for new connections,
// and one for known (good) peers.
// that way we can safely do a LRU scheme for good peers...
void UdtServer::accept()
{
	_started.shutdown();

	struct sockaddr_in their_addr;
	int addr_sz = sizeof(their_addr);
	memset((char*)&their_addr, 0, addr_sz);

	while (_running)
	{
		UDTSOCKET conn = UDT::accept(_sock, (sockaddr*)&their_addr, &addr_sz);
		if (conn == UDT::INVALID_SOCK)
			continue;

		if (UDT::epoll_add_usock(_pollPackets, conn, &_epollEventFlag) < 0)
		{
			std::cout << "UDT::epoll_add_usock error." << std::endl;
			continue;
		}
	}
}

void UdtServer::run()
{
	std::string buffer;
	std::set<UDTSOCKET> irrelevant;
	std::set<UDTSOCKET> reads;
	while (_running)
	{
		reads.clear();
		irrelevant.clear();

		int waiters;
		if ((waiters = UDT::epoll_wait(_pollPackets, &reads, &irrelevant, 5000)) < 0)
		{
			std::cout << "epoll_wait did an error! :( " << waiters << std::endl;
			continue;
		}
		//std::cout << "epoll says there are " << waiters << " guys ready. Yes, " << reads.size() << " ... ? " << irrelevant.size() << std::endl;

		for (std::set<UDTSOCKET>::const_iterator it = reads.begin(); it != reads.end(); ++it)
		{
			UdtSocket sock(*it);
			//std::cout << "udt read: " << sock.getTarget().toString() << std::endl;

			buffer.resize(_maxPacketSize);
			if (sock.recv(buffer) <= 0)
			{
				std::cout << "udt badness. :(" << std::endl;
				UDT::epoll_remove_usock(_pollPackets, *it);
				UDT::close(*it);
			}

			_onPacket(sock, buffer);
			_connections[sock.getTarget().toString()] = *it;
		}
	}
}

bool UdtServer::isRunning() const
{
	return _running;
}

std::string UdtServer::lastError() const
{
	return _lastError;
}

void UdtServer::fatalError(const std::string& error)
{
	_lastError = error;
}

std::shared_ptr<IIpSocket> UdtServer::sock(const IpAddress& addr)
{
	// concurrent unordered map or something
	std::shared_ptr<IIpSocket> res;
	std::pair< tbb::concurrent_unordered_map<std::string, int>::iterator, bool> pear = _connections.insert( {addr.toString(), -1} );
	if (pear.first->second < 0)
	{
		UDTSOCKET handle = UDT::socket(AF_INET, SOCK_DGRAM, 0);
		if (handle == UDT::INVALID_SOCK)
			return NULL;

		UdtSocket* sock = new UdtSocket(handle);
		res.reset(sock);
		if (!sock->connect(addr))
			return NULL;
		pear.first->second = handle;

		if (UDT::epoll_add_usock(_pollPackets, handle, &_epollEventFlag) < 0)
			std::cout << "UDT::epoll_add_usock error for client sock." << std::endl;
	}
	else
		res.reset(new UdtSocket(pear.first->second));
	return std::shared_ptr<IIpSocket>(res);
}
<|endoftext|>


<commit_before>#include "ofp/rpc/rpcevents.h"
#include "ofp/unittest.h"

TEST(rpcevents, test_TrimErrorMessage) {
  std::string msg1 = "x\n     ^";
  ofp::rpc::TrimErrorMessage(msg1);
  EXPECT_EQ(msg1, "x");

  std::string msg2 = "";
  ofp::rpc::TrimErrorMessage(msg2);
  EXPECT_EQ(msg2, "");

  std::string msg3 = "abc";
  ofp::rpc::TrimErrorMessage(msg3);
  EXPECT_EQ(msg3, "abc");
}
<commit_msg>cpplint fix.<commit_after>// Copyright (c) 2015-2018 William W. Fisher (at gmail dot com)
// This file is distributed under the MIT License.

#include "ofp/rpc/rpcevents.h"
#include "ofp/unittest.h"

TEST(rpcevents, test_TrimErrorMessage) {
  std::string msg1 = "x\n     ^";
  ofp::rpc::TrimErrorMessage(msg1);
  EXPECT_EQ(msg1, "x");

  std::string msg2 = "";
  ofp::rpc::TrimErrorMessage(msg2);
  EXPECT_EQ(msg2, "");

  std::string msg3 = "abc";
  ofp::rpc::TrimErrorMessage(msg3);
  EXPECT_EQ(msg3, "abc");
}
<|endoftext|>


<commit_before>#include <memory>
#include <gmock/gmock.h>

#include "smartsqlite/connection.h"
#include "smartsqlite/exceptions.h"
#include "smartsqlite/scopedtransaction.h"

using namespace testing;
using ConnPtr = std::shared_ptr<SmartSqlite::Connection>;

static ConnPtr makeConnection()
{
    return std::make_shared<SmartSqlite::Connection>(
                SmartSqlite::makeConnection(":memory:"));
}

static int getUserVersion(ConnPtr conn)
{
    auto stmt = conn->prepare("PRAGMA user_version");
    return stmt.execWithSingleResult().get<int>(0);
}

static void setUserVersion(ConnPtr conn, int version)
{
    conn->exec("PRAGMA user_version = " + std::to_string(version));
}

TEST(ScopedTransaction, ctorDoesntThrow)
{
    SmartSqlite::ScopedTransaction tx(makeConnection());
}

TEST(ScopedTransaction, ctorBeginsTransaction)
{
    auto conn = makeConnection();
    SmartSqlite::ScopedTransaction tx(conn);
    (void)tx;

    EXPECT_THROW(conn->beginTransaction(), SmartSqlite::SqliteException);
}

TEST(ScopedTransaction, dtorRollsBack)
{
    auto conn = makeConnection();
    int origVersion = 23;
    conn->exec("PRAGMA user_version = " + std::to_string(origVersion));
    {
        SmartSqlite::ScopedTransaction tx(conn);
        (void)tx;
        setUserVersion(conn, 42);
    }

    EXPECT_THAT(getUserVersion(conn), Eq(origVersion));
}

TEST(ScopedTransaction, commitEndsTransaction)
{
    auto conn = makeConnection();
    SmartSqlite::ScopedTransaction tx(conn);
    tx.commit();

    // would throw if commit didn't end the transaction
    conn->beginTransaction();
}

TEST(ScopedTransaction, commitCancelsRollback)
{
    auto conn = makeConnection();
    setUserVersion(conn, 42);
    int version = 23;
    {
        SmartSqlite::ScopedTransaction tx(conn);
        tx.commit();

        conn->beginTransaction();
        setUserVersion(conn, version);
    }

    // user_version would be 42 if ~ScopedTransaction would rollback
    EXPECT_THAT(getUserVersion(conn), Eq(version));
}
<commit_msg>ScopedTransaction tests: Reuse SQL<commit_after>#include <memory>
#include <gmock/gmock.h>

#include "smartsqlite/connection.h"
#include "smartsqlite/exceptions.h"
#include "smartsqlite/scopedtransaction.h"

using namespace testing;
using ConnPtr = std::shared_ptr<SmartSqlite::Connection>;

static ConnPtr makeConnection()
{
    return std::make_shared<SmartSqlite::Connection>(
                SmartSqlite::makeConnection(":memory:"));
}

static int getUserVersion(ConnPtr conn)
{
    auto stmt = conn->prepare("PRAGMA user_version");
    return stmt.execWithSingleResult().get<int>(0);
}

static void setUserVersion(ConnPtr conn, int version)
{
    conn->exec("PRAGMA user_version = " + std::to_string(version));
}

TEST(ScopedTransaction, ctorDoesntThrow)
{
    SmartSqlite::ScopedTransaction tx(makeConnection());
}

TEST(ScopedTransaction, ctorBeginsTransaction)
{
    auto conn = makeConnection();
    SmartSqlite::ScopedTransaction tx(conn);
    (void)tx;

    EXPECT_THROW(conn->beginTransaction(), SmartSqlite::SqliteException);
}

TEST(ScopedTransaction, dtorRollsBack)
{
    auto conn = makeConnection();
    int origVersion = 23;
    setUserVersion(conn, origVersion);
    {
        SmartSqlite::ScopedTransaction tx(conn);
        (void)tx;
        setUserVersion(conn, 42);
    }

    EXPECT_THAT(getUserVersion(conn), Eq(origVersion));
}

TEST(ScopedTransaction, commitEndsTransaction)
{
    auto conn = makeConnection();
    SmartSqlite::ScopedTransaction tx(conn);
    tx.commit();

    // would throw if commit didn't end the transaction
    conn->beginTransaction();
}

TEST(ScopedTransaction, commitCancelsRollback)
{
    auto conn = makeConnection();
    setUserVersion(conn, 42);
    int version = 23;
    {
        SmartSqlite::ScopedTransaction tx(conn);
        tx.commit();

        conn->beginTransaction();
        setUserVersion(conn, version);
    }

    // user_version would be 42 if ~ScopedTransaction would rollback
    EXPECT_THAT(getUserVersion(conn), Eq(version));
}
<|endoftext|>


<commit_before>/*
 * Written by Nitin Kumar Maharana
 * nitin.maharana@gmail.com
 */

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    TreeNode* buildTree(vector<int>& inorder, vector<int>& preorder, int l, int r, int i)
    {
        if(l > r || i >= preorder.size())
            return NULL;

        int found = -1;

        for(int j = l; j <= r; j++)
        {
            if(inorder[j] == preorder[i])
            {
                found = j;
                break;
            }
        }

        if(found == -1)
            return buildTree(inorder, preorder, l, r, i+1);

        TreeNode* head;

        head = new TreeNode(preorder[i]);

        head->left = buildTree(inorder, preorder, l, found-1, i+1);

        head->right = buildTree(inorder, preorder, found+1, r, i+1);
    }
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return buildTree(inorder, preorder, 0, inorder.size()-1, 0);
    }
};<commit_msg>105. Construct Binary Tree from Preorder and Inorder Traversal - Optimized<commit_after>/*
 * Written by Nitin Kumar Maharana
 * nitin.maharana@gmail.com
 */

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    TreeNode* buildTree(vector<int>& inorder, vector<int>& preorder, int l, int r, int i)
    {
        if(l > r || i >= preorder.size())
            return NULL;

        int found;

        for(int j = l; j <= r; j++)
        {
            if(inorder[j] == preorder[i])
            {
                found = j;
                break;
            }
        }

        TreeNode* head;

        head = new TreeNode(preorder[i]);

        head->left = buildTree(inorder, preorder, l, found-1, i+1);

        head->right = buildTree(inorder, preorder, found+1, r, i+1+found-l);
    }
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return buildTree(inorder, preorder, 0, inorder.size()-1, 0);
    }
};<|endoftext|>