PageRenderTime 53ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/Snippets/ProxyStuff/OtherIdeas/ProxyCode.sc

http://github.com/iani/SC
Scala | 333 lines | 221 code | 38 blank | 74 comment | 17 complexity | e5e16b425ce09f0f9d96d4c2e00f7ad3 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, AGPL-1.0
  1. /* IZ 2012 07 01
  2. Evaluate a snippet from a Document and set the resulting object as source to a proxy named after the name of the snippet.
  3. Additional methods for starting, stopping, or incrementing / decrementing the volume of the proxy.
  4. Add the proxy code in History but also add the snippet that was evaluated in a history of snippets for this proxy.
  5. Some of the functionality is evoked by keyboard shortcuts set by Code, another part is used via gui through the ProxySourceEditor.
  6. New version Sat 29 September 2012 12:32 PM EEST, will work without doc, so that it can be used with data saved in sctxar by ScriptListGui. See ProxyCodeParser
  7. */
  8. ProxyCode {
  9. classvar all; // all ProxyCode instances in a Dictionary by ProxySpace
  10. classvar <historyTimer; // routine that counts time from last executed snippet
  11. classvar <>historyEndInterval = 300; // end History if nothing has been done for 5 minutes
  12. var <doc; // the document from which this snippet was created.
  13. var <proxySpace;
  14. var <proxy;
  15. var <proxyName;
  16. var <params; // parameters and their specs, as parsed from the proxy and
  17. // from the initial comment line of the snippet
  18. var <snippet;
  19. var <index;
  20. /*
  21. *initClass {
  22. // since CmdPeriod stops routines, restart the historyTimer routine
  23. StartUp add: {
  24. CmdPeriod add: { { this.startHistoryTimer }.defer(0.1) };
  25. CocoaMenuItem.add(["Load all Snippet Proxies"], { this.loadAll });
  26. };
  27. }
  28. */
  29. *startHistoryTimer {
  30. if (historyTimer.notNil) { historyTimer.stop };
  31. historyTimer = {
  32. historyEndInterval.wait;
  33. History.end;
  34. }.fork(AppClock);
  35. }
  36. *new { | doc |
  37. var new;
  38. doc = doc ?? { Document.current; };
  39. new = this.all[doc];
  40. if (new.isNil) { new = this.newCopyArgs(doc).init };
  41. ^new;
  42. }
  43. *all {
  44. if (all.isNil) { all = IdentityDictionary.new };
  45. ^all;
  46. }
  47. init {
  48. all[doc] = this;
  49. // proxyHistory = IdentityDictionary.new;
  50. this.initProxySpace;
  51. }
  52. initProxySpace {
  53. proxySpace = Document.prepareProxySpace(doc);
  54. }
  55. getSnippet {
  56. var code;
  57. if (History.started.not) {
  58. History.clear;
  59. History.start;
  60. this.enterSnippet2History("ProxySpace.push");
  61. };
  62. if (doc.envir.isNil) { this.initProxySpace };
  63. code = Code(doc);
  64. index = code.findIndexOfSnippet;
  65. ^snippet = code.getSnippetStringAt(index);
  66. }
  67. getProxy { | argSnippet, argIndex |
  68. ^proxy = proxySpace[this.getProxyName(argSnippet ? snippet, argIndex ? index)];
  69. }
  70. getProxyName { | argSnippet, argIndex = 0 |
  71. ^(argSnippet.findRegexp("^//:([a-z][a-zA-Z0-9_]+)")[1] ?? {
  72. [0, format("out%", argIndex)]
  73. })[1].asSymbol;
  74. }
  75. makeProxyHistoryFromDoc { | eraseDuplicates = true |
  76. // get all proxies and all snippets, and store them in proxyHistory.
  77. // Can be used to open ProxySourceEditor on the entire document, with history ready.
  78. // It will also create proxies for all snippets with different names on the comment line
  79. // TODO: if eraseDuplicates is true, then remove from history
  80. // identical snippets for the same proxy.
  81. Code(doc).getAllSnippetStrings(skipFirstSnippet: false) do: { | newSnippet, argIndex |
  82. this.addNodeSourceCodeToHistory(
  83. proxySpace[this.getProxyName(newSnippet, argIndex).asSymbol],
  84. newSnippet;
  85. )
  86. };
  87. }
  88. /*
  89. clearProxyHistory { // NOT TESTED
  90. // when clearing history, changed any editors or other objects
  91. var oldProxies;
  92. oldProxies = proxyHistory.keys;
  93. proxyHistory = IdentityDictionary.new;
  94. oldProxies do: { | oldProxy |
  95. this.changedHistoryChanged(oldProxy, [], oldProxy);
  96. }
  97. }
  98. */
  99. removeDuplicatesFromProxyHistory {
  100. // under construction
  101. // remove those snippets from proxyHistory that have been entered twice.
  102. }
  103. evalInProxySpace { | argSnippet, argProxy, argProxyName, start = true, addToSourceHistory = true |
  104. /* evaluate a code snippet and set it as source to a proxy
  105. If argSnippet, argProxy, argProxyName are not given, then extract
  106. proxy, proxyName and snippet from the code of doc.
  107. If snippet begins with a comment, skip this when entering the code to History
  108. */
  109. var index, source;
  110. snippet = argSnippet ?? { this.getSnippet };
  111. source = snippet.interpret;
  112. if (source.isValidProxyCode) {
  113. /* TODO: If the snippet comes from a ProxySourceEditor, then parse proxy name
  114. from snippet, and use that if available. changed ProxySourceEditor to change
  115. proxy name */
  116. proxy = argProxy ?? { this.getProxy };
  117. argProxyName !? { proxyName = argProxyName };
  118. proxy.source = source;
  119. if (snippet[0] == $/) {
  120. index = snippet indexOf: $\n;
  121. this.enterSnippet2History(
  122. format("%~% = %", snippet[..index], proxyName, snippet[index + 1..])
  123. );
  124. MergeSpecs.parseArguments(proxy, snippet);
  125. }{
  126. this enterSnippet2History: format("~% = %", proxyName, snippet);
  127. MergeSpecs.parseArguments(proxy);
  128. };
  129. if (addToSourceHistory) { this.addNodeSourceCodeToHistory(proxy, snippet); };
  130. if (proxy.rate === \audio and: { start } and: { proxy.isMonitoring.not }) {
  131. this.startProxy(proxy, proxyName);
  132. };
  133. }{
  134. postf("snippet: %\n", snippet);
  135. this.enterSnippet2History(snippet);
  136. }
  137. ^proxy;
  138. }
  139. enterSnippet2History { | argSnippet |
  140. History.enter(argSnippet);
  141. this.class.startHistoryTimer;
  142. }
  143. // proxy history stuff
  144. /* Under review: proxyHistory variable will be removed. proxy histories stored in
  145. Library.at('Proxies', proxySpace) inside ProxyItems.
  146. Views can alter the proxy history directly, with updates happening via the Value-ListAdapter
  147. mechanism.
  148. The only method that remains then is: addNodeSourceCodeToHistory
  149. */
  150. *replaceProxyHistory { | argProxy, argHistory, argChanger |
  151. /* An application that changes my history sends the new version to me
  152. I changed all applications that I changed, so that they may update.
  153. I send also who updated me, so that the updater will not re-update itself
  154. (otherwise an endless loop would ensue).
  155. */
  156. // proxyHistory[argProxy] = argHistory;
  157. // this.changedHistoryChanged(argProxy, argHistory, argChanger);
  158. }
  159. *changedHistoryChanged { | argProxy, argHistory, argChanger |
  160. /* update interested applications of my new history for a proxy.
  161. Also tell them who did the change, so that the changer may avoid re-updating */
  162. argProxy.changed(\proxyHistory, [argHistory, argChanger]);
  163. }
  164. changedHistoryChanged { | argProxy, argHistory, argChanger |
  165. /* update interested applications of my new history for a proxy.
  166. Also tell them who did the change, so that the changer may avoid re-updating */
  167. this.class.changedHistoryChanged(argProxy, argHistory, argChanger);
  168. }
  169. addNodeSourceCodeToHistory { | argProxy, argSnippet |
  170. proxySpace.proxyItem(argProxy).addSnippet(argSnippet);
  171. }
  172. startProxy { | argProxy, argProxyName |
  173. this.enterSnippet2History(format("~%.play;", argProxyName));
  174. argProxy.play;
  175. postf("proxy % started: %\n", argProxyName, argProxy);
  176. }
  177. deleteNodeSourceCodeFromHistory { | argProxy, snippetIndex |
  178. var history;
  179. // history = proxyHistory[argProxy];
  180. // history.removeAt(snippetIndex - 1);
  181. // this.changedHistoryChanged(argProxy, history, argProxy);
  182. }
  183. editNodeProxySource { | proxy |
  184. ProxyCodeEditor(this, proxy);
  185. }
  186. openProxySourceEditor {
  187. // called by keyboard shortcut from Code
  188. var thisProxy;
  189. this.getSnippet;
  190. thisProxy = this.getProxy;
  191. if (proxySpace.proxyItem(thisProxy).history.size == 0) {
  192. this.addNodeSourceCodeToHistory(thisProxy, snippet);
  193. };
  194. ProxyCodeEditor(proxySpace, proxySpace.proxyItem(thisProxy));
  195. }
  196. playCurrentDocProxy {
  197. this.getSnippetAndProxy;
  198. if (proxy.source.isNil) {
  199. ^this.evalInProxySpace;
  200. };
  201. if (proxy.isMonitoring.not) {
  202. proxy.play;
  203. postf("proxy % started: % \n", proxyName, proxy);
  204. this.enterSnippet2History(format("~%.play", proxyName));
  205. }
  206. }
  207. getSnippetAndProxy {
  208. this.getSnippet;
  209. this.getProxy;
  210. }
  211. stopCurrentDocProxy {
  212. this.getSnippetAndProxy;
  213. this.stopProxy(proxy, proxyName)
  214. }
  215. stopProxy { | argProxy, argProxyName |
  216. argProxy.stop;
  217. // argProxy.end; // fades out well, but not good if using as input to fx NodeProxy
  218. postf("proxy % stopped: %\n", argProxyName, argProxy);
  219. this.enterSnippet2History(format("~%.stop", argProxyName));
  220. }
  221. proxyMixer {
  222. ProxyCodeMixer3(doc, 8);
  223. }
  224. *proxyMixerNano { ^ProxyCodeMixer(Document.current, 8); }
  225. *proxyMixer { ^ProxyCodeMixer3(Document.current, 8); }
  226. changeVol { | increment = 0.1 |
  227. var vol1, vol2;
  228. this.getSnippetAndProxy;
  229. vol1 = proxy.vol;
  230. vol2 = vol1 + increment max: 0;
  231. proxy.vol = vol2;
  232. postf("%: vol % -> %\n", proxyName, vol1.round(0.000001), vol2.round(0.000001));
  233. this.enterSnippet2History(format("~%.vol = %", proxyName, vol2));
  234. }
  235. // =========== Documenting code history ===========
  236. // These have been transferred to ProxySpace and ProxyItem
  237. openHistoryInDoc { | argProxy |
  238. var title, docString;
  239. if (argProxy.isNil) {
  240. title = Date.getDate.format("History for all proxies on %Y-%m-%e at %Hh:%Mm:%Ss");
  241. docString = this.makeHistoryStringForAll;
  242. }{
  243. title = format("History for % on %",
  244. proxySpace.proxyItem(argProxy).name,
  245. Date.getDate.format("%Y-%d-%e at %Hh:%mm:%Ss")
  246. );
  247. docString = this.makeHistoryStringForProxy(proxy);
  248. };
  249. ^Document(title, docString)
  250. }
  251. makeHistoryStringForAll {
  252. var docString, histories;
  253. docString = format(
  254. "/* *********** HISTORY FOR ALL PROXIES on % *********** */\n",
  255. Date.getDate.format("%Y-%m-%e at %Hh:%Mm:%Ss")
  256. );
  257. docString = docString ++ this.makeLoadBuffersString;
  258. histories = Library.at('Proxies', proxySpace) collect: this.makeHistoryStringForProxy(_);
  259. ^histories.inject(docString, { | a, b | a ++ b });
  260. }
  261. makeLoadBuffersString {
  262. var buffers;
  263. buffers = Library.at('Buffers').asArray;
  264. if (buffers.size == 0) { ^"" };
  265. ^buffers.inject("\n// ====== BUFFERS ====== \n\n", { | str, b |
  266. str ++ format("BufferItem(%).load;\n", b.name.asCompileString);
  267. });
  268. }
  269. makeHistoryStringForProxy { | proxyItem |
  270. var myHistory, docString;
  271. myHistory = proxyItem.history;
  272. docString = format(
  273. "\n/* =========== HISTORY FOR % on % =========== */",
  274. proxyItem.name;
  275. Date.getDate.format("%Y-%d-%e at %Hh:%mm:%Ss'")
  276. );
  277. ^myHistory.inject(docString, { | a, b, i |
  278. a
  279. ++ format("\n\n// ***** % ***** \n", i + 1)
  280. ++ b
  281. };
  282. );
  283. }
  284. // =========== Loading all Proxies from a Document ===========
  285. loadAll {
  286. Code(doc).getAllSnippetStrings do: { | snippet, index |
  287. this.addNodeSourceCodeToHistory(this.getProxy(snippet, index), snippet);
  288. }
  289. }
  290. *loadAll { ^this.new(Document.current).loadAll }
  291. }