Examples under Synth:new should not use SynthDef:play to make nodes
[supercollider.git] / SCClassLibrary / Platform / Platform.sc
blob31e51a23de674e4a79579ae7083a9d3cea9981f3
1 Platform
3         classvar defaultStartupFile;
4         var <classLibraryDir, <helpDir, <>recordingsDir, features;
6         var <>devpath;
8         *initClass {
9                 defaultStartupFile = this.userConfigDir +/+ "startup.scd"
10         }
12         initPlatform {
13                 classLibraryDir = thisMethod.filenameSymbol.asString.dirname.dirname;
14                 helpDir = thisMethod.filenameSymbol.asString.dirname.dirname.dirname ++ "/Help";
15                 features = IdentityDictionary.new;
16                 recordingsDir = this.userAppSupportDir +/+ "Recordings";
17         }
19         name { ^this.subclassResponsibility }
21         recompile { ^this.subclassResponsibility }
22         *case { | ... cases |
23                 ^thisProcess.platform.name.switch(*cases)
24         }
26         // directories
27         *classLibraryDir { ^thisProcess.platform.classLibraryDir }
28         *helpDir { ^thisProcess.platform.helpDir }
30         systemAppSupportDir { _Platform_systemAppSupportDir }
31         *systemAppSupportDir { ^thisProcess.platform.systemAppSupportDir }
33         userAppSupportDir { _Platform_userAppSupportDir }
34         *userAppSupportDir { ^thisProcess.platform.userAppSupportDir }
36         systemExtensionDir { _Platform_systemExtensionDir }
37         *systemExtensionDir { ^thisProcess.platform.systemExtensionDir }
39         userExtensionDir { _Platform_userExtensionDir }
40         *userExtensionDir { ^thisProcess.platform.userExtensionDir }
42         userConfigDir { _Platform_userConfigDir }
43         *userConfigDir { ^thisProcess.platform.userConfigDir }
45         defaultTempDir { ^this.subclassResponsibility() }
46         *defaultTempDir { ^thisProcess.platform.defaultTempDir }
48         // The "ideName" is for ide-dependent compilation.
49         // From SC.app, the value is "scapp" meaning "scide_scapp" folders will be compiled and other "scide_*" ignored.
50         ideName { _Platform_ideName }
51         *ideName { ^thisProcess.platform.ideName }
53         platformDir { ^this.name.asString }
54         *platformDir { ^thisProcess.platform.platformDir }
56         pathSeparator { ^this.subclassResponsibility }
57         *pathSeparator { ^thisProcess.platform.pathSeparator }
59         isPathSeparator { |char| ^this.subclassResponsibility }
60         *isPathSeparator { |char| ^thisProcess.platform.isPathSeparator(char) }
62         clearMetadata { |path| ^this.subclassResponsibility }
63         *clearMetadata { |path| ^thisProcess.platform.clearMetadata(path) }
65         getMouseCoords { ^this.subclassResponsibility }
66         *getMouseCoords { ^thisProcess.platform.getMouseCoords }
68         // startup/shutdown hooks
69         startup { }
70         shutdown { }
72         startupFiles {
73                 ^[defaultStartupFile];
74         }
76         *deprecatedStartupFiles {|paths|
77                 var postWarning = false;
78                 paths.do {|path|
79                         if (File.exists(path.standardizePath)) {
80                                 warn("Deprecated startup file found: %\n".format(path));
81                                 postWarning = true;
82                         }
83                 };
84                 if (postWarning) {
85                         postln("Please use % as startup file.\nDeprecated startup files will be ignored in future versions.\n".format(defaultStartupFile));
86                 }
87         }
89         loadStartupFiles { this.startupFiles.do{|afile|
90                 afile = afile.standardizePath;
91                 if(File.exists(afile), {afile.load})
92                 }
93         }
95         // features
96         declareFeature { | aFeature |
97                 var str = aFeature.asString;
98                 if (str.first.isUpper) {
99                         Error("cannot declare class name features").throw;
100                 };
101                 if (str.first == $_) {
102                         Error("cannot declare primitive name features").throw;
103                 };
104                 features.put(aFeature, true);
105         }
106         hasFeature { | symbol |
107                 if (features.includesKey(symbol).not) {
108                         features.put(
109                                 symbol,
110                                 symbol.asSymbol.asClass.notNil or: { symbol.isPrimitive }
111                         )
112                 };
113                 ^features.at(symbol)
114         }
115         when { | features, ifFunction, elseFunction |
116                 ^features.asArray.inject(true, { |v,x|
117                         v and: { this.hasFeature(x) }
118                 }).if(ifFunction, elseFunction)
119         }
120         *when {  | features, ifFunction, elseFunction |
121                 ^thisProcess.platform.when(features, ifFunction, elseFunction)
122         }
124         // Prefer qt but fall back to swing if qt not installed.
125         defaultGUIScheme { if (GUI.get(\qt).notNil) {^\qt} {^\swing} }
126         defaultHIDScheme { ^\none }
128         isSleeping { ^false } // unless defined otherwise
130         // used on systems to deduce a svn directory path, if system wide location is used for installed version. (tested on Linux).
131         devLoc{ |inpath|
132                 var outpath;
133                 if ( devpath.isNil ){ ^inpath };
134                 outpath = inpath.copyToEnd( inpath.find( "SuperCollider") );
135                 outpath = outpath.replace( "SuperCollider", devpath );
136                 ^outpath;
137         }
139         // hook for clients to write frontend.css
140         writeClientCSS {}
142         killAll { |cmdLineArgs|
143                 ^this.subclassResponsibility(\killAll)
144         }
147 UnixPlatform : Platform
149         pathSeparator { ^$/ }
151         isPathSeparator { |char|
152                 ^(char === this.pathSeparator)
153         }
155         clearMetadata { |path|
156                 "rm -f %\.*meta".format(path.splitext[0].escapeChar($ )).systemCmd;
157         }
159         arch {
160                 var pipe, arch;
161                 pipe = Pipe("arch", "r");
162                 arch = pipe.getLine;
163                 pipe.close;
164                 ^arch.asSymbol;
165         }
167         killAll { |cmdLineArgs|
168                 ("killall -9 " ++ cmdLineArgs).unixCmd;
169         }
171         defaultTempDir {
172                 // +/+ "" looks funny but ensures trailing slash
173                 ^["/tmp/", this.userAppSupportDir +/+ ""].detect({ |path|
174                         File.exists(path);
175                 });
176         }