/ProjectConfig.cpp

https://bitbucket.org/Klinkenstecker/csurf_klinke_mcu · C++ · 195 lines · 154 code · 30 blank · 11 comment · 24 complexity · fdf8343d7ae2afcf82d255fdf5576d0e MD5 · raw file

  1. /**
  2. * Copyright (C) 2009-2012 Steffen Fuerst
  3. * Distributed under the GNU GPL v2. For full terms see the file gplv2.txt.
  4. */
  5. #include "ProjectConfig.h"
  6. #include "csurf.h"
  7. #ifdef EXT_B
  8. #define CONFIG_ID "<MCU_B_KLINKE"
  9. #define CONFIG_ID_JUCE JUCE_T("<MCU_B_KLINKE")
  10. #else
  11. #define CONFIG_ID "<MCU_KLINKE"
  12. #define CONFIG_ID_JUCE JUCE_T("<MCU_KLINKE")
  13. #endif
  14. bool ProcessExtensionLine(
  15. const char *line, ProjectStateContext *ctx, bool isUndo,
  16. struct project_config_extension_t *
  17. reg) // returns BOOL if line (and optionally subsequent lines) processed
  18. {
  19. return ProjectConfig::instance()->processExtensionLine(line, ctx, isUndo,
  20. reg);
  21. }
  22. void SaveExtensionConfig(ProjectStateContext *ctx, bool isUndo,
  23. struct project_config_extension_t *reg) {
  24. ProjectConfig::instance()->saveExtensionConfig(ctx, isUndo, reg);
  25. }
  26. void BeginLoadProjectState(bool isUndo,
  27. struct project_config_extension_t *reg) {
  28. ProjectConfig::instance()->beginLoadProjectState(isUndo, reg);
  29. }
  30. project_config_extension_t csurf_mcu_pcreg = {
  31. ProcessExtensionLine,
  32. SaveExtensionConfig,
  33. BeginLoadProjectState,
  34. NULL,
  35. };
  36. ProjectConfig *ProjectConfig::s_instance = NULL;
  37. ProjectConfig *ProjectConfig::instance() {
  38. if (s_instance == NULL) {
  39. s_instance = new ProjectConfig();
  40. }
  41. return s_instance;
  42. }
  43. ProjectConfig::ProjectConfig(void)
  44. : m_pLastMaster(NULL), m_nextConnectionId(0) {}
  45. ProjectConfig::~ProjectConfig(void) {
  46. for (tXMLStorage::iterator iterStorage = m_xmlStorage.begin();
  47. iterStorage != m_xmlStorage.end(); ++iterStorage) {
  48. delete ((*iterStorage).second);
  49. }
  50. m_xmlStorage.clear();
  51. s_instance = NULL;
  52. }
  53. project_config_extension_t *ProjectConfig::getRegisterInfo() {
  54. return &csurf_mcu_pcreg;
  55. }
  56. bool ProjectConfig::processExtensionLine(
  57. const char *line, ProjectStateContext *ctx, bool isUndo,
  58. struct project_config_extension_t *
  59. reg) // returns BOOL if line (and optionally subsequent lines) processed
  60. {
  61. bool commentign = false;
  62. String buildString;
  63. char linebuf[4096];
  64. if (String(line).contains(CONFIG_ID_JUCE)) {
  65. for (;;) {
  66. if (ctx->GetLine(linebuf, sizeof(linebuf)))
  67. break;
  68. if (String(linebuf).trimStart().startsWithChar('>'))
  69. break;
  70. buildString += String(linebuf);
  71. }
  72. // '<' and '>' can't be used in the project files, so i replace them with
  73. // |#{ and }#| before writing into the file and convert this back here
  74. XmlDocument *pTmpDoc =
  75. new XmlDocument(buildString.replace(JUCE_T("|#{"), JUCE_T("<"))
  76. .replace(JUCE_T("}#|"), JUCE_T(">")));
  77. XmlElement *pElement = pTmpDoc->getDocumentElement();
  78. if (pElement) {
  79. m_signalProjectChanged(pElement, READ);
  80. delete (pElement);
  81. }
  82. delete (pTmpDoc);
  83. return true;
  84. }
  85. return false;
  86. }
  87. void ProjectConfig::saveExtensionConfig(
  88. ProjectStateContext *ctx, bool isUndo,
  89. struct project_config_extension_t *reg) {
  90. bool commentign = false;
  91. // '<' and '>' can't be used in the project files, so i replace them with |#{
  92. // and }#| before writing into the file and convert this back after reading
  93. // from it
  94. String xmlDocString = createXmlDocString()
  95. .replace(JUCE_T("<"), JUCE_T("|#{"))
  96. .replace(JUCE_T(">"), JUCE_T("}#|"));
  97. ctx->AddLine(CONFIG_ID);
  98. // the fucking buffer overwrite in ctx->AddLine took me two days of debugging
  99. // to avoid it, the xmlDocString must be diveded in single parts
  100. int from = 0;
  101. int to = 0;
  102. do {
  103. int to = xmlDocString.indexOfChar(from, '\n');
  104. if (to != -1) {
  105. if (to - from > 4000) {
  106. to = from + 4000;
  107. ctx->AddLine(xmlDocString.substring(from, to).toCString());
  108. } else {
  109. ctx->AddLine(xmlDocString.substring(from, to - 1).toCString());
  110. from = to + 1;
  111. }
  112. } else {
  113. ctx->AddLine(xmlDocString.substring(from).toCString());
  114. break;
  115. }
  116. } while (to != -1); // to < found
  117. ctx->AddLine(">");
  118. }
  119. void ProjectConfig::beginLoadProjectState(
  120. bool isUndo, struct project_config_extension_t *reg) {
  121. checkReaProjectChange();
  122. m_pLastMaster = GetMasterTrack(NULL);
  123. bool commentign = false;
  124. m_signalProjectChanged(NULL, FREE);
  125. }
  126. String ProjectConfig::createXmlDocString() {
  127. XmlElement *root = new XmlElement(JUCE_T("PROJECT_CONFIG"));
  128. m_signalProjectChanged(root, WRITE);
  129. String doc = root->createDocument("", false, false);
  130. delete (root);
  131. return doc;
  132. }
  133. void ProjectConfig::checkReaProjectChange() {
  134. MediaTrack *pActualMasterTrack = GetMasterTrack(NULL);
  135. if (m_pLastMaster != pActualMasterTrack) {
  136. if (m_pLastMaster != NULL) {
  137. store(m_pLastMaster, createXmlDocString());
  138. }
  139. if (m_xmlStorage.find(pActualMasterTrack) != m_xmlStorage.end()) {
  140. m_signalProjectChanged(NULL, FREE);
  141. XmlElement *pDocElement =
  142. m_xmlStorage[pActualMasterTrack]->getDocumentElement();
  143. m_signalProjectChanged(pDocElement, READ);
  144. delete (pDocElement);
  145. }
  146. m_pLastMaster = pActualMasterTrack;
  147. }
  148. }
  149. void ProjectConfig::store(MediaTrack *pMT, String &xmlString) {
  150. if (m_xmlStorage.find(pMT) != m_xmlStorage.end()) {
  151. delete (m_xmlStorage[pMT]);
  152. }
  153. m_xmlStorage[pMT] = new XmlDocument(xmlString);
  154. }
  155. int ProjectConfig::connect2ProjectChangeSignal(
  156. const tProjectChangedSignalSlot &slot) {
  157. m_activeProjectChangedConnections[++m_nextConnectionId] =
  158. m_signalProjectChanged.connect(slot);
  159. return m_nextConnectionId;
  160. }
  161. void ProjectConfig::disconnectProjectChangeSignal(int connectionId) {
  162. m_activeProjectChangedConnections[connectionId].disconnect();
  163. m_activeProjectChangedConnections.erase(
  164. m_activeProjectChangedConnections.find(connectionId));
  165. }