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