///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// File:           CC121Options.cpp                                          //
//                                                                           //
// Functionality:  Control surface option helper class implementation.       //
//                                                                           //
// Author:         Rolf Meyerhoff (rm@matrix44.de)                           //
//                                                                           //
// Copyright:      (C) 2009 by Rolf Meyerhoff. All rights reserved.          //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// License:                                                                  //
//                                                                           //
// This library is free software;  you can redistribute it  and/or modify it //
// under the terms of the GNU Lesser  General Public License as published by //
// the Free Software Foundation;  either version 2.1 of the License,  or (at //
// your option) any later version.                                           //
//                                                                           //
// This  library is  distributed in  the hope that  it will  be useful,  but //
// WITHOUT   ANY   WARRANTY;   without   even   the   implied  warranty   of //
// MERCHANTABILITY or FITNESS FOR A  PARTICULAR PURPOSE.  See the GNU Lesser //
// General Public License for more details.                                  //
//                                                                           //
// You should have received a copy of  the GNU Lesser General Public License //
// along with this library;  if not,  write to the Free Software Foundation, //
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.              //
///////////////////////////////////////////////////////////////////////////////
#include "reaper_cc121.h"

///////////////////////////////////////////////////////////////////////////////
// CC121Options::CC121Options()
///////////////////////////////////////////////////////////////////////////////
// Description:  Default constructor of this struct.
// Parameters:   None.
// Return value: No return value.
// Remarks:      Just initializes the members of this struct.
///////////////////////////////////////////////////////////////////////////////
CC121Options::CC121Options() :
  skipToStartEnd(false),
  rotarySpeed(31),
  midiInDev(-1),
  midiOutDev(-1),
  wrapAround(false),
  useMCP(false),
  rotaryAccel(10),
  valueEncCmd("12"),
  valueBtnCmd("40364"),
  user1BtnCmd("1011"),
  user2BtnCmd("1012"),
  user3BtnCmd("40112"),
  user4BtnCmd("40111"),
  ftSwitchCmd("1013")
{
  // Nothing to do here.
}

///////////////////////////////////////////////////////////////////////////////
// CC121Options::CC121Options()
///////////////////////////////////////////////////////////////////////////////
// Description:  Copy constructor of this struct.
// Parameters:   [in] other: The source struct to copy.
// Return value: No return value.
// Remarks:      Just copies the members of the source struct.
///////////////////////////////////////////////////////////////////////////////
CC121Options::CC121Options(const CC121Options& other) :
  skipToStartEnd(other.skipToStartEnd),
  rotarySpeed(other.rotarySpeed),
  midiInDev(other.midiInDev),
  midiOutDev(other.midiOutDev),
  wrapAround(other.wrapAround),
  useMCP(other.useMCP),
  rotaryAccel(other.rotaryAccel),
  valueEncCmd(other.valueEncCmd),
  valueBtnCmd(other.valueBtnCmd),
  user1BtnCmd(other.user1BtnCmd),
  user2BtnCmd(other.user2BtnCmd),
  user3BtnCmd(other.user3BtnCmd),
  user4BtnCmd(other.user4BtnCmd),
  ftSwitchCmd(other.ftSwitchCmd)
{
  // Nothing to do here.
}

///////////////////////////////////////////////////////////////////////////////
// CC121Options::~CC121Options()
///////////////////////////////////////////////////////////////////////////////
// Description:  Destructor of this struct.
// Parameters:   None.
// Return value: No return value.
// Remarks:      Clears up all allocated resources.
///////////////////////////////////////////////////////////////////////////////
CC121Options::~CC121Options()
{
  // Nothing to do here.
}

///////////////////////////////////////////////////////////////////////////////
// CC121Options::CC121Options()
///////////////////////////////////////////////////////////////////////////////
// Description:  Initialization constructor of this struct.
// Parameters:   [in] config: The members of this struct as text.
// Return value: No return value.
// Remarks:      The configuration is just a sequence of int values. This
//               constructor just loads these values and initializes the
//               members of this struct.
///////////////////////////////////////////////////////////////////////////////
CC121Options::CC121Options(const char* config) :
  skipToStartEnd(false),
  rotarySpeed(31),
  midiInDev(-1),
  midiOutDev(-1),
  wrapAround(false),
  useMCP(false),
  rotaryAccel(10),
  valueEncCmd("12"),
  valueBtnCmd("40364"),
  user1BtnCmd("1011"),
  user2BtnCmd("1012"),
  user3BtnCmd("40112"),
  user4BtnCmd("40111"),
  ftSwitchCmd("1013")
{
  // Read configuration:
  int s_len;
  const char* ptr = config;
  if (ptr)
  {
    // Loop through parameters:
    int param = 0;
    while (*ptr != 0 && param < 21)
    {
      // Skip leading spaces:
      while (*ptr != 0 && *ptr == ' ')
        ptr++;

      // Done?
      if (*ptr == 0)
        break;

      // Is a number?
      bool is_number = ((*ptr >= '0' && *ptr <= '9') || *ptr == '-');

      // Convert value to int:
      int val = is_number ? atoi(ptr) : 0;

      // Fill parameter:
      switch (param)
      {
      case 0:
        skipToStartEnd = val != 0;
        break;
      case 1:
        rotarySpeed = val;
        break;
      case 2:
        midiInDev = val;
        break;
      case 3:
        midiOutDev = val;
        break;
      case 4:
        wrapAround = val != 0;
        break;
      case 5:
        useMCP = val != 0;
        break;
      case 6:
        rotaryAccel = val;
        break;
      case 7:
        s_len = abs(val);
        break;
      case 8:
        valueEncCmd = std::string(ptr, s_len);
        ptr += s_len;
        break;
      case 9:
      case 11:
      case 13:
      case 15:
      case 17:
      case 19:
        s_len = abs(val);
        break;
      case 10:
        valueBtnCmd = std::string(ptr, s_len);
        ptr += s_len;
        break;
      case 12:
        user1BtnCmd = std::string(ptr, s_len);
        ptr += s_len;
        break;
      case 14:
        user2BtnCmd = std::string(ptr, s_len);
        ptr += s_len;
        break;
      case 16:
        user3BtnCmd = std::string(ptr, s_len);
        ptr += s_len;
        break;
      case 18:
        user4BtnCmd = std::string(ptr, s_len);
        ptr += s_len;
        break;
      case 20:
        ftSwitchCmd = std::string(ptr, s_len);
        ptr += s_len;
        break;
      }

      // Next parameter:
      param++;

      // Go to next parameter:
      while (*ptr != 0 && *ptr != ' ')
        ptr++;
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
// CC121Options::WriteConfig()
///////////////////////////////////////////////////////////////////////////////
// Description:  Write members of this struct to a string.
// Parameters:   [out] config: Receives the members of this struct as text.
// Return value: No return value.
// Remarks:      The configuration is just a sequence of int values. This
//               functions just writes the members of this struct into the
//               provided buffer.
///////////////////////////////////////////////////////////////////////////////
void CC121Options::WriteConfig(char* config) const
{
  char buff[512];

  // Parameter check:
  if (!config)
    return;

  // Fill buffer with simple values:
  sprintf(config, "%d %d %d %d %d %d %d", skipToStartEnd, rotarySpeed, midiInDev, midiOutDev, wrapAround, useMCP, rotaryAccel);

  // Add commands, value encoder:
  sprintf(buff, " %d %s", valueEncCmd.length(), valueEncCmd.length() ? valueEncCmd.c_str() : "-");
  strcat(config, buff);

  // Value button:
  sprintf(buff, " %d %s", valueBtnCmd.length(), valueBtnCmd.length() ? valueBtnCmd.c_str() : "-");
  strcat(config, buff);

  // Function button 1:
  sprintf(buff, " %d %s", user1BtnCmd.length(), user1BtnCmd.length() ? user1BtnCmd.c_str() : "-");
  strcat(config, buff);

  // Function button 2:
  sprintf(buff, " %d %s", user2BtnCmd.length(), user2BtnCmd.length() ? user2BtnCmd.c_str() : "-");
  strcat(config, buff);

  // Function button 3:
  sprintf(buff, " %d %s", user3BtnCmd.length(), user3BtnCmd.length() ? user3BtnCmd.c_str() : "-");
  strcat(config, buff);

  // Function button 4:
  sprintf(buff, " %d %s", user4BtnCmd.length(), user4BtnCmd.length() ? user4BtnCmd.c_str() : "-");
  strcat(config, buff);

  // Foot switch:
  sprintf(buff, " %d %s", ftSwitchCmd.length(), ftSwitchCmd.length() ? ftSwitchCmd.c_str() : "-");
  strcat(config, buff);
}

///////////////////////////////// End of File /////////////////////////////////
