Codebase list supercollider / c0429f9
Imported Upstream version 3.4.2 Dan Stowell 13 years ago
54 changed file(s) with 419 addition(s) and 2886 deletion(s). Raw diff Collapse all Expand all
00 -*-text-*---------------------------------------------------------------
11 supercollider 3 for linux
22 ------------------------------------------------------------------------
3 $Id: README LINUX 10144 2010-06-05 07:37:21Z danstowell $
3 $Id$
44 ------------------------------------------------------------------------
55
66 ------------------------------------------------------------------------
0 3.4
1 classvar scVersionMajor=3, scVersionMinor=4, scVersionPostfix="";
0 3.4.2
1 classvar scVersionMajor=3, scVersionMinor=4, scVersionPostfix=".2";
5757 // Returns TRUE iff 'name' is to be ignored during compilation.
5858 bool sc_SkipDirectory(const char *name);
5959
60 void sc_ResolveIfAlias(const char *path, char *returnPath, bool &isAlias, int length);
60 int sc_ResolveIfAlias(const char *path, char *returnPath, bool &isAlias, int length);
6161
6262 extern char *gIdeName; // string used for conditional compilation according to which IDE is in use this session.
6363 // for example, if the value is "scapp" then folders "scide_scapp" will be included, all other "scide_*" excluded.
00 // emacs: -*- c++ -*-
11 // file: SC_StringBuffer.h
22 // copyright: 2003 stefan kersten <steve@k-hornz.de>
3 // cvs: $Id: SC_StringBuffer.h 9082 2009-04-20 08:38:27Z danstowell $
3 // cvs: $Id$
44
55 // This program is free software; you can redistribute it and/or
66 // modify it under the terms of the GNU General Public License as
00 // emacs: -*- c++ -*-
11 // file: SC_StringParser.h
22 // copyright: 2003-2006 stefan kersten
3 // cvs: $Id: SC_StringParser.h 9082 2009-04-20 08:38:27Z danstowell $
3 // cvs: $Id$
44
55 // This program is free software; you can redistribute it and/or
66 // modify it under the terms of the GNU General Public License as
7575 void yyerror(char *s) ;
7676 void fatal() ;
7777 bool isValidSourceFileName(char *filename);
78 bool passOne_ProcessOneFile(char *filename, int level);
78 bool passOne_ProcessOneFile(const char *filename, int level);
7979
8080 extern void asRelativePath(char *inPath,char *outPath);
8181
193193 inline bool NotFloat(PyrSlot* slot) { return (((slot)->utag & 0xFFFFFFF0) == 0x7FF90000); }
194194
195195 inline bool IsPtr(PyrSlot* slot) { return ((slot)->utag == tagPtr); }
196 inline bool NotPtr(PyrSlot* slot) { return ((slot)->utag != tagPtr); }
196197
197198 inline void SetRawChar(PyrSlot* slot, int val) { assert(IsChar(slot)); slot->uc = val; }
198199 inline void SetRaw(PyrSlot* slot, int val) { assert(IsInt(slot)); slot->ui = val; }
00 // emacs: -*- c++ -*-
11 // file: SC_LibraryConfig.h
2 // cvs: $Id: SC_LibraryConfig.h 9417 2009-09-26 06:17:48Z timblech $
2 // cvs: $Id$
33
44 // This program is free software; you can redistribute it and/or
55 // modify it under the terms of the GNU General Public License as
3131 done
3232 shift $(($OPTIND - 1))
3333
34 revision=`svnversion -n ../../`
35 if ( echo $revision | grep "M" > /dev/null 2>&1 ); then
36 echo "WARNING: The working copy has uncommitted changes which will be included in the package."
34 revision=`git rev-list HEAD -1 | sed -E 's/([[:alnum:]]{1,10}).*/\1/'`
35 if [ "`git status -s -uno`" != "" ]; then
36 echo "WARNING: The working copy has uncommitted changes which will NOT be included in the package."
3737 fi
38
39 if ( echo $revision | grep ":" > /dev/null 2>&1 ); then
40 echo "WARNING: The working copy has mixed revision numbers (some folders had 'svn update' ran more recently than others)."
41 fi
42 revision=`echo $revision | sed -e 's/^[^:]*://;s/[A-Za-z]//'`
4338
4439 if [ $package_type == "source" ]; then
4540 mkdir SuperCollider-Source
46 svn export -q --force ../../ SuperCollider-Source
41 returndir=`pwd`
42 cd ../../
43 git archive $revision | tar -x --exclude ".gitignore" -C "$returndir/SuperCollider-Source"
44 cd $returndir
4745
4846 if $include_optionals; then
4947 cp -Rp optional SuperCollider-Source/optional_installs
5654 fi
5755
5856 # Here we build a list of (many) files that are useless on linux, so as to build a slimline source.tar.gz
59 find SuperCollider-Source -iname windows -or -iname osx -or -name "*.xcodeproj" -or -name scide_scapp -or -name "iPhone*" > LinuxExclusions.txt
57 find SuperCollider-Source -iname windows -or -iname osx -or -name "*.xcodeproj" -or -name scide_scapp -or -iname "iPhone*" > LinuxExclusions.txt
6058 echo 'SuperCollider-Source/SuperColliderAU
6159 SuperCollider-Source/Psycollider
6260 SuperCollider-Source/README OS X
6866 SuperCollider-Source/mac
6967 SuperCollider-Source/iphone
7068 SuperCollider-Source/common/Source/lang/LangPrimSource/HID_Utilities
69 SuperCollider-Source/common/Source/lang/LangPrimSource/WiiMote_OSX
7170 SuperCollider-Source/common/Headers/app
7271 SuperCollider-Source/common/Source/app' >> LinuxExclusions.txt
7372
8786 about_version="$version (Revision $revision)"
8887 echo "About box version string:" $about_version
8988
90 svn export -q --force ../../common/build SuperCollider
91 cp -R ../../common/build/SuperCollider.app ../../common/build/scsynth ../../common/build/sclang SuperCollider
92 cp ../../common/build/plugins/* SuperCollider/plugins/
93 cp ../../COPYING SuperCollider/COPYING
89 mkdir -p SuperCollider/plugins
90 returndir=`pwd`
91 cd ../../common/build
92 git archive $revision | tar -x -C "$returndir/SuperCollider"
93 cp -R SuperCollider.app scsynth sclang "$returndir/SuperCollider/"
94 cp plugins/* "$returndir/SuperCollider/plugins/"
95 cp ../../COPYING "$returndir/SuperCollider/"
96 cd $returndir
9497 find SuperCollider/help/ \( -name "*.htm" -or -name "*.html" \) -exec /Developer/Tools/SetFile -c SCjm {} \;
9598 defaults write $PWD/SuperCollider/SuperCollider.app/Contents/Info CFBundleVersion -string "$about_version"
9699 defaults write $PWD/SuperCollider/SuperCollider.app/Contents/Info CFBundleGetInfoString -string "$version"
5050 CPU = short_cpu_name(platform.uname()[4])
5151
5252 ANY_FILE_RE = re.compile('.*')
53 HELP_FILE_RE = re.compile('.*\.(rtf(d)?|scd|html)$')
53 HELP_FILE_RE = re.compile('.*\.(rtf(d)?|scd|htm(l)?)$')
5454 SC_FILE_RE = re.compile('.*\.sc$')
5555 SRC_FILE_RE = re.compile('.*\.(c(pp)|h)$')
5656
266266 def make_static_objects(env, sources, postfix="_a"):
267267 return map(lambda x: make_static_object(env, x, postfix), sources)
268268
269 # for linking libX.so => libX.so.1 on *nixy systems. Note, they must be in same dir.
270 def make_local_symlink(target, source, env):
271 targetname = os.path.basename(str(target[0]))
272 if os.path.isfile(targetname):
273 if not os.path.islink(targetname):
274 liblog.error("ERROR: cannot create symlink %s because already exists as non-symlink." % (targetname))
275 else:
276 os.symlink(os.path.basename(str(source[0])), targetname)
277 return None
278
279 # for linking libX.so => libX.so.1 on *nixy systems. Note, they must be in same dir.
280 def make_local_symlink(target, source, env):
281 targetname = os.path.basename(str(target[0]))
282 if os.path.isfile(targetname):
283 if not os.path.islink(targetname):
284 liblog.error("ERROR: cannot create symlink %s because already exists as non-symlink." % (targetname))
285 else:
286 os.symlink(os.path.basename(str(source[0])), targetname)
287 return None
288
269289 # ======================================================================
270290 # command line options
271291 # ======================================================================
287307 BoolOption('DEBUG',
288308 'Build with debugging information', 0),
289309 PathOption('DESTDIR',
290 'Intermediate installation prefix for packaging', '/'),
310 'Intermediate installation prefix for packaging', '/',
311 PathOption.PathAccept),
291312 BoolOption('DEVELOPMENT',
292313 'Build and install the development files', 0),
293314 BoolOption('FFTW',
750771 '#Headers/server'],
751772 CPPDEFINES = [('SC_PLUGIN_DIR', '\\"' + pkg_lib_dir(FINAL_PREFIX, 'plugins') + '\\"'), ('SC_PLUGIN_EXT', '\\"' + PLUGIN_EXT + '\\"')],
752773 LIBPATH = 'build')
774
775 # platform specific
776
777 # functionality of libdl is included in libc on freebsd
778 if PLATFORM == 'freebsd':
779 serverEnv.Append(LIBS = ['common', 'pthread'])
780 else:
781 serverEnv.Append(LIBS = ['common', 'pthread', 'dl'])
782
783 if PLATFORM == 'darwin':
784 serverEnv.Append(
785 LINKFLAGS = [
786 '-framework', 'CoreServices'])
787 elif PLATFORM == 'linux':
788 serverEnv.Append(
789 CPPDEFINES = [('SC_PLUGIN_LOAD_SYM', '\\"load\\"')],
790 LINKFLAGS = ['-Wl,-rpath,' + FINAL_PREFIX + '/lib'])
791
792 elif PLATFORM == 'freebsd':
793 serverEnv.Append(CPPDEFINES = [('SC_PLUGIN_LOAD_SYM', '\\"load\\"')])
794
795 # required libraries
796 merge_lib_info(
797 serverEnv,
798 libraries['sndfile'], libraries['audioapi'])
799
800 # optional features
801 if features['rendezvous']:
802 serverEnv.Append(CPPDEFINES = ['USE_RENDEZVOUS'])
803 merge_lib_info(serverEnv, libraries['rendezvous'])
804
805 if env['CURL']:
806 serverEnv.Append(CPPDEFINES = ['HAVE_LIBCURL'])
807 merge_lib_info(serverEnv, libraries['libcurl'])
808
753809 libscsynthEnv = serverEnv.Clone(
754810 PKGCONFIG_NAME = 'libscsynth',
755811 PKGCONFIG_DESC = 'SuperCollider synthesis server library',
759815 libraries['rendezvous']),
760816 PKGCONFIG_LIBS = ['-lscsynth'],
761817 # PKGCONFIG_LIBS_PRIVATE = ['-lm', '-lpthread', '-ldl'],
762 PKGCONFIG_CFLAGS = ['-D' + PLATFORM_SYMBOL, '-I${includedir}/common', '-I${includedir}/plugin_interface', '-I${includedir}/server']
818 PKGCONFIG_CFLAGS = ['-D' + PLATFORM_SYMBOL, '-I${includedir}/common', '-I${includedir}/plugin_interface', '-I${includedir}/server'],
819 SHLIBSUFFIX='.so.1.0.0',
820 LIBSUFFIXES=['.so.1.0.0']
763821 )
764
765 # platform specific
766
767 # functionality of libdl is included in libc on freebsd
768 if PLATFORM == 'freebsd':
769 serverEnv.Append(LIBS = ['common', 'pthread'])
770 else:
771 serverEnv.Append(LIBS = ['common', 'pthread', 'dl'])
772
773 if PLATFORM == 'darwin':
774 serverEnv.Append(
775 LINKFLAGS = [
776 '-framework', 'CoreServices'])
777 elif PLATFORM == 'linux':
778 serverEnv.Append(
779 CPPDEFINES = [('SC_PLUGIN_LOAD_SYM', '\\"load\\"')],
780 LINKFLAGS = ['-Wl,-rpath,' + FINAL_PREFIX + '/lib'])
781
782 elif PLATFORM == 'freebsd':
783 serverEnv.Append(CPPDEFINES = [('SC_PLUGIN_LOAD_SYM', '\\"load\\"')])
784
785 # required libraries
786 merge_lib_info(
787 serverEnv,
788 libraries['sndfile'], libraries['audioapi'])
789
790 # optional features
791 if features['rendezvous']:
792 serverEnv.Append(CPPDEFINES = ['USE_RENDEZVOUS'])
793 merge_lib_info(serverEnv, libraries['rendezvous'])
794
795 if env['CURL']:
796 serverEnv.Append(CPPDEFINES = ['HAVE_LIBCURL'])
797 merge_lib_info(serverEnv, libraries['libcurl'])
822 if PLATFORM == 'linux':
823 libscsynthEnv.Append(
824 LINKFLAGS = ['-Wl,-soname,libscsynth.so.1.0.0'])
825 # create local symlink for linker to follow (not installed)
826 libscsynthEnv.Command('build/libscsynth.so', 'build/libscsynth.so.1.0.0', make_local_symlink, chdir=1)
798827
799828 libscsynthSources = Split('''
800829 Source/server/Rendezvous.cpp
823852
824853 scsynthSources = ['Source/server/scsynth_main.cpp']
825854
826 libscsynth = serverEnv.SharedLibrary('build/scsynth', libscsynthSources)
855 libscsynth = libscsynthEnv.SharedLibrary('build/scsynth', libscsynthSources)
827856 env.Alias('install-programs', env.Install(lib_dir(INSTALL_PREFIX), [libscsynth]))
857 env.Alias('install-programs', env.Command(lib_dir(INSTALL_PREFIX) + '/libscsynth.so', lib_dir(INSTALL_PREFIX) + '/libscsynth.so.1.0.0', make_local_symlink, chdir=1))
828858
829859 libscsynthStaticSources = libscsynthSources + make_static_objects(serverEnv, commonSources, "_libscsynthStatic");
830860 libscsynthStatic = serverEnv.StaticLibrary('build/scsynth', libscsynthStaticSources)
10321062 PKGCONFIG_PREFIX = FINAL_PREFIX,
10331063 PKGCONFIG_REQUIRES = make_pkgconfig_requires(libraries['sndfile']) + ['libscsynth'],
10341064 PKGCONFIG_LIBS = ['-lsclang'],
1035 PKGCONFIG_CFLAGS = ['-D' + PLATFORM_SYMBOL, '-I${includedir}/common', '-I${includedir}/plugin_interface', '-I${includedir}/lang', '-I${includedir}/server']
1065 PKGCONFIG_CFLAGS = ['-D' + PLATFORM_SYMBOL, '-I${includedir}/common', '-I${includedir}/plugin_interface', '-I${includedir}/lang', '-I${includedir}/server'],
1066 SHLIBSUFFIX='.so.1.0.0',
1067 LIBSUFFIXES=['.so.1.0.0']
10361068 )
10371069 if PLATFORM == 'linux':
10381070 libsclangEnv.Append(
1039 LINKFLAGS = ['-Wl,-soname,libsclang.so'])
1071 LINKFLAGS = ['-Wl,-soname,libsclang.so.1.0.0'])
1072 # create local symlink for linker to follow (not installed)
1073 libsclangEnv.Command('build/libsclang.so', 'build/libsclang.so.1.0.0', make_local_symlink, chdir=1)
1074 Requires('build/libsclang.so.1.0.0', 'build/libscsynth.so')
10401075
10411076 # required libraries
10421077 merge_lib_info(langEnv, libraries['sndfile'])
11391174 sclangSources = ['Source/lang/LangSource/cmdLineFuncs.cpp']
11401175
11411176 if env['LANG']:
1142 libsclang = langEnv.SharedLibrary('build/sclang', libsclangSources)
1177 libsclang = libsclangEnv.SharedLibrary('build/sclang', libsclangSources)
11431178 env.Alias('install-bin', env.Install(lib_dir(INSTALL_PREFIX), [libsclang]))
1179 env.Alias('install-bin', env.Command(lib_dir(INSTALL_PREFIX) + '/libsclang.so', lib_dir(INSTALL_PREFIX) + '/libsclang.so.1.0.0', make_local_symlink, chdir=1))
11441180 if PLATFORM == 'darwin':
11451181 sclangLibs = ['scsynth', 'sclang']
11461182 else:
172172 }
173173
174174
175 void sc_ResolveIfAlias(const char *path, char *returnPath, bool &isAlias, int length)
175 int sc_ResolveIfAlias(const char *path, char *returnPath, bool &isAlias, int length)
176176 {
177177 isAlias = false;
178 #ifdef SC_DARWIN
178 #if defined(__APPLE__) && !defined(SC_IPHONE)
179179 FSRef dirRef;
180180 OSStatus osStatusErr = FSPathMakeRef ((const UInt8 *) path, &dirRef, NULL);
181181 if ( !osStatusErr ) {
182182 Boolean isFolder;
183183 Boolean wasAliased;
184184 OSErr err = FSResolveAliasFile (&dirRef, true, &isFolder, &wasAliased);
185 if (err)
186 {
187 return -1;
188 }
185189 isAlias = wasAliased;
186 if ( !err && wasAliased ) {
190 if (wasAliased)
191 {
187192 UInt8 resolvedPath[PATH_MAX];
188193 osStatusErr = FSRefMakePath (&dirRef, resolvedPath, length);
189 if ( !osStatusErr ) {
190 strncpy(returnPath, (char *) resolvedPath, length);
191 return;
194 if (osStatusErr)
195 {
196 return -1;
192197 }
198 strncpy(returnPath, (char *) resolvedPath, length);
199 return 0;
193200 }
194201 }
195 #elif defined(SC_LINUX)
202 #elif defined(__linux__) || defined(__FreeBSD__)
196203 isAlias = sc_IsSymlink(path);
197 if (!realpath(path, returnPath))
198 strcpy(returnPath, path);
199 return;
200 #elif defined(SC_FREEBSD)
201 isAlias = sc_IsSymlink(path);
202 if (!realpath(path, returnPath))
203 strcpy(returnPath, path);
204 return;
204 if (realpath(path, returnPath))
205 {
206 return 0;
207 }
208
209 return -1;
205210 #endif
206211 strcpy(returnPath, path);
207 return;
212 return 0;
208213 }
209214
210215 // Support for Bundles
543548 char* errstr = (char*)malloc(CURL_ERROR_SIZE);
544549 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errstr);
545550 if((ret = curl_easy_setopt(curl, CURLOPT_URL, mFilename)) != 0){
546 scprintf("CURL setopt error while setting URL. Error code %i\n%s\n", ret, errstr);
551 printf("CURL setopt error while setting URL. Error code %i\n%s\n", ret, errstr);
547552 success = false;
548553 }
549554 if((ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp)) != 0){
550 scprintf("CURL setopt error while setting temp file pointer. Error code %i\n%s\n", ret, errstr);
555 printf("CURL setopt error while setting temp file pointer. Error code %i\n%s\n", ret, errstr);
551556 success = false;
552557 }
553558 //printf("Loading remote file %s...\n", mFilename);
554559 if((ret = curl_easy_perform(curl)) != 0){
555 scprintf("CURL perform error while attempting to access remote file. Error code %i\n%s\n", ret, errstr);
560 printf("CURL perform error while attempting to access remote file. Error code %i\n%s\n", ret, errstr);
556561 success = false;
557562 //}else{
558563 // printf("...done.\n");
00 // emacs: -*- c++ -*-
11 // file: SC_StringBuffer.cpp
22 // copyright: 2003 stefan kersten <steve@k-hornz.de>
3 // cvs: $Id: SC_StringBuffer.cpp 9082 2009-04-20 08:38:27Z danstowell $
3 // cvs: $Id$
44
55 // This program is free software; you can redistribute it and/or
66 // modify it under the terms of the GNU General Public License as
3333 {
3434 toaddr.sin_family = AF_INET; // host byte order
3535 toaddr.sin_port = htons(port); // short, network byte order
36 addr = htonl(addr);
37 toaddr.sin_addr = *((struct in_addr *)&addr);
36 toaddr.sin_addr.s_addr = htonl(addr);
3837 bzero(&(toaddr.sin_zero), 8); // zero the rest of the struct
3938 }
4039
17811781 int newSize = 1;
17821782 int tupSize = obj1->size;
17831783 for (int i=0; i < tupSize; ++i) {
1784 if (isKindOfSlot(slots1+i, class_arrayed_collection)) {
1784 if (isKindOfSlot(slots1+i, class_array)) {
17851785 newSize *= slotRawObject(&slots1[i])->size;
17861786 }
17871787 }
17921792
17931793 for (int i=0; i < newSize; ++i) {
17941794 int k = i;
1795 obj3 = (PyrObject*)instantiateObject(g->gc, obj1->classptr, tupSize, false, true);
1795 obj3 = (PyrObject*)instantiateObject(g->gc, obj1->classptr, tupSize, false, false);
17961796 slots3 = obj3->slots;
17971797 for (int j=tupSize-1; j >= 0; --j) {
1798 if (isKindOfSlot(slots1+j, class_arrayed_collection)) {
1798 if (isKindOfSlot(slots1+j, class_array)) {
17991799 PyrObject *obj4 = slotRawObject(&slots1[j]);
18001800 slotCopy(&slots3[j],&obj4->slots[k % obj4->size]);
1801 g->gc->GCWrite(obj3, obj3);
1801 g->gc->GCWrite(obj3, obj4);
18021802 k /= obj4->size;
18031803 } else {
18041804 slotCopy(&slots3[j],&slots1[j]);
23352335 if(size3 < 1) return errFailed;
23362336
23372337 for(i=0; i<numLists; ++i) {
2338 obj3 = (PyrObject*)instantiateObject(g->gc, obj1->classptr, size3, false, true);
2338 obj3 = (PyrObject*)instantiateObject(g->gc, obj1->classptr, size3, false, false);
23392339 obj3->size = size3;
23402340 slots3 = obj3->slots;
23412341 for(j=0; j<size3; j+=clump) {
29802980
29812981 err = slotIntVal(c, &stacksize);
29822982 if (err) return err;
2983
2984 stacksize = std::max(stacksize, EVALSTACKDEPTH);
29832985
29842986 initPyrThread(g, thread, b, stacksize, (PyrInt32Array*)(slotRawObject(&g->thread->randData)),
29852987 slotRawFloat(&g->thread->beats), slotRawFloat(&g->thread->seconds), &g->thread->clock, true);
11181118 err = slotDoubleVal(b, &delta);
11191119 if (err) return errNone; // return nil OK, just don't schedule
11201120 beats += delta;
1121 if(beats == INFINITY) return errNone; // return nil OK, just don't schedule
11211122
11221123 clock->Add(beats, c);
11231124
11381139 }
11391140
11401141 double beats;
1141 int err = slotDoubleVal(b, &beats);
1142 int err = slotDoubleVal(b, &beats) || (beats == INFINITY);
11421143 if (err) return errNone; // return nil OK, just don't schedule
11431144
11441145 clock->Add(beats, c);
12971298 err = slotDoubleVal(&g->thread->seconds, &seconds);
12981299 if (err) return errNone; // return nil OK, just don't schedule
12991300 seconds += delta;
1301 if(seconds == INFINITY) return errNone; // return nil OK, just don't schedule
13001302 PyrObject* inQueue = slotRawObject(&g->process->sysSchedulerQueue);
13011303
13021304 schedAdd(g, inQueue, seconds, c);
13121314 PyrSlot *c = g->sp;
13131315
13141316 double time;
1315 int err = slotDoubleVal(b, &time);
1317 int err = slotDoubleVal(b, &time) || (time == INFINITY);
13161318 if (err) return errNone; // return nil OK, just don't schedule
13171319 PyrObject* inQueue = slotRawObject(&g->process->sysSchedulerQueue);
13181320
512512
513513 static SerialPort* getSerialPort(PyrSlot* slot)
514514 {
515 if (NotPtr(&slotRawObject(slot)->slots[0]))
516 return NULL;
515517 return (SerialPort*)slotRawPtr(&slotRawObject(slot)->slots[0]);
516518 }
517519
4848 };
4949 typedef struct SCRegExRegion SCRegExRegion;
5050
51 int prString_FindRegexp(struct VMGlobals *g, int numArgsPushed);
52 int prString_FindRegexp(struct VMGlobals *g, int numArgsPushed)
51 static int prString_FindRegexp(struct VMGlobals *g, int numArgsPushed)
5352 {
54 int err;
55
5653 PyrSlot *a = g->sp - 2; // source string
5754 PyrSlot *b = g->sp - 1; // pattern
5855 PyrSlot *c = g->sp; // offset
6461 int stringsize = slotRawObject(a)->size + 1;
6562 int patternsize = slotRawObject(b)->size + 1;
6663 char *string = (char*)malloc(slotRawObject(a)->size + 1);
67 err = slotStrVal(a, string, slotRawObject(a)->size + 1);
64 int err = slotStrVal(a, string, slotRawObject(a)->size + 1);
6865 if (err){
6966 free(string);
7067 return err;
133130 {
134131 result_array->size++;
135132 SetNil(result_array->slots+i);
136 }
137 else
138 {
139 result_array->size++;
140
133 } else {
141134 int match_start = what[i].start;
142135 int match_length = what[i].end - what[i].start;
143136 // post("for i:%i, start %i, end %i\n", i, what[i].start, what[i].end);
144 // char *match = (char*)malloc(match_length);
145 char match[match_length];
137 char match[match_length+1];
146138
147139 strncpy(match, string + offset + match_start, match_length);
148140 match[match_length] = 0;
149141 PyrObject *array = newPyrArray(g->gc, 2, 0, true);
142
143 result_array->size++;
144 SetObject(result_array->slots + i, array);
145 g->gc->GCWrite(result_array, array);
146
147 PyrObject *matched_string = (PyrObject*)newPyrString(g->gc, match, 0, true);
148
150149 array->size = 2;
151150 SetInt(array->slots, match_start + offset);
152151
153 PyrObject *matched_string = (PyrObject*)newPyrString(g->gc, match, 0, true);
154152 SetObject(array->slots+1, matched_string);
155 g->gc->GCWrite(matched_string, array->slots + 1);
153 g->gc->GCWrite(array, matched_string);
156154
157 SetObject(result_array->slots + i, array);
158 g->gc->GCWrite(array, result_array->slots + i);
159155 }
160156 }
161157 }
162158 else
163 {
164159 SetNil(a);
165 }
166 free(what);
167 free(pattern);
168 free(regexStr);
169 free(ustring);
170 free(string);
160
161 free(what);
162 free(pattern);
163 free(regexStr);
164 free(ustring);
165 free(string);
171166 SetObject(a, result_array);
172 g->gc->GCWrite(result_array,a);
173167 //uregex_close(expression);
174168 return errNone;
175169 }
176170
177 nilout:
178 free(string);
179 free(what);
180 free(pattern);
181 free(regexStr);
182 free(ustring);
183 SetNil(a);
184 return errNone;
171 nilout:
172 free(string);
173 free(what);
174 free(pattern);
175 free(regexStr);
176 free(ustring);
177 SetNil(a);
178 return errNone;
185179 }
186180
187181 void initUStringPrimitives();
+0
-13
common/Source/lang/LangPrimSource/WiiMote_OSX/COPYRIGHT.txt less more
0 Max porting by Masayuki Akamatsu
1 Copyright (c) 2006, Masayuki Akamatsu
2 Based on "DarwiinRemote" by Hiroaki Kimura
3 Copyright (c) 2006, Hiroaki Kimura
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 3. Neither the name of this project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11
12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+0
-54
common/Source/lang/LangPrimSource/WiiMote_OSX/HISTORY.txt less more
0 aka.wiiremote Version History
1
2 1.0B6 : 2007.04.24
3
4 - The Classic Controller is supported.
5 - The help patch is updated.
6 - The URLs in [info] subpatch are updated.
7
8 - 'expansion' message enables to use the expansion controller(Nunchuk or Classic Controller).
9 - 'nunchuk' message is obsolete.
10 You should use 'expansion' instead of it even though you can use it for the backward compatibility only.
11
12 - The IR sensor and the expansion controller (ex. Nunchuk) can be used together.
13
14 - The stability on PPC-Mac is a little improved.
15 You have to do the following steps every time you use the Wii Remote on PPC-Mac.
16 (You would set up only once on Intel-Mac.)
17 1: Delete "Nintendo RVL-CNT-01" on "Device" tab in "Bluetooth" System Preference.
18 2: Do the setup for Wii Remote. See http://max.iamas.ac.jp/2061/articles/121.html
19 3: Open "aka.wiiremote.help" and connect it.
20
21
22 1.0B5 : 2007.02.03
23
24 - Nunchuk is supported.
25 ( Classic Controller is NOT supported.)
26 - device address is supported.
27 - outlets and output messages are changed.
28 - some input messages are simplified.
29 - help patch is expanded for Nunchuk.
30
31
32 1.0B4 : 2006.12.24
33
34 - multiple Wii remotes are supported.
35
36
37 1.0B3 : 2006.12.20
38
39 - data acquisition is improved.
40 - unusual vibration sound is resolved.
41
42
43 1.0B2 : 2006.12.15
44
45 - connection/disconnection is improved.
46 - IR sensor is supported.
47 - status report is supported
48 - help patch is rewritten.
49
50
51 1.0B1 : 2006.12.12
52
53 - first release
+0
-1083
common/Source/lang/LangPrimSource/WiiMote_OSX/wiiremote.c less more
0 // wiiremote.c
1 // Copyright by Masayuki Akamatsu
2 // Based on "DarwiinRemote" by Hiroaki Kimura
3
4 #include <unistd.h>
5 #include "wiiremote.h"
6
7
8 // this type is used a lot (data array):
9 typedef unsigned char darr[];
10
11 #define kTrial 10
12 #define kWait 10000
13 // the unit of kWait is microseconds, thus 10000 means 10ms
14
15 #define kWiiIRPixelsWidth 1024.0
16 #define kWiiIRPixelsHeight 768.0
17
18
19 Boolean requestUpdates(WiiRemoteRef wiiremote);
20 void myEventListener(IOBluetoothL2CAPChannelRef channel, void *refCon, IOBluetoothL2CAPChannelEvent *event);
21
22
23 //--------------------------------------------------------------------------------------------
24 //--------------------------------------------------------------------------------------------
25
26 void wiiremote_init(WiiRemoteRef wiiremote)
27 {
28 wiiremote->inquiry = nil;
29 wiiremote->device = nil;
30 wiiremote->ichan = nil;
31 wiiremote->cchan = nil;
32
33 wiiremote->address = nil;
34
35 wiiremote->accX = 0x10;
36 wiiremote->accY = 0x10;
37 wiiremote->accZ = 0x10;
38 wiiremote->buttonData = 0;
39
40 wiiremote->lowZ = 0;
41 wiiremote->lowX = 0;
42 wiiremote->leftPoint = -1;
43 wiiremote->tracking = false;
44
45 wiiremote->batteryLevel = 0;
46
47 wiiremote->readingRegister = false;
48 wiiremote->isMotionSensorEnabled = false;
49 wiiremote->isVibrationEnabled = false;
50 wiiremote->isIRSensorEnabled = false;
51 wiiremote->wiiIRMode = kWiiIRModeExtended;
52 wiiremote->isExpansionPortEnabled = false;
53 wiiremote->isExpansionPortAttached = false;
54 wiiremote->expType = WiiExpNotAttached;
55
56 wiiremote->isLED1Illuminated = false;
57 wiiremote->isLED2Illuminated = false;
58 wiiremote->isLED3Illuminated = false;
59 wiiremote->isLED4Illuminated = false;
60
61 wiiremote->nAccX = 0x10;
62 wiiremote->nAccY = 0x10;
63 wiiremote->nAccZ = 0x10;
64 wiiremote->nButtonData = 0;
65
66 wiiremote->nLowZ = 0;
67 wiiremote->nLowX = 0;
68
69 }
70
71 //--------------------------------------------------------------------------------------------
72 //--------------------------------------------------------------------------------------------
73
74 Boolean openCChan(WiiRemoteRef wiiremote)
75 {
76 short i;
77 IOReturn ret;
78
79 // open L2CAPChannel : BluetoothL2CAPPSM = 17
80 for (i=0; i<kTrial; i++)
81 {
82 ret = IOBluetoothDeviceOpenL2CAPChannelSync(wiiremote->device, &(wiiremote->cchan), 17, myEventListener, (void *)wiiremote);
83 if ( ret == kIOReturnSuccess)
84 break;
85 usleep(kWait); // wait 10ms
86 }
87 if (i==kTrial)
88 {
89 wiiremote->cchan = nil;
90 IOBluetoothDeviceCloseConnection(wiiremote->device);
91 return false;
92 }
93 IOBluetoothObjectRetain(wiiremote->cchan);
94
95 return (ret==kIOReturnSuccess);
96 }
97
98 Boolean openIChan(WiiRemoteRef wiiremote)
99 {
100 short i;
101 IOReturn ret;
102
103 // open L2CAPChannel : BluetoothL2CAPPSM = 19
104 for (i=0; i<kTrial; i++)
105 {
106 ret = IOBluetoothDeviceOpenL2CAPChannelSync(wiiremote->device, &(wiiremote->ichan), 19, myEventListener, (void *)wiiremote);
107 if ( ret == kIOReturnSuccess)
108 break;
109 usleep(kWait); // wait 10ms
110 }
111 if (i==kTrial)
112 {
113 wiiremote->ichan = nil;
114 IOBluetoothL2CAPChannelCloseChannel(wiiremote->cchan);
115 IOBluetoothObjectRelease(wiiremote->cchan);
116 IOBluetoothDeviceCloseConnection(wiiremote->device);
117 return false;
118 }
119 IOBluetoothObjectRetain(wiiremote->ichan);
120
121 return (ret==kIOReturnSuccess);
122 }
123
124 //--------------------------------------------------------------------------------------------
125
126 Boolean sendCommand(WiiRemoteRef wiiremote, unsigned char *data, unsigned short length)
127 {
128 unsigned char buf[40];
129 IOReturn ret;
130 int i;
131
132 memset(buf,0,40);
133 buf[0] = 0x52;
134 memcpy(buf+1, data, length);
135 if (buf[1] == 0x16)
136 length=23;
137 else
138 length++;
139
140 usleep(kWait); // wait 10ms // Done to make sure commands don't happen too fast.
141
142 for (i = 0; i<kTrial; i++)
143 {
144 ret = IOBluetoothL2CAPChannelWriteSync(wiiremote->cchan, buf, length);
145 if (ret == kIOReturnSuccess)
146 break;
147 usleep(kWait);
148 }
149
150 if (ret != kIOReturnSuccess)
151 wiiremote_disconnect(wiiremote);
152
153 return (ret==kIOReturnSuccess);
154 }
155
156 Boolean writeData(WiiRemoteRef wiiremote, const unsigned char *data, unsigned long address, unsigned short length)
157 {
158 unsigned char cmd[22];
159 int i;
160 unsigned long addr = address;
161
162
163 for(i=0 ; i<length ; i++)
164 cmd[i+6] = data[i];
165
166 for(;i<16 ; i++)
167 cmd[i+6]= 0;
168
169 cmd[0] = 0x16;
170 cmd[1] = (addr>>24) & 0xFF;
171 cmd[2] = (addr>>16) & 0xFF;
172 cmd[3] = (addr>> 8) & 0xFF;
173 cmd[4] = (addr>> 0) & 0xFF;
174 cmd[5] = length;
175
176 // and of course the vibration flag, as usual
177 if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01;
178
179 data = cmd;
180
181 return sendCommand(wiiremote, cmd, 22);
182 }
183
184 Boolean readData(WiiRemoteRef wiiremote, unsigned long address, unsigned short length)
185 {
186
187 unsigned char cmd[7];
188 unsigned long addr = address;
189 unsigned short len = length;
190
191 cmd[0] = 0x17;
192 cmd[1] = (addr>>24)&0xFF;
193 cmd[2] = (addr>>16)&0xFF;
194 cmd[3] = (addr>> 8)&0xFF;
195 cmd[4] = (addr>> 0)&0xFF;
196
197 cmd[5] = (len >> 8)&0xFF;
198 cmd[6] = (len >> 0)&0xFF;
199
200 if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01;
201 if (cmd[1] & 0x02) wiiremote->readingRegister = true;
202
203 return sendCommand(wiiremote, cmd, 7);
204 }
205
206 //--------------------------------------------------------------------------------------------
207 //--------------------------------------------------------------------------------------------
208
209 void checkDevice(WiiRemoteRef wiiremote, IOBluetoothDeviceRef device)
210 {
211 CFStringRef name;
212 CFStringRef address;
213
214 if (wiiremote_isconnected(wiiremote))
215 return;
216
217 name = IOBluetoothDeviceGetName(device);
218 address = IOBluetoothDeviceGetAddressString(device);
219 if (name != nil && address != nil)
220 {
221 if (CFStringCompare(name, CFSTR("Nintendo RVL-CNT-01"), 0) == kCFCompareEqualTo)
222 {
223 if ( CFStringGetLength(wiiremote->address) == 0
224 || CFStringCompare(address, wiiremote->address, kCFCompareCaseInsensitive) == kCFCompareEqualTo)
225 {
226 wiiremote->device = IOBluetoothObjectRetain(device);
227 if ( wiiremote_connect(wiiremote) == false )
228 wiiremote_disconnect(wiiremote);
229 }
230 }
231 }
232 }
233
234 void myFoundFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device)
235 {
236 checkDevice((WiiRemoteRef)refCon, device);
237 }
238
239 void myUpdatedFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device, uint32_t devicesRemaining)
240 {
241 checkDevice((WiiRemoteRef)refCon, device);
242 }
243
244 void myCompleteFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOReturn error, Boolean aborted)
245 {
246 IOReturn ret;
247
248 if (aborted) return; // called by stop ;)
249
250 if (error != kIOReturnSuccess)
251 {
252 wiiremote_stopsearch((WiiRemoteRef)refCon);
253 return;
254 }
255
256 /*
257 ret = IOBluetoothDeviceInquiryStart(((WiiRemoteRef)refCon)->inquiry);
258 if (ret != kIOReturnSuccess)
259 {
260 wiiremote_stopsearch((WiiRemoteRef)refCon);
261 }
262 */
263 }
264
265 //--------------------------------------------------------------------------------------------
266
267 Boolean wiiremote_isconnected(WiiRemoteRef wiiremote)
268 {
269 Boolean result;
270
271 result = wiiremote->device != nil && IOBluetoothDeviceIsConnected(wiiremote->device);
272 return result;
273 }
274
275 Boolean wiiremote_search(WiiRemoteRef wiiremote, char *address)
276 {
277 IOReturn ret;
278
279 if (wiiremote->inquiry != nil)
280 return true;
281
282 wiiremote->inquiry = IOBluetoothDeviceInquiryCreateWithCallbackRefCon((void *)wiiremote);
283 IOBluetoothDeviceInquirySetDeviceFoundCallback(wiiremote->inquiry, myFoundFunc);
284 IOBluetoothDeviceInquirySetDeviceNameUpdatedCallback(wiiremote->inquiry, myUpdatedFunc);
285 IOBluetoothDeviceInquirySetCompleteCallback(wiiremote->inquiry, myCompleteFunc);
286
287 if (wiiremote->address != nil)
288 CFRelease(wiiremote->address);
289 wiiremote->address = CFStringCreateWithCString(nil, address, kCFStringEncodingMacRoman);
290
291 ret = IOBluetoothDeviceInquiryStart(wiiremote->inquiry);
292 if (ret != kIOReturnSuccess)
293 {
294 IOBluetoothDeviceInquiryDelete(wiiremote->inquiry);
295 wiiremote->inquiry = nil;
296 return false;
297 }
298 return true;
299 }
300
301 Boolean wiiremote_stopsearch(WiiRemoteRef wiiremote)
302 {
303 IOReturn ret;
304
305 if (wiiremote->inquiry == nil)
306 {
307 return true; // already stopped
308 }
309
310 ret = IOBluetoothDeviceInquiryStop(wiiremote->inquiry);
311
312 if (ret != kIOReturnSuccess && ret != kIOReturnNotPermitted)
313 {
314 // kIOReturnNotPermitted is if it's already stopped
315 }
316
317 IOBluetoothDeviceInquiryDelete(wiiremote->inquiry);
318 wiiremote->inquiry = nil;
319
320 return (ret==kIOReturnSuccess);
321 }
322
323 //--------------------------------------------------------------------------------------------
324 //--------------------------------------------------------------------------------------------
325
326 unsigned char decrypt(unsigned char data)
327 {
328 return (data ^ 0x17) + 0x17;
329 }
330
331 //--------------------------------------------------------------------------------------------
332
333 /**
334 * Handle report 0x21 (Read Data) from wiimote.
335 * dp[0] = Bluetooth header
336 * dp[1] = (0x21) Report/Channel ID
337 * dp[2] = Wiimote Buttons
338 * dp[3] = Wiimote Buttons
339 * dp[4] = High 4 bits = payload size; Low 4 bits = Error flag (0 = all good)
340 * dp[5] = Offset of memory read
341 * dp[6] = Offset of memory read
342 * dp[7+] = the Data.
343 **/
344
345 void handleRAMData(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength)
346 {
347 // specify attached expasion device
348 if ((dp[5] == 0x00) && (dp[6] == 0xF0))
349 {
350 if (decrypt(dp[21]) == 0x00)
351 {
352 wiiremote->expType = WiiNunchuk;
353 }
354 else
355 if (decrypt(dp[21]) == 0x01)
356 {
357 wiiremote->expType = WiiClassicController;
358 }
359 else
360 {
361 wiiremote->expType = WiiExpNotAttached;
362 }
363 // initExpPort = NO;
364 return;
365 }
366
367 // wiimote calibration data
368 if (!wiiremote->readingRegister && dp[5] == 0x00 && dp[6] == 0x20)
369 {
370 wiiremote->wiiCalibData.accX_zero = dp[7];
371 wiiremote->wiiCalibData.accY_zero = dp[8];
372 wiiremote->wiiCalibData.accZ_zero = dp[9];
373
374 //dp[10] - unknown/unused
375
376 wiiremote->wiiCalibData.accX_1g = dp[11];
377 wiiremote->wiiCalibData.accY_1g = dp[12];
378 wiiremote->wiiCalibData.accZ_1g = dp[13];
379 return;
380 }
381
382 // expansion device calibration data.
383 if (wiiremote->readingRegister && dp[5] == 0x00 && dp[6] == 0x20)
384 {
385 if (wiiremote->expType == WiiNunchuk)
386 {
387 //nunchuk calibration data
388 wiiremote->nunchukCalibData.accX_zero = decrypt(dp[7]);
389 wiiremote->nunchukCalibData.accY_zero = decrypt(dp[8]);
390 wiiremote->nunchukCalibData.accZ_zero = decrypt(dp[9]);
391
392 wiiremote->nunchukCalibData.accX_1g = decrypt(dp[11]);
393 wiiremote->nunchukCalibData.accY_1g = decrypt(dp[12]);
394 wiiremote->nunchukCalibData.accZ_1g = decrypt(dp[13]);
395
396 wiiremote->nunchukJoyStickCalibData.x_max = decrypt(dp[15]);
397 wiiremote->nunchukJoyStickCalibData.x_min = decrypt(dp[16]);
398 wiiremote->nunchukJoyStickCalibData.x_center = decrypt(dp[17]);
399
400 wiiremote->nunchukJoyStickCalibData.y_max = decrypt(dp[18]);
401 wiiremote->nunchukJoyStickCalibData.y_min = decrypt(dp[19]);
402 wiiremote->nunchukJoyStickCalibData.y_center = decrypt(dp[20]);
403
404 return;
405 }
406 else
407 if (wiiremote->expType == WiiClassicController)
408 {
409 //classic controller calibration data (probably)
410 }
411 }
412
413 // wii remote buttons
414 wiiremote->buttonData = ((short)dp[2] << 8) + dp[3];
415 }
416
417 void handleStatusReport(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength)
418 {
419 wiiremote->batteryLevel = (double)dp[7];
420 wiiremote->batteryLevel /= (double)0xC0; // C0 = fully charged.
421
422 if ((dp[4] & 0x02)) //some device attached to Wiimote
423 {
424 wiiremote->isExpansionPortAttached = true;
425 // initExpPort = YES;
426
427 Boolean ret = writeData(wiiremote, (darr){0x00}, 0x04A40040, 1); // Initialize the device
428
429 if (ret == false)
430 {
431 wiiremote->isExpansionPortAttached = false;
432 return;
433 }
434
435 usleep(kWait); // Give the write a chance to be processed.
436
437 ret = readData(wiiremote, 0x04A400F0, 16); // read expansion device type
438 if (ret == false)
439 {
440 wiiremote->isExpansionPortAttached = false;
441 }
442 }
443 else
444 { // unplugged
445 wiiremote->isExpansionPortAttached = false;
446 wiiremote->expType = WiiExpNotAttached;
447 }
448
449 if (dp[4] & 0x10)
450 wiiremote->isLED1Illuminated = true;
451 else
452 wiiremote->isLED1Illuminated = false;
453
454 if (dp[4] & 0x20)
455 wiiremote->isLED2Illuminated = true;
456 else
457 wiiremote->isLED2Illuminated = false;
458
459 if (dp[4] & 0x40)
460 wiiremote->isLED3Illuminated = true;
461 else
462 wiiremote->isLED3Illuminated = false;
463
464 if (dp[4] & 0x80)
465 wiiremote->isLED4Illuminated = true;
466 else
467 wiiremote->isLED4Illuminated = false;
468 }
469
470 void handleExtensionData(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength)
471 {
472 unsigned char startByte;
473
474 switch (dp[1]) {
475 case 0x34 :
476 startByte = 4;
477 break;
478 case 0x35 :
479 startByte = 7;
480 break;
481 case 0x36 :
482 startByte = 14;
483 break;
484 case 0x37 :
485 startByte = 17;
486 break;
487 default:
488 return; // This shouldn't ever happen.
489 break;
490 }
491
492 if (wiiremote->expType == WiiNunchuk)
493 {
494 wiiremote->nStickX = decrypt(dp[startByte]);
495 wiiremote->nStickY = decrypt(dp[startByte +1]);
496 wiiremote->nAccX = decrypt(dp[startByte +2]);
497 wiiremote->nAccY = decrypt(dp[startByte +3]);
498 wiiremote->nAccZ = decrypt(dp[startByte +4]);
499 wiiremote->nButtonData = decrypt(dp[startByte +5]);
500
501 wiiremote->nLowZ = wiiremote->nLowZ * .9 + wiiremote->nAccZ * .1;
502 wiiremote->nLowX = wiiremote->nLowX * .9 + wiiremote->nAccX * .1;
503
504 float absx = abs(wiiremote->nLowX - 128);
505 float absz = abs(wiiremote->nLowZ - 128);
506
507 if (wiiremote->nOrientation == 0 || wiiremote->nOrientation == 2) absx -= 5;
508 if (wiiremote->nOrientation == 1 || wiiremote->nOrientation == 3) absz -= 5;
509
510 if (absz >= absx)
511 {
512 if (absz > 5)
513 wiiremote->nOrientation = (wiiremote->nLowZ > 128) ? 0 : 2;
514 }
515 else
516 {
517 if (absx > 5)
518 wiiremote->nOrientation = (wiiremote->nLowX > 128) ? 3 : 1;
519 }
520 }
521 else
522 if (wiiremote->expType == WiiClassicController)
523 {
524 wiiremote->cButtonData = (unsigned short)(decrypt(dp[startByte + 4]) << 8) + decrypt(dp[startByte + 5]);
525 wiiremote->cButtonData = ~wiiremote->cButtonData; // bit reverse
526
527 wiiremote->cStickX1 = decrypt(dp[startByte]) & 0x3F;
528 wiiremote->cStickY1 = decrypt(dp[startByte + 1]) & 0x3F;
529
530 wiiremote->cStickX2 = (((decrypt(dp[startByte +0]) & 0xC0) >> 3) |
531 ((decrypt(dp[startByte +1]) & 0xC0) >> 5) |
532 ((decrypt(dp[startByte +2]) & 0x80) >> 7)) & 0x1F;
533 wiiremote->cStickY2 = decrypt(dp[startByte + 2]) & 0x1F;
534
535 wiiremote->cAnalogL = (((decrypt(dp[startByte +2]) & 0x60) >> 2) |
536 ((decrypt(dp[startByte +3]) & 0xE0) >> 5)) & 0x1F;
537 wiiremote->cAnalogR = decrypt(dp[startByte + 3]) & 0x1F;
538 }
539 }
540
541 void handleIRData(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength)
542 {
543 int i;
544
545 if (dp[1] == 0x33)
546 { // 12 IR bytes
547 int startByte = 0;
548 for(i=0 ; i < 4 ; i++)
549 {
550 startByte = 7 + 3 * i;
551 wiiremote->irData[i].x = (dp[startByte +0] | ((dp[startByte +2] & 0x30) << 4)) & 0x3FF;
552 wiiremote->irData[i].y = (dp[startByte +1] | ((dp[startByte +2] & 0xC0) << 2)) & 0x3FF;
553 wiiremote->irData[i].s = dp[startByte +2] & 0x0F;
554 }
555 }
556 else
557 { // 10 IR bytes
558 int shift = (dp[1] == 0x36) ? 4 : 7;
559 int startByte = 0;
560 for (i=0; i < 2; i++) {
561 startByte = shift + 5 * i;
562 wiiremote->irData[2*i].x = (dp[startByte +0] | ((dp[startByte +2] & 0x30) << 4)) & 0x3FF;
563 wiiremote->irData[2*i].y = (dp[startByte +1] | ((dp[startByte +2] & 0xC0) << 2)) & 0x3FF;
564 wiiremote->irData[2*i].s = ((wiiremote->irData[2*i].x == wiiremote->irData[2*i].y) && (wiiremote->irData[2*i].x == 0x3FF)) ? 0x0F : 0x05; // No size is given in 10 byte report.
565
566 wiiremote->irData[(2*i)+1].x = (dp[startByte +3] | ((dp[startByte +2] & 0x03) << 8)) & 0x3FF;
567 wiiremote->irData[(2*i)+1].y = (dp[startByte +4] | ((dp[startByte +2] & 0x0C) << 6)) & 0x3FF;
568 wiiremote->irData[(2*i)+1].s = ((wiiremote->irData[(2*i)+1].x == wiiremote->irData[(2*i)+1].y) && (wiiremote->irData[(2*i)+1].x == 0x3FF)) ? 0x0F : 0x05; // No size is given in 10 byte report.
569 }
570 }
571
572 int p1 = -1;
573 int p2 = -1;
574 // we should modify this loop to take the points with the lowest s (the brightest ones)
575 for (i=0 ; i<4 ; i++) {
576 if (p1 == -1) {
577 if (wiiremote->irData [i].s < 0x0F)
578 p1 = i;
579 } else {
580 if (wiiremote->irData [i].s < 0x0F) {
581 p2 = i;
582 break;
583 }
584 }
585 }
586
587 double ox, oy;
588 if ((p1 > -1) && (p2 > -1))
589 {
590 int l = wiiremote->leftPoint;
591 if (wiiremote->leftPoint == -1)
592 {
593 switch (wiiremote->orientation)
594 {
595 case 0: l = (wiiremote->irData[p1].x < wiiremote->irData[p2].x) ? 0 : 1; break;
596 case 1: l = (wiiremote->irData[p1].y > wiiremote->irData[p2].y) ? 0 : 1; break;
597 case 2: l = (wiiremote->irData[p1].x > wiiremote->irData[p2].x) ? 0 : 1; break;
598 case 3: l = (wiiremote->irData[p1].y < wiiremote->irData[p2].y) ? 0 : 1; break;
599 }
600
601 wiiremote->leftPoint = l;
602 }
603
604 int r = 1-l;
605
606 double dx = wiiremote->irData[r].x - wiiremote->irData[l].x;
607 double dy = wiiremote->irData[r].y - wiiremote->irData[l].y;
608 double d = hypot (dx, dy);
609
610 dx /= d;
611 dy /= d;
612
613 double cx = (wiiremote->irData[l].x + wiiremote->irData[r].x)/kWiiIRPixelsWidth - 1;
614 double cy = (wiiremote->irData[l].y + wiiremote->irData[r].y)/kWiiIRPixelsHeight - 1;
615
616 ox = -dy*cy-dx*cx;
617 oy = -dx*cy+dy*cx;
618
619 // cam:
620 // Compensate for distance. There must be fewer than 0.75*768 pixels between the spots for this to work.
621 // In other words, you have to be far enough away from the sensor bar for the two spots to have enough
622 // space on the image sensor to travel without one of the points going off the image.
623 // note: it is working very well ...
624 double gain = 4;
625 if (d < (0.75 * kWiiIRPixelsHeight))
626 gain = 1 / (1 - d/kWiiIRPixelsHeight);
627
628 ox *= gain;
629 oy *= gain;
630
631 wiiremote->angle = atan2(dy, dx);
632 wiiremote->tracking = true;
633 }
634 else
635 {
636 ox = oy = -100;
637 wiiremote->leftPoint = -1; // not tracking
638 wiiremote->angle = -100;
639 wiiremote->tracking = false;
640 }
641
642 wiiremote->posX = ox;
643 wiiremote->posY = oy;
644 }
645
646 void handleButtonReport(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength)
647 {
648 // wiimote buttons
649 wiiremote->buttonData = ((short)dp[2] << 8) + dp[3];
650
651 // report contains extension data
652 switch (dp[1])
653 {
654 case 0x34 :
655 case 0x35 :
656 case 0x36 :
657 case 0x37 :
658 handleExtensionData(wiiremote, dp, dataLength);
659 break;
660 }
661
662 // report contains IR data
663 if (dp[1] & 0x02)
664 {
665 handleIRData(wiiremote, dp, dataLength);
666 }
667
668 // report contains motion sensor data
669 if (dp[1] & 0x01)
670 {
671 wiiremote->accX = dp[4];
672 wiiremote->accY = dp[5];
673 wiiremote->accZ = dp[6];
674
675 wiiremote->lowZ = wiiremote->lowZ * 0.9 + wiiremote->accZ * 0.1;
676 wiiremote->lowX = wiiremote->lowX * 0.9 + wiiremote->accX * 0.1;
677
678 float absx = abs(wiiremote->lowX-128);
679 float absz = abs(wiiremote->lowZ-128);
680
681 if (wiiremote->orientation == 0 || wiiremote->orientation == 2) absx -= 5;
682 if (wiiremote->orientation == 1 || wiiremote->orientation == 3) absz -= 5;
683
684 if (absz >= absx)
685 {
686 if (absz > 5)
687 wiiremote->orientation = (wiiremote->lowZ > 128)?0:2;
688 }
689 else
690 {
691 if (absx > 5)
692 wiiremote->orientation = (wiiremote->lowX > 128)?3:1;
693 }
694 }
695 }
696
697 //--------------------------------------------------------------------------------------------
698
699 void myDataListener(IOBluetoothL2CAPChannelRef channel, void *dataPointer, UInt16 dataLength, void *refCon)
700 {
701 WiiRemoteRef wiiremote = (WiiRemoteRef)refCon;
702 unsigned char* dp = (unsigned char*)dataPointer;
703
704 if (!wiiremote->device)
705 return;
706
707 //controller status (expansion port and battery level data) - received when report 0x15 sent to Wiimote (getCurrentStatus:) or status of expansion port changes.
708 if (dp[1] == 0x20 && dataLength >= 8)
709 {
710 handleStatusReport(wiiremote, dp, dataLength);
711 requestUpdates(wiiremote); // Make sure we keep getting state change reports.
712 return;
713 }
714
715 if (dp[1] == 0x21)
716 {
717 handleRAMData(wiiremote, dp, dataLength);
718 return;
719 }
720
721 if (dp[1] == 0x22)
722 { // Write data response
723 //NSLog(@"Write data response: %00x %00x %00x %00x", dp[2], dp[3], dp[4], dp[5]);
724 return;
725 }
726
727 // report contains button info
728 if ((dp[1] & 0xF0) == 0x30)
729 {
730 handleButtonReport(wiiremote, dp, dataLength);
731 }
732 }
733
734 void myEventListener(IOBluetoothL2CAPChannelRef channel, void *refCon, IOBluetoothL2CAPChannelEvent *event)
735 {
736 if (event->eventType == kIOBluetoothL2CAPChannelEventTypeData)
737 {
738 // In thise case:
739 // event->u.newData.dataPtr is a pointer to the block of data received.
740 // event->u.newData.dataSize is the size of the block of data.
741 myDataListener(channel, event->u.data.dataPtr, event->u.data.dataSize, refCon);
742 }
743 else
744 if (event->eventType == kIOBluetoothL2CAPChannelEventTypeClosed)
745 {
746 // In this case:
747 // event->u.terminatedChannel is the channel that was terminated. It can be converted in an IOBluetoothL2CAPChannel
748 // object with [IOBluetoothL2CAPChannel withL2CAPChannelRef:]. (see below).
749 }
750 }
751
752 void myDisconnectedFunc(void * refCon, IOBluetoothUserNotificationRef inRef, IOBluetoothObjectRef objectRef)
753 {
754 CFStringRef itsAddress, myAddress;
755
756 itsAddress = IOBluetoothDeviceGetAddressString(objectRef);
757 if (itsAddress != nil)
758 {
759 myAddress = IOBluetoothDeviceGetAddressString(((WiiRemoteRef)refCon)->device);
760 if (myAddress != nil)
761 {
762 if (CFStringCompare(itsAddress, myAddress, 0) == kCFCompareEqualTo)
763 {
764 wiiremote_disconnect((WiiRemoteRef)refCon);
765 }
766 CFRelease(myAddress);
767 }
768 CFRelease(itsAddress);
769 }
770 }
771
772 //--------------------------------------------------------------------------------------------
773
774 void wiiremote_getaddress(WiiRemoteRef wiiremote, char *address)
775 {
776 CFStringRef cfstring;
777
778 cfstring = IOBluetoothDeviceGetAddressString(wiiremote->device);
779 CFStringGetCString(cfstring, address, 32, kCFStringEncodingMacRoman);
780 CFRelease(cfstring);
781
782 }
783
784 //--------------------------------------------------------------------------------------------
785
786 Boolean wiiremote_connect(WiiRemoteRef wiiremote)
787 {
788 IOReturn ret;
789 Boolean result;
790 short i;
791
792 if (wiiremote->device == nil)
793 return false;
794
795 // connect the device
796 for (i=0; i<kTrial; i++)
797 {
798 ret = IOBluetoothDeviceOpenConnection(wiiremote->device, nil, nil);
799 if ( ret == kIOReturnSuccess)
800 break;
801 usleep(kWait); // wait 10ms
802 }
803 if (i==kTrial)
804 return false;
805
806 wiiremote->disconnectNotification = IOBluetoothDeviceRegisterForDisconnectNotification(wiiremote->device, myDisconnectedFunc, (void *)wiiremote);
807
808 // performs an SDP query
809 for (i=0; i<kTrial; i++)
810 {
811 ret = IOBluetoothDevicePerformSDPQuery(wiiremote->device, nil, nil);
812 if ( ret == kIOReturnSuccess)
813 break;
814 usleep(kWait); // wait 10ms
815 }
816 if (i==kTrial)
817 return false;
818
819 result = openCChan(wiiremote);
820 result = openIChan(wiiremote);
821
822 if (result)
823 {
824 result = wiiremote_led(wiiremote, wiiremote->isLED1Illuminated, wiiremote->isLED2Illuminated, wiiremote->isLED3Illuminated, wiiremote->isLED4Illuminated);
825 }
826
827 if (result == false)
828 {
829 wiiremote_disconnect(wiiremote);
830 return result;
831 }
832
833 wiiremote_getstatus(wiiremote);
834 requestUpdates(wiiremote);
835
836 readData(wiiremote, 0x0020, 7); // Get Accelerometer callibration data
837
838 return true;
839 }
840
841
842 Boolean wiiremote_disconnect(WiiRemoteRef wiiremote)
843 {
844 short i;
845
846 if (wiiremote->cchan)
847 {
848 if (IOBluetoothDeviceIsConnected(wiiremote->device))
849 {
850 for (i=0; i<kTrial; i++)
851 {
852 if (IOBluetoothL2CAPChannelCloseChannel(wiiremote->cchan) == kIOReturnSuccess)
853 break;
854 usleep(kWait); // wait 10ms
855 }
856 }
857 if (i==kTrial) return false;
858 IOBluetoothObjectRelease(wiiremote->cchan);
859 wiiremote->cchan = nil;
860 }
861
862 if (wiiremote->ichan)
863 {
864 if (IOBluetoothDeviceIsConnected(wiiremote->device))
865 {
866 for (i=0; i<kTrial; i++)
867 {
868 if (IOBluetoothL2CAPChannelCloseChannel(wiiremote->ichan) == kIOReturnSuccess)
869 break;
870 }
871 }
872 if (i==kTrial) return false;
873 IOBluetoothObjectRelease(wiiremote->ichan);
874 wiiremote->ichan = nil;
875 }
876
877 if (wiiremote->device)
878 {
879 if (IOBluetoothDeviceIsConnected(wiiremote->device))
880 {
881 for (i=0; i<kTrial; i++)
882 {
883 if (IOBluetoothDeviceCloseConnection(wiiremote->device) == kIOReturnSuccess)
884 break;
885 }
886 }
887 if (i==kTrial) return false;
888 IOBluetoothObjectRelease(wiiremote->device);
889 wiiremote->device = nil;
890 }
891
892 if (wiiremote->disconnectNotification != nil)
893 {
894 IOBluetoothUserNotificationUnregister(wiiremote->disconnectNotification);
895 wiiremote->disconnectNotification = nil;
896 }
897
898 return true;
899 }
900
901 //--------------------------------------------------------------------------------------------
902 //--------------------------------------------------------------------------------------------
903
904 Boolean requestUpdates(WiiRemoteRef wiiremote)
905 {
906 Boolean result;
907
908 // Set the report type the Wiimote should send.
909 unsigned char cmd[] = {0x12, 0x02, 0x30}; // Just buttons.
910
911 if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01;
912
913 /*
914 There are numerous status report types that can be requested.
915 The IR reports must be matched with the data format set when initializing the IR camera:
916 0x36, 0x37 - 10 IR bytes go with Basic mode
917 0x33 - 12 IR bytes go with Extended mode
918 0x3e/0x3f - 36 IR bytes go with Full mode
919
920 The Nunchuk and Classic controller use 6 bytes to report their state, so the reports that
921 give more extension bytes don't provide any more info.
922
923 Buttons | Accelerometer | IR | Extension
924 --------------------+-------------------+-----------+-------------
925 0x30: Core Buttons | | |
926 0x31: Core Buttons | Accelerometer | |
927 0x32: Core Buttons | | | 8 bytes
928 0x33: Core Buttons | Accelerometer | 12 bytes |
929 0x34: Core Buttons | | | 19 bytes
930 0x35: Core Buttons | Accelerometer | | 16 bytes
931 0x36: Core Buttons | | 10 bytes | 9 bytes
932 0x37: Core Buttons | Accelerometer | 10 bytes | 6 bytes
933 ?? 0x38: Core Buttons and Accelerometer with 16 IR bytes ??
934 0x3d: | | | 21 bytes
935
936 0x3e / 0x3f: Interleaved Core Buttons and Accelerometer with 16/36 IR bytes
937
938 */
939
940 if (wiiremote->isIRSensorEnabled)
941 {
942 if (wiiremote->isExpansionPortEnabled)
943 {
944 cmd[2] = 0x36; // Buttons, 10 IR Bytes, 9 Extension Bytes
945 wiiremote->wiiIRMode = kWiiIRModeBasic;
946 }
947 else
948 {
949 cmd[2] = 0x33; // Buttons, Accelerometer, and 12 IR Bytes.
950 wiiremote->wiiIRMode = kWiiIRModeExtended;
951 }
952
953 // Set IR Mode
954 writeData(wiiremote, (darr){ wiiremote->wiiIRMode }, 0x04B00033, 1);
955 usleep(kWait); // wait 10ms
956 }
957 else
958 {
959 if (wiiremote->isExpansionPortEnabled)
960 {
961 cmd[2] = 0x34; // Buttons, 19 Extension Bytes
962 }
963 else
964 {
965 cmd[2] = 0x30; // Buttons
966 }
967 }
968
969 if (wiiremote->isMotionSensorEnabled) cmd[2] |= 0x01; // Add Accelerometer
970
971 usleep(kWait); // wait 10ms
972 result = sendCommand(wiiremote, cmd, 3);
973
974 return(result);
975 }
976
977 //--------------------------------------------------------------------------------------------
978
979 Boolean wiiremote_motionsensor(WiiRemoteRef wiiremote, Boolean enabled)
980 {
981 wiiremote->isMotionSensorEnabled = enabled;
982 return requestUpdates(wiiremote);
983 }
984
985 Boolean wiiremote_vibration(WiiRemoteRef wiiremote, Boolean enabled)
986 {
987
988 wiiremote->isVibrationEnabled = enabled;
989 return requestUpdates(wiiremote);
990 }
991
992 Boolean wiiremote_led(WiiRemoteRef wiiremote, Boolean enabled1, Boolean enabled2, Boolean enabled3, Boolean enabled4)
993 {
994 unsigned char cmd[] = {0x11, 0x00};
995 if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01;
996 if (enabled1) cmd[1] |= 0x10;
997 if (enabled2) cmd[1] |= 0x20;
998 if (enabled3) cmd[1] |= 0x40;
999 if (enabled4) cmd[1] |= 0x80;
1000
1001 wiiremote->isLED1Illuminated = enabled1;
1002 wiiremote->isLED2Illuminated = enabled2;
1003 wiiremote->isLED3Illuminated = enabled3;
1004 wiiremote->isLED4Illuminated = enabled4;
1005
1006 return sendCommand(wiiremote, cmd, 2);
1007 }
1008
1009 Boolean wiiremote_expansion(WiiRemoteRef wiiremote, Boolean enabled)
1010 {
1011 wiiremote->isExpansionPortEnabled = enabled;
1012 if (wiiremote->isExpansionPortAttached == false)
1013 {
1014 wiiremote->isExpansionPortEnabled = false;
1015 }
1016 else
1017 {
1018 readData(wiiremote, 0x04A40020, 16); //get calbdata
1019 }
1020
1021 return requestUpdates(wiiremote);
1022 }
1023
1024 Boolean wiiremote_irsensor(WiiRemoteRef wiiremote, Boolean enabled)
1025 {
1026 Boolean ret;
1027
1028 wiiremote->isIRSensorEnabled = enabled;
1029
1030 // ir enable 1
1031 unsigned char cmd[] = {0x13, 0x00};
1032 if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01;
1033 if (wiiremote->isIRSensorEnabled) cmd[1] |= 0x04;
1034 if ((ret = sendCommand(wiiremote, cmd, 2)) == false)
1035 return ret;
1036 usleep(kWait);
1037
1038 // set register 0x1a (ir enable 2)
1039 unsigned char cmd2[] = {0x1a, 0x00};
1040 if (enabled) cmd2[1] |= 0x04;
1041 if ((ret = sendCommand(wiiremote, cmd2, 2)) == false)
1042 return ret;
1043 usleep(kWait);
1044
1045 if(enabled)
1046 {
1047 // based on marcan's method, found on wiili wiki:
1048 // tweaked to include some aspects of cliff's setup procedure in the hopes
1049 // of it actually turning on 100% of the time (was seeing 30-40% failure rate before)
1050 // the sleeps help it it seems
1051 usleep(kWait);
1052 if ((ret = writeData(wiiremote, (darr){0x01}, 0x04B00030, 1)) == false) return ret;
1053 usleep(kWait);
1054 if ((ret = writeData(wiiremote, (darr){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xC0}, 0x04B00000, 9)) == false) return ret;
1055 usleep(kWait);
1056 if ((ret = writeData(wiiremote, (darr){0x40, 0x00}, 0x04B0001A, 2)) == false) return ret;
1057 usleep(kWait);
1058 if ((ret = writeData(wiiremote, (darr){0x08}, 0x04B00030, 1)) == false) return ret;
1059 usleep(kWait);
1060
1061 requestUpdates(wiiremote);
1062 }
1063 else
1064 {
1065 // probably should do some writes to power down the camera, save battery
1066 // but don't know how yet.
1067
1068 ret = wiiremote_motionsensor(wiiremote, wiiremote->isMotionSensorEnabled);
1069 ret = wiiremote_vibration(wiiremote, wiiremote->isVibrationEnabled);
1070 ret = wiiremote_expansion(wiiremote, wiiremote->isExpansionPortEnabled);
1071 }
1072
1073 return ret;
1074 }
1075
1076 Boolean wiiremote_getstatus(WiiRemoteRef wiiremote)
1077 {
1078 unsigned char cmd[] = {0x15, 0x00};
1079 return sendCommand(wiiremote, cmd, 2);
1080 }
1081
1082
+0
-170
common/Source/lang/LangPrimSource/WiiMote_OSX/wiiremote.h less more
0 // wiiremote.h
1 // Copyright by Masayuki Akamatsu
2 // Based on "DarwiinRemote" by Hiroaki Kimura
3
4 #define BLUETOOTH_VERSION_USE_CURRENT
5 //#include <AvailabilityMacros.h>
6 #include <math.h>
7 #include <CoreFoundation/CoreFoundation.h>
8 //#include <CoreFoundation/CFMachPort.h>
9 #include <IOBluetooth/IOBluetoothUserLib.h>
10
11 typedef unsigned char WiiIRModeType;
12 enum {
13 kWiiIRModeBasic = 0x01,
14 kWiiIRModeExtended = 0x03,
15 kWiiIRModeFull = 0x05
16 };
17
18 typedef struct {
19 int x, y, s;
20 } IRData;
21
22 typedef struct {
23 unsigned char accX_zero, accY_zero, accZ_zero, accX_1g, accY_1g, accZ_1g;
24 } WiiAccCalibData;
25
26 typedef struct {
27 unsigned char x_min, x_max, x_center, y_min, y_max, y_center;
28 } WiiJoyStickCalibData;
29
30 typedef UInt16 WiiButtonType;
31 enum {
32 WiiRemoteAButton,
33 WiiRemoteBButton,
34 WiiRemoteOneButton,
35 WiiRemoteTwoButton,
36 WiiRemoteMinusButton,
37 WiiRemoteHomeButton,
38 WiiRemotePlusButton,
39 WiiRemoteUpButton,
40 WiiRemoteDownButton,
41 WiiRemoteLeftButton,
42 WiiRemoteRightButton,
43
44 WiiNunchukZButton,
45 WiiNunchukCButton,
46
47 WiiClassicControllerXButton,
48 WiiClassicControllerYButton,
49 WiiClassicControllerAButton,
50 WiiClassicControllerBButton,
51 WiiClassicControllerLButton,
52 WiiClassicControllerRButton,
53 WiiClassicControllerZLButton,
54 WiiClassicControllerZRButton,
55 WiiClassicControllerUpButton,
56 WiiClassicControllerDownButton,
57 WiiClassicControllerLeftButton,
58 WiiClassicControllerRightButton,
59 WiiClassicControllerMinusButton,
60 WiiClassicControllerHomeButton,
61 WiiClassicControllerPlusButton
62 };
63
64
65 typedef UInt16 WiiExpansionPortType;
66 enum{
67 WiiExpNotAttached,
68 WiiNunchuk,
69 WiiClassicController
70 };
71
72 typedef UInt16 WiiAccelerationSensorType;
73 enum{
74 WiiRemoteAccelerationSensor,
75 WiiNunchukAccelerationSensor
76 };
77
78
79 typedef UInt16 WiiJoyStickType;
80 enum{
81 WiiNunchukJoyStick,
82 WiiClassicControllerLeftJoyStick,
83 WiiClassicControllerRightJoyStick
84 };
85
86
87 typedef struct _WiiRemoteRec
88 {
89 IOBluetoothDeviceInquiryRef inquiry;
90 IOBluetoothDeviceRef device;
91 IOBluetoothL2CAPChannelRef ichan;
92 IOBluetoothL2CAPChannelRef cchan;
93
94 CFStringRef address;
95
96 unsigned char accX;
97 unsigned char accY;
98 unsigned char accZ;
99 unsigned short buttonData;
100
101 float lowZ;
102 float lowX;
103 int orientation;
104 int leftPoint; // is point 0 or 1 on the left. -1 when not tracking.
105
106 float posX;
107 float posY;
108 float angle;
109 Boolean tracking;
110
111 WiiExpansionPortType expType;
112 WiiAccCalibData wiiCalibData, nunchukCalibData;
113 WiiJoyStickCalibData nunchukJoyStickCalibData;
114 WiiIRModeType wiiIRMode;
115 IRData irData[4];
116 double batteryLevel;
117
118 Boolean readingRegister;
119 Boolean isMotionSensorEnabled;
120 Boolean isIRSensorEnabled;
121 Boolean isVibrationEnabled;
122 Boolean isExpansionPortEnabled;
123 Boolean initExpPort;
124 Boolean isLED1Illuminated;
125 Boolean isLED2Illuminated;
126 Boolean isLED3Illuminated;
127 Boolean isLED4Illuminated;
128
129 Boolean isExpansionPortAttached;
130
131 IOBluetoothUserNotificationRef disconnectNotification;
132
133 //nunchuk
134 unsigned char nStickX;
135 unsigned char nStickY;
136 unsigned char nAccX;
137 unsigned char nAccY;
138 unsigned char nAccZ;
139 unsigned char nButtonData;
140
141 float nLowZ;
142 float nLowX;
143 int nOrientation;
144
145 //classic controller
146 unsigned short cButtonData;
147 unsigned char cStickX1;
148 unsigned char cStickY1;
149 unsigned char cStickX2;
150 unsigned char cStickY2;
151 unsigned char cAnalogL;
152 unsigned char cAnalogR;
153
154 } WiiRemoteRec, *WiiRemoteRef;
155
156 void wiiremote_init(WiiRemoteRef wiiremote);
157 Boolean wiiremote_isconnected(WiiRemoteRef wiiremote);
158 Boolean wiiremote_search(WiiRemoteRef wiiremote, char *address);
159 Boolean wiiremote_stopsearch(WiiRemoteRef wiiremote);
160 Boolean wiiremote_connect(WiiRemoteRef wiiremote);
161 Boolean wiiremote_disconnect(WiiRemoteRef wiiremote);
162 void wiiremote_getaddress(WiiRemoteRef wiiremote, char *address);
163 Boolean wiiremote_motionsensor(WiiRemoteRef wiiremote, Boolean enabled);
164 Boolean wiiremote_irsensor(WiiRemoteRef wiiremote, Boolean enabled);
165 Boolean wiiremote_vibration(WiiRemoteRef wiiremote, Boolean enabled);
166 Boolean wiiremote_led(WiiRemoteRef wiiremote, Boolean enabled1, Boolean enabled2, Boolean enabled3, Boolean enabled4);
167 Boolean wiiremote_expansion(WiiRemoteRef wiiremote, Boolean enabled);
168 Boolean wiiremote_getstatus(WiiRemoteRef wiiremote);
169
20442044 if (!validItem) break;
20452045 if (skipItem) continue;
20462046
2047 if (sc_DirectoryExists(diritem)) {
2048 success = passOne_ProcessDir(diritem, level + 1);
2049 } else {
2050 success = passOne_ProcessOneFile(diritem, level + 1);
2051 }
2047 if (sc_DirectoryExists(diritem)) {
2048 success = passOne_ProcessDir(diritem, level + 1);
2049 } else {
2050 success = passOne_ProcessOneFile(diritem, level + 1);
2051 }
20522052
20532053 if (!success) break;
20542054 }
21242124 }
21252125
21262126 // sekhar's replacement
2127 bool passOne_ProcessOneFile(char *filenamearg, int level)
2127 bool passOne_ProcessOneFile(const char * filenamearg, int level)
21282128 {
21292129 bool success = true;
21302130
21312131 bool isAlias = false;
21322132 // on non-Darwin, sc_ResolveIfAlias always returns original path
21332133 char filename[MAXPATHLEN];
2134 sc_ResolveIfAlias(filenamearg, filename, isAlias, MAXPATHLEN);
2134 int status = sc_ResolveIfAlias(filenamearg, filename, isAlias, MAXPATHLEN);
2135
2136 if (status<0) {
2137 printf("WARNING: skipping invalid symbolic link: %s\n", filenamearg);
2138 return success;
2139 }
21352140
21362141 #ifdef ENABLE_LIBRARY_CONFIGURATOR
21372142 if (gLibraryConfig && gLibraryConfig->pathIsExcluded(filename)) {
21402145 }
21412146 #endif
21422147
2143 PyrSymbol *fileSym;
21442148 if (isValidSourceFileName(filename)) {
21452149 gNumCompiledFiles++;
2146 fileSym = getsym(filename);
2150 PyrSymbol * fileSym = getsym(filename);
21472151 fileSym->u.source = NULL;
21482152 if (startLexer(fileSym, -1, -1, -1)) {
21492153 while (parseOneClass(fileSym)) { };
21532157 success = false;
21542158 }
21552159 } else {
2156 #ifndef SC_WIN32
2157 // check if this is a symlink
2158 char realpathname[MAXPATHLEN];
2159 realpath(filename, realpathname);
2160 if (strncmp(filename, realpathname, strlen(filename))) {
2161 if (sc_DirectoryExists(realpathname))
2162 success = passOne_ProcessDir(realpathname, level);
2163 }
2164 #else
2165 // under window, we're sure it's a file so wer don't do anything...
2166 // maybe processing .lnk files could be interesting...
2167 // $$$todo fixme add .lnk file parsing...
2168 // (see http://www.thecodeproject.com/managedcpp/mcppshortcuts.asp)
2169 #endif
2170 }
2160 if (sc_DirectoryExists(filename))
2161 success = passOne_ProcessDir(filename, level);
2162 }
21712163 return success;
21722164 }
21732165
12721272 sizeof(PyrSlot) * classClassNumInstVars);
12731273 memcpy(slotRawSymbolArray(&metaclassobj->instVarNames)->symbols,
12741274 slotRawSymbolArray(&metaSuperClass->instVarNames)->symbols,
1275 sizeof(PyrSlot) * classClassNumInstVars);
1275 sizeof(PyrSymbol*) * classClassNumInstVars);
12761276 slotRawObject(&metaclassobj->iprototype)->size = classClassNumInstVars;
12771277 slotRawObject(&metaclassobj->instVarNames)->size = classClassNumInstVars;
12781278 //dumpObject((PyrObject*)metaclassobj);
12891289 sizeof(PyrSlot) * superInstVars);
12901290 memcpy(slotRawSymbolArray(&classobj->instVarNames)->symbols,
12911291 slotRawSymbolArray(&superClass->instVarNames)->symbols,
1292 sizeof(PyrSlot) * superInstVars);
1292 sizeof(PyrSymbol*) * superInstVars);
12931293 slotRawObject(&classobj->iprototype)->size = superInstVars;
12941294 slotRawObject(&classobj->instVarNames)->size = superInstVars;
12951295 }
14861486
14871487 addIntrinsicVar(class_thread, "environment", &o_nil);
14881488 addIntrinsicVar(class_thread, "exceptionHandler", &o_nil);
1489
1489
14901490 addIntrinsicVar(class_thread, "executingPath", &o_nil);
14911491 addIntrinsicVar(class_thread, "oldExecutingPath", &o_nil);
14921492
20112011 {
20122012 float xa = ZIN0(0);
20132013
2014 nova::over_vec_simd(OUT(0), IN(1), xa, inNumSamples);
2014 nova::over_vec_simd(OUT(0), xa, IN(1), inNumSamples);
20152015 unit->mPrevA = xa;
20162016 }
20172017
166166 {
167167 if (full_rate)
168168 return GRAIN_IN_AT(unit, index, offset);
169
170 if (INRATE(index) == calc_DemandRate)
171 return DEMANDINPUT_A(index, offset + 1);
169172 else
170173 return IN0(index);
171174 }
11761179
11771180 // end add //
11781181
1179 int nsmps = sc_min(grain->counter, inNumSamples);
1182 int nsmps = sc_min(grain->counter, inNumSamples - position);
11801183
11811184 if (grain->winType < 0.)
11821185 GRAIN_BUF_PLAY_GRAIN(INTERNAL);
5757
5858 struct LagControl : public IOUnit
5959 {
60 float m_b1[kMaxLags];
61 float m_y1[kMaxLags];
60 float * m_b1;
61 float * m_y1;
6262 };
6363
6464
351351
352352 void LagControl_Ctor(LagControl* unit)
353353 {
354 int numChannels = unit->mNumInputs;
355 float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;
356
357 char * chunk = (char*)RTAlloc(unit->mWorld, numChannels * 2 * sizeof(float));
358 unit->m_y1 = (float*)chunk;
359 unit->m_b1 = unit->m_y1 + numChannels;
360
361 for (int i=0; i<numChannels; ++i, mapin++) {
362 unit->m_y1[i] = **mapin;
363 float lag = ZIN0(i);
364 unit->m_b1[i] = lag == 0.f ? 0.f : (float)exp(log001 / (lag * unit->mRate->mSampleRate));
365 }
366
354367 if (unit->mNumOutputs == 1) {
355368 SETCALC(LagControl_next_1);
356369 LagControl_next_1(unit, 1);
358371 SETCALC(LagControl_next_k);
359372 LagControl_next_k(unit, 1);
360373 }
361 int numChannels = unit->mNumInputs;
362 float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;
363 for (int i=0; i<numChannels; ++i, mapin++) {
364 unit->m_y1[i] = **mapin;
365 float lag = ZIN0(i);
366 unit->m_b1[i] = lag == 0.f ? 0.f : (float)exp(log001 / (lag * unit->mRate->mSampleRate));
367 }
374 }
375
376 void LagControl_Dtor(LagControl* unit)
377 {
378 RTFree(unit->mWorld, unit->m_y1);
368379 }
369380
370381 //////////////////////////////////////////////////////////////////////////////////////////////////
19311942 DefineDtorUnit(OffsetOut);
19321943 DefineDtorUnit(LocalIn);
19331944 DefineSimpleUnit(XOut);
1934 DefineSimpleUnit(LagControl);
1945 DefineDtorUnit(LagControl);
19351946 DefineDtorUnit(AudioControl);
19361947 DefineUnit("Control", sizeof(Unit), (UnitCtorFunc)&Control_Ctor, 0, 0);
19371948 DefineUnit("TrigControl", sizeof(Unit), (UnitCtorFunc)&TrigControl_Ctor, 0, 0);
637637 float z = phase;
638638 ZXP(out) = 1.f - z*z;
639639 }
640 phase += ZXP(freq) * freqmul;
640 // Note: the following two lines were originally one, but seems to compile wrong on mac
641 float phaseadd = ZXP(freq) * freqmul;
642 phase += phaseadd;
641643 );
642644
643645 unit->mPhase = phase;
702704 z = phase;
703705 }
704706 ZXP(out) = z * z * (6.f - 4.f * z) - 1.f;
705 phase += ZXP(freq) * freqmul;
707 float phaseadd = ZXP(freq);
708 phase += phaseadd * freqmul;
706709 );
707710
708711 unit->mPhase = phase;
10751075 unit->m_prevtrig = 0.f;
10761076 unit->mLevel = 0.f;
10771077
1078 ZOUT0(0) = 0.f;
1078 ZOUT0(0) = ZIN0(1) > 0.f ? ZIN0(0) : 0.f;
10791079 }
10801080
10811081
165165 { \
166166 if (inNumSamples) { \
167167 float x = DEMANDINPUT_A(0, inNumSamples); \
168 OUT0(0) = sc_isnan(x) ? NAN : sc_cpsoct(x); \
168 OUT0(0) = sc_isnan(x) ? NAN : function(x); \
169169 } else { \
170170 RESETINPUT(0); \
171171 } \
11 dnl file: configure.in
22 dnl contents: autoconf template
33 dnl author: stefan kersten <steve@k-hornz.de>
4 dnl CVS: $Id: configure.in 2231 2003-11-28 11:06:57Z kersten $
4 dnl CVS: $Id$
55 dnl ===================================================================
66
77 # initialize autoconf
6767 void sc_SetDenormalFlags()
6868 {
6969 // all Macs have SSE
70 _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
7071 _mm_setcsr(_mm_getcsr() | 0x40);
7172 }
7273
252252 bool result;
253253 inWorld->mDriverLock->Lock();
254254 SC_AudioDriver *driver = AudioDriver(inWorld);
255 if (!driver) return false;
255 if (!driver) {
256 inWorld->mDriverLock->Unlock();
257 return false;
258 }
256259 inPacket->mIsBundle = gIsBundle.checkIsBundle((int32*)inPacket->mData);
257260 FifoMsg fifoMsg;
258261 fifoMsg.Set(inWorld, Perform_ToEngine_Msg, FreeOSCPacket, (void*)inPacket);
12931293 SCErr meth_clearSched(World *inWorld, int inSize, char *inData, ReplyAddress *inReply);
12941294 SCErr meth_clearSched(World *inWorld, int inSize, char *inData, ReplyAddress *inReply)
12951295 {
1296 inWorld->hw->mAudioDriver->ClearSched();
1296 if(inWorld->mRealTime){
1297 inWorld->hw->mAudioDriver->ClearSched();
1298 }
12971299 return kSCErr_None;
12981300 }
12991301
00 Changes are listed below, grouped under each point release of SuperCollider.
1
2 SuperCollider v3.4.2, released 2011-03
3 ======================================
4
5 Bugfixes:
6 ---------
7
8 * 2010-06-05 fix Latch first sample output bug: if trigger > 0 initially, latch should not output 0 - jh
9 * 2010-09-04 fix firstArg behavior in BinaryOpUGen by a list-approved hack - jh
10 * 2010-10-01 fix SConstruct so that libscsynth and libsclang get SONAME entries - ds
11 * 2010-11-13 grainBuf: audio-rate trigger fix - tb
12 * 2010-11-15 generate libsclang and libscsynth with .so.1 extension (and soname) on linux - ds
13 * 2010-11-15 scons create symlinks from libX.so to libX.so.1 on linux, and install them - ds
14 * 2010-11-16 added .htm files to SConstruct as approved help file extension - mb
15 * 2010-11-28 compile fix for curl support - tb
16 * 2010-11-28 prevent asBus from breaking when called with no numChannels - jh
17 * 2010-12-03 grain ugens: demand ugen input fix - tb
18 * 2010-12-05 SystemClock and TempoClock sched and schedAbs with inf time doesn't schedule the task in the first place. backported from master - tb
19 * 2010-12-08 prString_FindRegexp fix: match char array was too short to hold null termination - jl
20 * 2010-12-11 fix classbrowser colors bugs. backported from master - tb
21 * 2010-12-12 fixes the bug where installed quark help files would not be detected - tb/ar
22 * 2010-12-13 mark inherited methods in class browser by background colour. backported from master - tb
23 * 2010-12-30 Pipe does not remove closed pipes from openFiles - jh
24 * 2010-12-30 fix String:rotate - pb
25 * 2011-01-02 unit generators: LagControl - fix initialization order - jh
26 * 2011-01-02 unit generators: LagControl - dynamically allocate buffer for filter states - tb
27 * 2011-01-07 fixed iOS compilation and backported changes from master branch - ab
28 * 2011-01-06 array primitives: fix allTuples and unlace - pb
29 * 2011-01-07 sclang: makeIntrinsicClass - correct bounds for memcpy - tb
30 * 2011-01-08 sclang: prString_FindRegexp - fill array after allocating objects - tb
31 * 2011-01-14 sclang: prString_FindRegexp ensure correct size of results array during gc calls - tb
32 * 2011-02-27 sclang: ensure minimum stack size - tb
33 * 2011-03-09 SCVim: avoid generating scvim help cache if not currently in scvim - ds
34 * 2011-03-11 fix the Event type 'note' (fixes rendering patterns to audio files) - rk
35
36
37
38 SuperCollider v3.4.1, released 2010-11
39 ======================================
40
41 * 2010-07-12 remove accidental debug messages from SCView (on mac, posted a lot of info to Console, could affect performance) - ds
42 * 2010-09-11 bug in audio rate mapping fixed, when new source object was inserted in a mapped node proxy - jr
43 * 2010-07-11 Collections should behave as reasonably as possible when empty - some fixes to better this - jr
44 * 2010-07-11 SynthDef:add now sends to all running servers if no libname is given. SynthDescs are still added to the global SynthDescLib. If you want to handle multiple SynthDesc libs, you have to add the servers to each of them explicitly - jr
45 * 2010-07-12 PanAz: added support for audio-rate pos arg - lfsaw
46 * 2010-07-18 improved the sclang syntax highlighting parses - Patrick Borgeat
47 * 2010-07-30 Dreset UGen allows to reset the child UGens on its input - jr
48 * 2010-08-05 storeOn / asCompileString now simplifies its output. Default arguments that are given in the *new method anyhow are omitted - jr
49 * 2010-08-06 Dictionary merge and blend methods - jr
50 * 2010-08-09 method overwrite messages not posted by default, rather a message inviting people to run Main:overwriteMsg for the info - ds
51 * 2010-08-13 MethodOverride class to encapsule information on overridden messages, inviting people to run MethodOverride.printAll - jr
52 * 2010-08-13 add size arg to Signal:zeroPad - jr and jh
53 * 2010-08-18 Pevent now uses default event if no event is passed in - jr
54 * 2010-08-18 added a shortcut to the rather tedious .asCompileString method. In analogy to object.postcs, object.cs returns the compile string - jr
55 * 2010-08-20 audio driver for scsynth running on Android (through JNI) - ds
56 * 2010-08-24 un-deprecate scsynth's ability to use internal "green" FFT lib, for embedded devices etc - ds
57 * 2010-08-28 no 'record' button for remote server GUIs, since path not generally known - ds
58 * 2010-09-02 token threading for sclang interpreter - tb
59 * 2010-09-07 when looking for a code file (openCodeFile) or cmd-J, it is now enough to select a full line, instead of having to select both words around the colon - jr
60 * 2010-09-07 added methods for better navigation in the class tree (findOverriddenMethod) - jr
61 * 2010-09-10 add method: Complex:abs to fit common usage - jr
62 * 2010-09-12 added Dwrand UGen - jr
63 * 2010-09-15 SystemClock and TempoClock sched and schedAbs with inf time doesn't schedule the task in the first place - jr
64 * 2010-10-07 change the mac HID error-handler code to output errors to sc post window rather than to mac log; removes a pascal-string issue - ds
65 * 2010-10-19 Ndef now releses its bus when server was quit or just booted - jr
66 * 2010-10-20 retain the path to the file in which an error has occurred and post it - jr
67
68
69 Bugfixes:
70 ---------
71 * 2010-07-10 protecting the server against malformatted SynthDef names - jr
72 * 2010-06-28 syntaxColorize fix for double-backslashes, thanks Patrick Borgeat for the patch - ds
73 * 2010-07-24 catch crash in the case that one tries to define a unique method using a return value directly - jr
74 * 2010-09-07 UGen:clip, :wrap, :fold now apply correctly to scalar-rate signals; also methodSelectorForRate tweak for which class is asked - ds
75 * 2010-09-09 fix a bug for trigger signals in Demand.kr that hold longer than one control period - jr
76 * 2010-09-12 fix bug: 2994009. LFPar and LFCub audio rate modulation frequency argument work now - jr
77 * 2010-09-19 fix to JITGui, when numItems is not supplied - jr
78 * 2010-10-10 remove more crufty NSLog debug messages - ds
79 * 2010-10-13 fix SCUserView:receiveDrag to receive mouse co-ordinates; thanks Daniel van den Eijkel - ds
80 * 2010-10-19 debian-style scvim-check-if-plugin-is-active, brought upstream - ds
81 * 2010-10-19 bug in audio rate mapping fixed, when new source object was inserted in a mapped node proxy - jr
82 * 2010-10-19 partial fix for bugs item #2994009 - seems to fix LFPar but not LFCub. More work needed - ds
83 * 2010-10-19 DC: fix multichannel expansion - tb
84 * 2010-10-19 fix to demand rate unary op ugens, thanks james harkins - tb
85 * 2010-10-19 Ugens: LinLin/LinExp fixes - tb
86 * 2010-10-19 only /clearSched if RT - to fix tracker item #3033454 - tb
87 * 2010-10-19 UGens: binary operators - fix scalar/signal division - tb
88 * 2010-10-19 fix bug 2988525: SynthDef:writeDefFile appends path correctly - tb
89 * 2010-10-19 ProcessOSCPacket: fix possible deadlock - tb
90 * 2010-10-19 fix network address handling - albert graef
91 * 2010-11-05 fix memory issues in regular expressions: correct memory management in prString_FindRegexp - tb
92 * 2010-11-07 sclang: correct symlink handling - tb, ar
193
294 SuperCollider v3.4, released 2010-07
395 ====================================
29121 * 2010-02-18 scvim: now compatible with gnu screen, opens post window using screen, making it compatible with a pure-CLI environment - ds
30122 * 2010-02-xx add the Deployment32-64 build style for building on OS X (10.5 and greater) - jp
31123 * 2010-03-10 SynthDef:memStore deprecated in favour of the more coherent and typeable SynthDef:add - jr
32 * 2010-04-11 Moved some more experimental JITLib classes to ÒJITLib extensions" Quark - jr
124 * 2010-04-11 Moved some more experimental JITLib classes to "JITLib extensions" Quark - jr
33125
34126
35127 Bugfixes:
68160 * 2010-03-11 SequenceableCollection:reduce no longer returns nil if the collection has only 1 element - ds
69161 * 2010-03-28 fix memory leak of empty command line, for interactive sclang mode - tb
70162 * 2010-03-29 main menu for Mac lang editor app: correction to key for evaluate selection, used to be return, now return+shift - nc
163 * 2010-04-19 fix missing font issue in Plotter -jr
71164
72165 Other additions/improvements:
73166 -----------------------------
1414 // }
1515 operator_ { arg op;
1616 operator = op;
17 specialIndex = operator.specialIndex;
18 // 'firstArg' check is necessary for audio-rate Demand units
19 if(specialIndex < 0 and: { operator != 'firstArg' }) {
17 // 'firstArg' exists in the server
18 // but the 'specialIndex' primitive doesn't report the right value
19 // admittedly this is a hack, but the hack was approved on sc-dev
20 if(operator == 'firstArg') {
21 specialIndex = 46
22 } {
23 specialIndex = operator.specialIndex;
24 };
25 if(specialIndex < 0) {
2026 Error("Operator '%' applied to a UGen is not supported in scsynth".format(operator)).throw
2127 }
2228 }
1616 }
1717
1818 LinExp : UGen {
19 checkInputs { ^this.checkSameRateAsFirstInput }
1920 *ar { arg in=0.0, srclo = 0.0, srchi = 1.0, dstlo = 1.0, dsthi = 2.0;
2021 ^this.multiNew('audio', in, srclo, srchi, dstlo, dsthi)
2122 }
2526 }
2627
2728 LinLin : UGen {
29 checkInputs { ^this.checkSameRateAsFirstInput }
2830 *ar { arg in=0.0, srclo = 0.0, srchi = 1.0, dstlo = 1.0, dsthi = 2.0;
2931 ^this.multiNew('audio', in, srclo, srchi, dstlo, dsthi)
3032 }
8789
8890 DC : MultiOutUGen {
8991 *ar { arg in=0.0;
90 ^this.multiNewList(['audio'] ++ in)
92 ^this.multiNew('audio', in)
9193 }
9294 *kr { arg in=0.0;
93 ^this.multiNewList(['control'] ++ in)
95 ^this.multiNew('control', in)
9496 }
9597 init { arg ... argInputs;
9698 inputs = argInputs;
510510 };
511511
512512 // schedule when the bundles are sent
513
514513 if (strum == 0) {
515 schedBundleArrayOnClock(
516 offset, thisThread.clock, bndl, lag, server, ~latency);
514 ~schedBundleArray.(lag, offset, server, bndl, ~latency);
517515 if (sendGate) {
518 schedBundleArrayOnClock(
519 sustain + offset, thisThread.clock,
520 [\n_set, ids, \gate, 0].flop,
521 lag, server, ~latency
516 ~schedBundleArray.(
517 lag,
518 sustain + offset,
519 server,
520 [\n_set, ids, \gate, 0].flop,
521 ~latency
522522 );
523523 }
524524 } {
525
526525 if (strum < 0) { bndl = bndl.reverse };
527526 strumOffset = offset + Array.series(bndl.size, 0, strum.abs);
528 schedBundleArrayOnClock(
529 strumOffset, thisThread.clock, bndl,
530 lag, server, ~latency
527 ~schedBundleArray.(
528 lag, strumOffset, server, bndl, ~latency
531529 );
532530 if (sendGate) {
533531 if (~strumEndsTogether) {
535533 } {
536534 strumOffset = sustain + strumOffset
537535 };
538 schedBundleArrayOnClock(
539 strumOffset, thisThread.clock,
540 [\n_set, ids, \gate, 0].flop,
541 lag, server, ~latency
536 ~schedBundleArray.(
537 lag, strumOffset, server,
538 [\n_set, ids, \gate, 0].flop,
539 ~latency
542540 );
543541 }
544542 }
277277 ^this.as(Array).scramble.as(String)
278278 }
279279
280 rotate { |n|
280 rotate { arg n = 1;
281281 ^this.as(Array).rotate(n).as(String)
282282 }
283283
00
11 + Server {
2 asBus { arg rate,numChannels;
2 asBus { arg rate,numChannels=1;
33 ^Bus.alloc(rate,this,numChannels)
44 }
55 }
1515 }
1616
1717 + Nil {
18 asBus { arg rate,numChannels,server;
18 asBus { arg rate,numChannels=1,server;
1919 ^if(rate == \audio,{
2020 Bus(\audio,0,numChannels,server); // out yer speakers
2121 },{
109109 }
110110
111111 archiveAsCompileString { ^true }
112
113 superclassesDo {}
112114 }
113115
584584 var file;
585585 dir = dir ? SynthDef.synthDefDir;
586586 if (name.isNil) { error("missing SynthDef file name") } {
587 name = dir ++ name ++ ".scsyndef";
587 name = dir +/+ name ++ ".scsyndef";
588588 if(overwrite or: { pathMatch(name).isEmpty })
589589 {
590590 file = File(name, "w");
1616 var <>exceptionHandler;
1717 var <executingPath, <oldExecutingPath;
1818
19 *new { arg func, stackSize=64;
19 *new { arg func, stackSize=512;
2020 ^super.new.init(func, stackSize)
2121 }
22 init { arg argFunc, argStackSize=64;
22 init { arg argFunc, argStackSize=512;
2323 _Thread_Init
2424 ^this.primitiveFailed
2525 }
120120 });
121121 }
122122
123 close { // close the file
123 close {
124 this.prClose;
125 openFiles.remove(this);
126 }
127
128 prClose { // close the file
124129 // the GC will not call this for you
125130 _PipeClose
126131 ^this.primitiveFailed;
408408 },
409409 methodTitle: { |v| v.string_("methods") },
410410 methodView: { |v|
411 ~methodView.items_(~classMethodNames ++ ~methodNames)
411 var colorFunc = { |class, name|
412 if(class.findOverriddenMethod(name.asSymbol).isNil) {
413 Color.clear
414 } {
415 Color.grey(0.8)
416 }
417 };
418 var classMethodColors = ~classMethodNames.collect { |name|
419 colorFunc.value(~currentClass.class, name)
420 };
421 var methodColors = ~methodNames.collect { |name|
422 colorFunc.value(~currentClass, name)
423 };
424 var methodNames = ~classMethodNames ++ ~methodNames;
425 var colors = classMethodColors ++ methodColors;
426
427 ~methodView.items_(methodNames)
412428 .value_(~methodViewIndex ? 0)
413429 .action_(~displayCurrentMethodArgsAction)
414 .mouseDownAction_(~listViewDoubleClickAction);
430 .mouseDownAction_(~listViewDoubleClickAction)
431 .tryPerform(\colors_, colors)
415432 },
416433 argView: { |v|
417434 if (~currentMethod.isNil or: { ~currentMethod.argNames.isNil }) {
+0
-273
common/build/SCClassLibrary/Common/GUI/iphone/Base/GUIScreen.sc less more
0 SCWindow {
1 classvar <>allWindows, <currentFullScreen, <>initAction;
2
3 var dataptr, <name, <>onClose, <view, <userCanClose=true;
4 var <alwaysOnTop=false;
5 var <>drawHook;
6 var <acceptsMouseOver=false;
7 var <isClosed = false;
8 var <acceptsClickThrough = true;
9 var <> toFrontAction, <> endFrontAction;
10 var <editable=false, <>constructionView;
11 var <currentSheet; // current modal sheet attached to this window, if it exists
12
13 *initClass {
14 UI.registerForShutdown({ this.closeAll });
15 }
16
17 *new { arg name = "panel", bounds, resizable = true, border = true, server, scroll = false;
18 ^super.new.initSCWindow(name, bounds, resizable, border, scroll)
19 }
20 // appmodal is a private flag used to disable the close button
21 initSCWindow { arg argName, argBounds, resizable, border, scroll, appmodal = false;
22 name = argName.asString;
23 argBounds = argBounds ?? {Rect(128, 64, 400, 400)};
24 allWindows = allWindows.add(this);
25 scroll.if({
26 view = SCScrollTopView(nil, argBounds.moveTo(0,0));
27 },{
28 view = SCTopView(nil, argBounds.moveTo(0,0));
29 });
30 this.prInit(name, argBounds, resizable, border, scroll, view, appmodal);
31 initAction.value(this);
32 }
33
34 asView { ^view }
35 add { arg aView; view.add(aView) }
36
37 addFlowLayout { |margin, gap|
38 view.relativeOrigin.if
39 {view.decorator_( FlowLayout( view.bounds.moveTo(0,0), margin, gap ) )}
40 {view.decorator_( FlowLayout( view.bounds, margin, gap ) )};
41 ^this.view.decorator;
42 }
43
44 *closeAll {
45 var list;
46 list = allWindows.copy;
47 allWindows = Array.new(8);
48 list.do({ arg window; window.close; });
49 }
50
51 close {
52 if (isClosed) { ^this };
53 this.prClose;
54 }
55 closed {
56 isClosed = true;
57 onClose.value; // call user function
58 dataptr = nil;
59 view.prClose;
60 allWindows.remove(this);
61 }
62
63 addToOnClose { | function | onClose = onClose.addFunc(function) }
64
65 removeFromOnClose { | function | onClose = onClose.removeFunc(function) }
66
67 fullScreen {
68 currentFullScreen.notNil.if({currentFullScreen.endFullScreen});
69 this.prFullScreen;
70 currentFullScreen = this;
71 }
72 endFullScreen {
73 this.prEndFullScreen;
74 currentFullScreen = nil;
75 }
76
77 prFullScreen {
78 _SCWindow_BeginFullScreen
79 ^this.primitiveFailed
80 }
81 prEndFullScreen {
82 _SCWindow_EndFullScreen
83 ^this.primitiveFailed
84 }
85 userCanClose_ { arg boo;
86 _SCWindow_SetShouldClose
87 ^this.primitiveFailed
88 }
89 acceptsMouseOver_{arg bool;
90 acceptsMouseOver = bool;
91 this.prSetAcceptMouseOver(bool);
92 }
93 front {
94 _SCWindow_ToFront
95 ^this.primitiveFailed
96 }
97
98 alwaysOnTop_{|bool=true|
99 alwaysOnTop = bool;
100 this.prSetAlwaysOnTop(bool);
101 }
102
103 prSetAlwaysOnTop{|boolean=true|
104 _SCWindow_AlwaysOnTop
105 }
106
107 acceptsClickThrough_{|boolean=true|
108 acceptsClickThrough = boolean;
109 this.prSetAcceptsClickThrough(boolean);
110 }
111
112 prSetAcceptsClickThrough{|boolean=true|
113 _SCWindow_AcceptsClickThrough
114 }
115
116 refresh {
117 _SCWindow_Refresh
118 ^this.primitiveFailed
119 }
120 minimize {
121 _SCWindow_Minimize
122 ^this.primitiveFailed
123 }
124 alpha_ { arg alpha;
125 _SCWindow_SetAlpha
126 ^this.primitiveFailed
127 }
128
129 name_ { arg argName;
130 name = argName;
131 this.prSetName(argName);
132 }
133 // bounds are relative to the bottom left corner origin
134 bounds_ { arg argBounds;
135 this.prSetBounds(argBounds);
136 }
137 // set bounds relative to top left corner
138 setTopLeftBounds { |rect,menuSpacer=45|
139 rect = rect.copy;
140 // 45 is the height of the mac os menu
141 // if you are in full screen mode you would want to pass in 0
142 rect.top = SCWindow.screenBounds.height - rect.height - rect.top - menuSpacer;
143 this.bounds = rect
144 }
145 setInnerExtent { arg w,h; // resize window keeping top left corner fixed
146 var b;
147 b = this.bounds;
148 w = w ? b.width;
149 h = h ? b.height;
150 this.bounds = Rect(b.left,b.top + (b.height - h), w,h);
151 }
152 bounds {
153 ^this.prGetBounds(Rect.new);
154 }
155 *screenBounds {
156 ^this.prGetScreenBounds(Rect.new);
157 }
158 play { arg function;
159 AppClock.play({
160 if (dataptr.notNil, {
161 function.value;
162 });
163 });
164
165 }
166
167 findByID { arg id;
168 ^view.findByID(id)
169 }
170
171 // PRIVATE
172 // primitives
173 prInit { arg argName, argBounds, resizable, border, scroll, view, appmodal = false;
174 _SCWindow_New
175 ^this.primitiveFailed
176 }
177 prClose {
178 _SCWindow_Close
179 ^this.primitiveFailed
180 }
181 prSetName { arg argName;
182 _SCWindow_SetName
183 ^this.primitiveFailed
184 }
185 prGetBounds { arg argBounds;
186 _SCWindow_GetBounds
187 ^this.primitiveFailed
188 }
189 prSetBounds { arg argBounds;
190 _SCWindow_SetBounds
191 ^this.primitiveFailed
192 }
193 prSetAcceptMouseOver{arg bool;
194 _SCWindow_SetAcceptMouseOver
195 ^this.primitiveFailed
196 }
197 *prGetScreenBounds { arg argBounds;
198 _SCWindow_GetScreenBounds
199 ^this.primitiveFailed
200 }
201 callDrawHook {
202 drawHook.value(this);
203 }
204
205 didBecomeKey {
206 toFrontAction.value(this);
207 }
208
209 didResignKey {
210 endFrontAction.value(this);
211 }
212
213 toggleEditMode{
214 var panel;
215 editable = editable.not;
216 if(editable){
217 SCIBToolboxWindow.front.addWindow(this);
218 this.refresh;
219 }{
220 SCIBToolboxWindow.front.removeWindow(this);
221 }
222 }
223 setCurrentSheet {|sheet| currentSheet = sheet;}
224 /*
225 *viewPalette {|win|
226 var w, v, f, c;
227 w = SCWindow("View Palette", Rect(532, 64, 300, 320), scroll: true).front;
228 w.view.decorator = f = FlowLayout(w.view.bounds);
229 SCButton(w, 300@20).states_([ ["-> CODE"]])
230 .canFocus_(false).action_{
231 Document("window construction code", win.asConstructionCompileString);
232 };
233 w.view.decorator.nextLine;
234 // c = [SCSlider, SCRangeSlider, SC2DSlider, SCPopUpMenu, SCButton,
235 // SCNumberBox, SCMultiSliderView,
236 // SCStaticText, SCDragSource, SCDragSink, SCDragBoth,
237 // ];
238 c = SCView.allSubclasses.reject{|it|
239 (it.superclasses.indexOf(SCContainerView).notNil
240 or: (it.name === 'SCContainerView')
241 or: (it.name ==='SCStaticTextBase')
242 or: (it.name === 'SCSliderBase')
243 or: (it.name === 'SCControlView'))
244 };
245
246 c.do({ arg item;
247 var n;
248 n = SCDragSource(w, Rect(0, 0, 140, 24));
249 n.object = item;
250
251 try{
252 item.paletteExample(w, Rect(0,0,140,24));
253 }{
254 "no paletteExample found".warn;
255 };
256 w.view.decorator.nextLine;
257
258 });
259 win.onClose_{
260 Document("window construction code", win.asConstructionCompileString);
261 w.close
262 };
263 ^w
264 }
265 */
266
267 storeArgs{^[name, this.bounds]}
268 storeModifiersOn{|stream|
269 stream << ".front;";
270 }
271 }
272
+0
-40
common/build/SCClassLibrary/Common/GUI/iphone/Base/SCFont.sc less more
0 SCFont {
1 classvar <>default;
2 var <>name, <>size;
3
4 *new { arg name, size;
5 ^super.newCopyArgs(name, size);
6 }
7 setDefault { default = this }
8
9 *availableFonts {
10 // returns an Array of font names.
11 _Font_AvailableFonts
12 ^this.primitiveFailed
13 }
14 *antiAliasing_ { arg flag = false;
15 _Font_SetAntiAliasing;
16 ^this.primitiveFailed
17 }
18 *smoothing_ { arg flag = false;
19 _Font_SetSmoothing;
20 ^this.primitiveFailed
21 }
22 storeArgs { ^[name,size] }
23
24 boldVariant {
25 ^if( name.endsWith( "-Bold" ), this, { this.class.new( name ++ "-Bold", size )});
26 }
27
28 *defaultSansFace {
29 ^"Helvetica";
30 }
31
32 *defaultSerifFace {
33 ^"Times";
34 }
35
36 *defaultMonoFace {
37 ^"Monaco";
38 }
39 }
+0
-1006
common/build/SCClassLibrary/Common/GUI/iphone/Base/SCView.sc less more
0
1 SCView { // abstract class
2 classvar <>currentDrag, <>currentDragString;
3 classvar <>globalKeyDownAction, <>globalKeyUpAction;
4
5 var dataptr, <parent, <>action, <background;
6 var <>mouseDownAction, <>mouseUpAction, <>mouseOverAction, <>mouseMoveAction;
7 var <>keyDownAction, <>keyUpAction, <>keyTyped, <> keyModifiersChangedAction;
8 var <>beginDragAction,<>canReceiveDragHandler,<>receiveDragHandler;
9 var <>onClose;
10
11 *new { arg parent, bounds;
12 ^super.new.init(parent, bounds);
13 }
14 *viewClass { ^this }
15 *paletteExample { arg parent, bounds;
16 ^this.new(parent, bounds);
17 }
18
19 init { arg argParent, argBounds;
20 parent = argParent.asView; // actual view
21 background = Color.clear;
22 // call asView again because parent by this point might be a FlowView
23 this.prInit(parent.asView, argBounds.asRect,this.class.viewClass);
24 argParent.add(this);//maybe window or viewadapter
25 }
26
27 asView { ^this }
28
29 bounds {
30 ^this.getProperty(\bounds, Rect.new)
31 }
32 bounds_ { arg rect;
33 this.setProperty(\bounds, rect)
34 }
35
36 visible {
37 ^this.getProperty(\visible)
38 }
39 visible_ { arg bool;
40 this.setProperty(\visible, bool)
41 }
42
43 enabled {
44 ^this.getProperty(\enabled)
45 }
46 enabled_ { arg bool;
47 this.setProperty(\enabled, bool)
48 }
49
50 canFocus {
51 ^this.getProperty(\canFocus)
52 }
53 canFocus_ { arg bool;
54 this.setProperty(\canFocus, bool)
55 }
56 focus { arg flag=true;
57 _SCView_Focus
58 ^this.primitiveFailed
59 }
60 hasFocus{
61 _SCView_HasFocus
62 ^this.primitiveFailed
63 }
64
65 focusColor_{|color|
66 this.setProperty(\focusColor, color);
67 }
68
69 focusColor{
70 ^this.getProperty(\focusColor, Color.new);
71 }
72
73 id {
74 ^this.getProperty(\id)
75 }
76 id_ { arg id;
77 this.setProperty(\id, id)
78 }
79
80 dragLabel_ { arg string;
81 this.setProperty(\dragLabel, string)
82 }
83
84 refresh {
85 _SCView_Refresh
86 ^this.primitiveFailed
87 }
88 findByID { arg id;
89 _SCView_FindByID
90 ^this.primitiveFailed
91 }
92
93 isClosed { ^dataptr.isNil }
94 notClosed { ^dataptr.notNil }
95 remove {
96 if(dataptr.notNil,{
97 parent.prRemoveChild(this);
98 this.prRemove;
99 this.prClose;
100 },{
101 "SCView-remove : this view already removed.".debug(this);
102 });
103 }
104 /*
105 resize behaviour in an SCCompositeView:
106 1 2 3
107 4 5 6
108 7 8 9
109
110 1 - fixed to left, fixed to top
111 2 - horizontally elastic, fixed to top
112 3 - fixed to right, fixed to top
113
114 4 - fixed to left, vertically elastic
115 5 - horizontally elastic, vertically elastic
116 6 - fixed to right, vertically elastic
117
118 7 - fixed to left, fixed to bottom
119 8 - horizontally elastic, fixed to bottom
120 9 - fixed to right, fixed to bottom
121 */
122 resize {
123 ^this.getProperty(\resize)
124 }
125 resize_ { arg resize;
126 this.setProperty(\resize, resize)
127 }
128
129 background_ { arg color;
130 background = color;
131 this.setProperty(\background, color)
132 }
133 addAction { arg func, selector=\action;
134 this.perform(selector.asSetter, this.perform(selector).addFunc(func));
135 }
136 removeAction { arg func, selector=\action;
137 this.perform(selector.asSetter, this.perform(selector).removeFunc(func));
138 }
139 mouseDown{arg x, y, modifiers, buttonNumber, clickCount;
140 mouseDownAction.value(this, x, y, modifiers, buttonNumber, clickCount);
141 }
142 mouseUp{arg x, y, modifiers;
143 mouseUpAction.value(this, x, y, modifiers);
144 }
145 mouseMove{arg x, y, modifiers;
146 mouseMoveAction.value(this, x, y, modifiers);
147 }
148 mouseOver{arg x, y;
149 mouseOverAction.value(this, x, y);
150 }
151
152 keyDown { arg char, modifiers, unicode,keycode;
153 globalKeyDownAction.value(this, char, modifiers, unicode, keycode);
154 this.handleKeyDownBubbling(this, char, modifiers, unicode, keycode);
155 }
156
157 keyModifiersChanged{arg modifiers;
158 this.handleKeyModifiersChangedBubbling(this,modifiers)
159 }
160
161 handleKeyModifiersChangedBubbling { arg view, modifiers;
162 var result;
163 // nil from keyDownAction --> pass it on
164 if (keyModifiersChangedAction.isNil) {
165 // this.defaultKeyDownAction(char,modifiers,unicode,keycode);
166 result = nil;
167 }{
168 result = keyModifiersChangedAction.value(view, modifiers);
169 };
170 if(result.isNil) {
171 // call keydown action of parent view
172 parent.handleKeyModifiersChangedBubbling(view, modifiers);
173 };
174 }
175
176 defaultKeyDownAction { ^nil }
177 handleKeyDownBubbling { arg view, char, modifiers, unicode, keycode;
178 var result;
179 // nil from keyDownAction --> pass it on
180 if (keyDownAction.isNil) {
181 result = this.defaultKeyDownAction(char,modifiers,unicode,keycode);
182 }{
183 result = keyDownAction.value(view, char, modifiers, unicode, keycode);
184 };
185 if(result.isNil) {
186 // call keydown action of parent view
187 parent.handleKeyDownBubbling(view, char, modifiers, unicode, keycode);
188 };
189 }
190
191 // sc.solar addition
192 keyUp { arg char, modifiers, unicode,keycode;
193 this.keyTyped = char;
194 // always call global keydown action first
195 globalKeyUpAction.value(this, char, modifiers, unicode, keycode);
196 this.handleKeyUpBubbling(this, char, modifiers, unicode, keycode);
197 }
198 defaultKeyUpAction { ^nil }
199 handleKeyUpBubbling { arg view, char, modifiers,unicode,keycode;
200 var result;
201 // nil from keyDownAction --> pass it on
202 if (keyUpAction.isNil) {
203 result = this.defaultKeyUpAction(char,modifiers,unicode,keycode);
204 }{
205 result = keyUpAction.value(view, char, modifiers, unicode, keycode);
206 };
207 if(result.isNil) {
208 // call keydown action of parent view
209 parent.handleKeyUpBubbling(view, char, modifiers, unicode, keycode);
210 };
211 }
212
213
214 beginDrag {
215 currentDrag = if (beginDragAction.notNil)
216 {
217 beginDragAction.value(this)
218 }{
219 this.defaultGetDrag
220 };
221 currentDragString = currentDrag.asCompileString;
222 }
223 defaultGetDrag { ^nil }
224 canReceiveDrag {
225 ^if(canReceiveDragHandler.notNil,{ canReceiveDragHandler.value(this) },{ this.defaultCanReceiveDrag })
226 }
227 defaultCanReceiveDrag { ^false }
228 receiveDrag {|x,y|
229 if(receiveDragHandler.notNil,{ receiveDragHandler.value(this, x, y) },{ this.defaultReceiveDrag(x,y) });
230 currentDrag = currentDragString = nil;
231 }
232
233 // get the view parent tree up to the SCTopView
234 getParents {
235 var parents, view;
236 view = this;
237 parents = List.new;
238 while({(view = view.parent).notNil},{ parents.add(view)});
239 ^parents
240 }
241
242 doAction {
243 action.value(this);
244 }
245
246 properties {
247 ^#[\bounds, \visible, \enabled, \canFocus, \resize, \background,
248 \minWidth,\maxWidth,\minHeight,\maxHeight,\focusColor]
249 }
250 getPropertyList {
251 ^this.properties.collect({ arg name;
252 [name, this.perform(name)]
253 });
254 }
255 setPropertyList { arg list;
256 list.do({ arg item;
257 var name, value;
258 #name, value = item;
259 this.perform(name.asSetter, value);
260 });
261 }
262
263 // private
264 prInit { arg argParent, argBounds,argViewClass;
265 _SCView_New
266 ^this.primitiveFailed
267 }
268 prClose { dataptr = nil; onClose.value(this); }
269 prRemove {
270 _SCView_Remove
271 ^this.primitiveFailed
272 }
273 setProperty { arg key, value;
274 _SCView_SetProperty
275 ^this.primitiveFailed
276 }
277 getProperty { arg key, value;
278 _SCView_GetProperty
279 ^this.primitiveFailed
280 }
281 setPropertyWithAction { arg symbol, obj;
282 // setting some properties may need to have the action called.
283 if (this.setProperty(symbol, obj), {
284 // setProperty returns true if action needs to be called.
285 this.doAction;
286 });
287 }
288
289 // *importDrag {
290 // // this is called when an NSString is the drag object
291 // // from outside of the SC app
292 // // we compile it to an SCObject.
293 // currentDragString = currentDrag;
294 // currentDrag = currentDrag.interpret;
295 // }
296
297 absoluteBounds {
298 ^this.getProperty(\absoluteBounds,Rect.new)
299 }
300 }
301
302 SCContainerView : SCView { // abstract class
303 var <children, <decorator, < relativeOrigin = true;
304
305 add { arg child;
306 children = children.add(child);
307 if (decorator.notNil, { decorator.place(child); });
308 }
309
310 init { |argParent, argBounds|
311 super.init(argParent, argBounds);
312 // if user changed default relativeOrigin to true,
313 // the client would be out of sync with the cocoa widget
314 // without resetting the view property
315 this.relativeOrigin = relativeOrigin;
316 }
317
318 removeAll {
319 children.copy.do {|child| child.remove };
320 }
321
322 relativeOrigin_{ |bool|
323 relativeOrigin = bool;
324 this.setProperty(\relativeOrigin, bool);
325 }
326
327 addFlowLayout { |margin, gap|
328 this.relativeOrigin.if
329 {this.decorator_( FlowLayout( this.bounds.moveTo(0,0), margin, gap ) )}
330 {this.decorator_( FlowLayout( this.bounds, margin, gap ) )};
331 ^this.decorator;
332 }
333
334 decorator_ {|decor|
335 if(relativeOrigin, {
336 decor.bounds = decor.bounds.moveTo(0, 0);
337 decor.reset;
338 });
339 decorator = decor;
340 }
341
342 prRemoveChild { arg child;
343 children.remove(child);
344 // ... decorator should re-place all
345 }
346
347 //bounds_ ... replace all
348
349 prClose {
350 super.prClose;
351 children.do({ arg item; item.prClose });
352 }
353 }
354
355 SCCompositeView : SCContainerView {
356 }
357
358 SCTopView : SCCompositeView {
359 // created by SCWindow
360 handleKeyModifiersChangedBubbling { arg view, modifiers;
361 keyModifiersChangedAction.value(view, modifiers);
362 }
363 handleKeyDownBubbling { arg view, char, modifiers, unicode, keycode;
364 var currentAppModal, window;
365 keyDownAction.value(view, char, modifiers, unicode, keycode);
366 }
367 handleKeyUpBubbling { arg view, char, modifiers, unicode, keycode;
368 keyUpAction.value(view, char, modifiers, unicode, keycode);
369 }
370
371 //only in construction mode, handled internally
372 canReceiveDrag { ^currentDrag.isKindOf(Class)}
373 // remove { this.removeAll }
374
375 findWindow{
376 SCWindow.allWindows.do {|win|
377 if(win.view == this){
378 ^win
379 }
380 }
381 }
382
383 /* construction mode */
384
385 constructionGrid_{ arg point;
386 this.setProperty( \constructionGrid, point );
387 }
388
389 constructionGrid {
390 ^this.getProperty( \constructionGrid, Point.new );
391 }
392
393 enableConstructionGrid_{arg flag;
394 this.setProperty( \enableConstructionGrid, flag );
395 }
396
397 enableConstructionGrid{
398 ^this.getProperty( \enableConstructionGrid );
399 }
400
401 //private called from lang
402 setConstructionMode {|flag|
403 this.setProperty( \setConstructionMode, flag )
404 }
405
406 defaultReceiveDrag{|x,y|
407 var win, view;
408 win = this.findWindow;
409 view = currentDrag.paletteExample(win, Rect(x,y,140,24)).enabled_(false);
410 view.keyDownAction_({|view, char, modifiers, unicode, keycode|
411 if(keycode == 51){
412 view.remove;
413 }
414 });
415 }
416 }
417
418 SCScrollTopView : SCTopView {
419 var <autohidesScrollers = true, <hasHorizontalScroller = true, <hasVerticalScroller = true;
420 var <autoScrolls = true;
421
422 autohidesScrollers_{|bool|
423 autohidesScrollers = bool;
424 this.setProperty(\setAutohidesScrollers, bool);
425 }
426
427 hasHorizontalScroller_{|bool|
428 hasHorizontalScroller = bool;
429 this.setProperty(\setHasHorizontalScroller, bool);
430 }
431
432 hasVerticalScroller_{|bool|
433 hasVerticalScroller = bool;
434 this.setProperty(\setHasVerticalScroller, bool);
435 }
436
437 visibleOrigin_ { arg point;
438 this.setProperty( \clipViewOrigin, point );
439 }
440
441 visibleOrigin { ^this.getProperty( \clipViewOrigin, Point.new );}
442
443 autoScrolls_ {|bool|
444 autoScrolls = bool;
445 this.setProperty(\setAutoScrolls, bool);
446 }
447
448 innerBounds {
449 ^this.getProperty(\innerBounds, Rect.new)
450 }
451
452 bounds {
453 var bounds = this.absoluteBounds;
454 this.getParents.do({ |parent|
455 (parent.tryPerform(\relativeOrigin) == true).if({
456 bounds = bounds.moveBy(parent.bounds.left.neg, parent.bounds.top.neg)
457 }, {
458 ^bounds
459 });
460 });
461 ^bounds
462 }
463
464 // handleKeyModifiersChangedBubbling { arg view, modifiers;
465 // var result;
466 // // nil from keyDownAction --> pass it on
467 // if (keyModifiersChangedAction.isNil) {
468 // result = nil;
469 // }{
470 // result = keyModifiersChangedAction.value(view, modifiers);
471 // };
472 // if(result.isNil) {
473 // // call keydown action of parent view
474 // parent.handleKeyModifiersChangedBubbling(view, modifiers);
475 // };
476 // }
477 //
478 // handleKeyDownBubbling { arg view, char, modifiers, unicode, keycode;
479 // var result;
480 // // nil from keyDownAction --> pass it on
481 // if (keyDownAction.isNil) {
482 // result = this.defaultKeyDownAction(char,modifiers,unicode,keycode);
483 // }{
484 // result = keyDownAction.value(view, char, modifiers, unicode, keycode);
485 // };
486 // if(result.isNil) {
487 // // call keydown action of parent view
488 // parent.handleKeyDownBubbling(view, char, modifiers, unicode, keycode);
489 // };
490 // }
491 //
492 // handleKeyUpBubbling { arg view, char, modifiers,unicode,keycode;
493 // var result;
494 // // nil from keyDownAction --> pass it on
495 // if (keyUpAction.isNil) {
496 // result = this.defaultKeyUpAction(char,modifiers,unicode,keycode);
497 // }{
498 // result = keyUpAction.value(view, char, modifiers, unicode, keycode);
499 // };
500 // if(result.isNil) {
501 // // call keydown action of parent view
502 // parent.handleKeyUpBubbling(view, char, modifiers, unicode, keycode);
503 // };
504 // }
505
506 }
507
508 SCScrollView : SCScrollTopView {
509 var <hasBorder = false;
510
511 hasBorder_ { arg bool = true;
512 this.setProperty(\border, bool);
513 }
514
515 init { |argParent, argBounds|
516 super.init(argParent, argBounds);
517
518 relativeOrigin = false; // scroll views are never relative, although they really are ;-)
519 }
520
521 relativeOrigin_ { }
522
523 handleKeyModifiersChangedBubbling { arg view, modifiers;
524 var result;
525 // nil from keyDownAction --> pass it on
526 if (keyModifiersChangedAction.isNil) {
527 result = nil;
528 }{
529 result = keyModifiersChangedAction.value(view, modifiers);
530 };
531 if(result.isNil) {
532 // call keydown action of parent view
533 parent.handleKeyModifiersChangedBubbling(view, modifiers);
534 };
535 }
536
537 handleKeyDownBubbling { arg view, char, modifiers, unicode, keycode;
538 var result;
539 // nil from keyDownAction --> pass it on
540 if (keyDownAction.isNil) {
541 result = this.defaultKeyDownAction(char,modifiers,unicode,keycode);
542 }{
543 result = keyDownAction.value(view, char, modifiers, unicode, keycode);
544 };
545 if(result.isNil) {
546 // call keydown action of parent view
547 parent.handleKeyDownBubbling(view, char, modifiers, unicode, keycode);
548 };
549 }
550
551 handleKeyUpBubbling { arg view, char, modifiers,unicode,keycode;
552 var result;
553 // nil from keyDownAction --> pass it on
554 if (keyUpAction.isNil) {
555 result = this.defaultKeyUpAction(char,modifiers,unicode,keycode);
556 }{
557 result = keyUpAction.value(view, char, modifiers, unicode, keycode);
558 };
559 if(result.isNil) {
560 // call keydown action of parent view
561 parent.handleKeyUpBubbling(view, char, modifiers, unicode, keycode);
562 };
563 }
564
565 }
566
567 SCLayoutView : SCContainerView {
568 properties { ^super.properties ++ #[\spacing] }
569
570 spacing {
571 ^this.getProperty(\spacing, 0)
572 }
573 spacing_ { arg distance;
574 this.setProperty(\spacing, distance)
575 }
576 setProperty { |key, value|
577 // layout views don't recognize relativeOrigin in the backend
578 if(key != \relativeOrigin) {
579 super.setProperty(key, value);
580 };
581 }
582 }
583
584 SCHLayoutView : SCLayoutView {}
585 SCVLayoutView : SCLayoutView {}
586
587
588 SCControlView : SCView { // abstract class
589 }
590
591 SCSliderBase : SCControlView {
592
593 knobColor {
594 ^this.getProperty(\knobColor, Color.new)
595 }
596 knobColor_ { arg color;
597 this.setProperty(\knobColor, color)
598 }
599
600 step_ { arg stepSize;
601 this.setPropertyWithAction(\step, stepSize);
602 }
603 step {
604 ^this.getProperty(\step)
605 }
606
607 properties {
608 ^super.properties ++ #[\knobColor, \step]
609 }
610
611 }
612
613 SCSlider : SCSliderBase
614 {
615 value {
616 ^this.getProperty(\value)
617 }
618 value_ { arg val;
619 this.setProperty(\value, val);
620 }
621 valueAction_ { arg val;
622 this.setPropertyWithAction(\value, val);
623 }
624
625 increment { |zoom=1| ^this.valueAction = this.value + (max(this.step, this.pixelStep) * zoom) }
626 decrement { |zoom=1| ^this.valueAction = this.value - (max(this.step, this.pixelStep) * zoom) }
627
628 pixelStep {
629 var bounds = this.bounds;
630 ^(bounds.width.max(bounds.height) - this.thumbSize).reciprocal
631 }
632
633 defaultKeyDownAction { arg char, modifiers, unicode,keycode;
634 // standard keydown
635 if (char == $r, { this.valueAction = 1.0.rand; ^this });
636 if (char == $n, { this.valueAction = 0.0; ^this });
637 if (char == $x, { this.valueAction = 1.0; ^this });
638 if (char == $c, { this.valueAction = 0.5; ^this });
639 if (char == $], { this.increment; ^this });
640 if (char == $[, { this.decrement; ^this });
641 if (unicode == 16rF700, { this.increment; ^this });
642 if (unicode == 16rF703, { this.increment; ^this });
643 if (unicode == 16rF701, { this.decrement; ^this });
644 if (unicode == 16rF702, { this.decrement; ^this });
645 ^nil // bubble if it's an invalid key
646 }
647
648 defaultGetDrag {
649 ^this.value
650 }
651 defaultCanReceiveDrag {
652 ^currentDrag.isNumber
653 }
654 defaultReceiveDrag {
655 this.valueAction = currentDrag;
656 }
657
658 thumbSize {
659 ^this.getProperty(\thumbSize, 12);
660 }
661 thumbSize_ { arg size;
662 this.setProperty(\thumbSize, size);
663 }
664
665 properties {
666 ^super.properties ++ #[\thumbSize];
667 }
668 }
669
670 SCRangeSlider : SCSliderBase {
671
672 *paletteExample { arg parent, bounds;
673 var v;
674 v = this.new(parent, bounds);
675 v.lo = 0.2;
676 v.hi = 0.7;
677 ^v
678 }
679
680 lo {
681 ^this.getProperty(\lo)
682 }
683 lo_ { arg val;
684 this.setProperty(\lo, val);
685 }
686 activeLo_ { arg val;
687 this.setPropertyWithAction(\lo, val);
688 }
689 hi {
690 ^this.getProperty(\hi)
691 }
692 hi_ { arg val;
693 this.setProperty(\hi, val);
694 }
695 activeHi_ { arg val;
696 this.setPropertyWithAction(\hi, val);
697 }
698 range {
699 ^this.getProperty(\range)
700 }
701 range_ { arg val;
702 this.setProperty(\range, val);
703 }
704 activeRange_ { arg val;
705 this.setPropertyWithAction(\range, val);
706 }
707
708 setSpan { arg lo, hi;
709 this.lo = lo;
710 this.hi = hi;
711 }
712
713 setSpanActive { arg lo, hi;
714 this.setSpan( lo, hi );
715 this.doAction;
716 }
717
718 setDeviation { arg deviation, average;
719 var lo = ( 1 - deviation ) * average;
720 this.setSpan(lo, lo + deviation);
721 }
722
723 properties {
724 ^super.properties ++ #[\lo, \hi]
725 }
726
727 pixelStep {
728 var bounds = this.bounds;
729 ^(bounds.width.max(bounds.height)).reciprocal
730 }
731
732 increment { |zoom=1|
733 var inc = (max(this.step, this.pixelStep) * zoom);
734 var newHi = (this.hi + inc);
735 if (newHi > 1) {
736 inc = 1 - this.hi;
737 newHi = 1;
738 };
739 this.lo_(this.lo + inc).activeHi_(newHi);
740 }
741
742 decrement { |zoom=1|
743 var inc = (max(this.step, this.pixelStep) * zoom);
744 var newLo = (this.lo - inc);
745 if (newLo < 0) {
746 inc = this.lo;
747 newLo = 0;
748 };
749 this.lo_(newLo).activeHi_(this.hi - inc);
750 }
751
752 defaultKeyDownAction { arg char, modifiers, unicode;
753 var a, b;
754 // standard keydown
755 if (char == $r, {
756 a = 1.0.rand;
757 b = 1.0.rand;
758 this.activeLo_(min(a, b));
759 this.activeHi_(max(a, b));
760 ^this
761 });
762 if (char == $n, { this.activeLo_(0.0); this.activeHi_(0.0); ^this });
763 if (char == $x, { this.activeLo_(1.0); this.activeHi_(1.0); ^this });
764 if (char == $c, { this.activeLo_(0.5); this.activeHi_(0.5); ^this });
765 if (char == $a, { this.activeLo_(0.0); this.activeHi_(1.0); ^this });
766 if (unicode == 16rF700, { this.increment; ^this });
767 if (unicode == 16rF703, { this.increment; ^this });
768 if (unicode == 16rF701, { this.decrement; ^this });
769 if (unicode == 16rF702, { this.decrement; ^this });
770 ^nil // bubble if it's an invalid key
771 }
772 defaultGetDrag { ^Point(this.lo, this.hi) }
773 defaultCanReceiveDrag {
774 ^currentDrag.isKindOf(Point);
775 }
776 defaultReceiveDrag {
777 // changed to x,y instead of lo, hi
778 this.lo = currentDrag.x;
779 this.hi = currentDrag.y;
780 this.doAction
781 }
782 }
783
784 SCButton : SCControlView {
785 var <font, <states;
786
787 *paletteExample { arg parent, bounds;
788 var v;
789 v = this.new(parent, bounds);
790 v.states = [
791 ["Push", Color.black, Color.red],
792 ["Pop", Color.white, Color.blue]];
793 ^v
794 }
795
796 value {
797 ^this.getProperty(\value)
798 }
799 value_ { arg val;
800 this.setProperty(\value, val);
801 }
802 valueAction_ { arg val;
803 this.setPropertyWithAction(\value, val);
804 }
805
806 doAction { arg modifiers;
807 action.value(this, modifiers);
808 }
809
810 defaultKeyDownAction { arg char, modifiers, unicode;
811 if (char == $ , { this.valueAction = this.value + 1; ^this });
812 if (char == $\r, { this.valueAction = this.value + 1; ^this });
813 if (char == $\n, { this.valueAction = this.value + 1; ^this });
814 if (char == 3.asAscii, { this.valueAction = this.value + 1; ^this });
815 ^nil // bubble if it's an invalid key
816 }
817
818 font_ { arg argFont;
819 font = argFont;
820 this.setProperty(\font, font)
821 }
822
823 states_ { arg array;
824 states = array;
825 this.setProperty(\states, states);
826 }
827
828 properties {
829 ^super.properties ++ #[\value, \font, \states]
830 }
831
832 defaultGetDrag {
833 ^this.value
834 }
835 defaultCanReceiveDrag {
836 ^currentDrag.isNumber or: { currentDrag.isKindOf(Function) };
837 }
838 defaultReceiveDrag {
839 if (currentDrag.isNumber) {
840 this.valueAction = currentDrag;
841 }{
842 this.action = currentDrag;
843 };
844 }
845 }
846
847 SCStaticTextBase : SCView {
848 var <string, <font, <object, <>setBoth=true;
849
850 font_ { arg argFont;
851 font = argFont;
852 this.setProperty(\font, font)
853 }
854
855 string_ { arg argString;
856 string = argString.asString;
857 this.setProperty(\string, string)
858 }
859 align_ { arg align;
860 this.setProperty(\align, align)
861 }
862
863 stringColor {
864 ^this.getProperty(\stringColor, Color.new)
865 }
866 stringColor_ { arg color;
867 this.setProperty(\stringColor, color)
868 }
869
870 object_ { arg obj;
871 object = obj;
872 if (setBoth) { this.string = object.asString(80); };
873 }
874
875 properties {
876 ^super.properties ++ #[\string, \font, \stringColor]
877 }
878 }
879
880 SCStaticText : SCStaticTextBase {
881 *paletteExample { arg parent, bounds;
882 var v;
883 v = this.new(parent, bounds);
884 v.string = "The lazy brown fox";
885 ^v
886 }
887 }
888
889
890 SCNumberBox : SCStaticTextBase {
891 var <> keyString, <>step=1;
892 var <>typingColor, <>normalColor;
893 var <>clipLo = -inf, <>clipHi = inf, hit, inc=1.0, <>scroll=true, <>shift_step=0.1, <>ctrl_step=10;
894
895 *paletteExample { arg parent, bounds;
896 var v;
897 v = this.new(parent, bounds);
898 v.value = 123.456;
899 ^v
900 }
901
902 init { arg argParent, argBounds;
903 typingColor = Color.red;
904 normalColor = Color.black;
905 background = Color.white;
906 parent = argParent.asView; // actual view
907 this.prInit(parent.asView, argBounds.asRect,this.class.viewClass);
908 argParent.add(this);//maybe window or viewadapter
909 }
910
911 increment { this.valueAction = this.value + step; }
912 decrement { this.valueAction = this.value - step; }
913
914 defaultKeyDownAction { arg char, modifiers, unicode;
915 // standard chardown
916 if (unicode == 16rF700, { this.increment; ^this });
917 if (unicode == 16rF703, { this.increment; ^this });
918 if (unicode == 16rF701, { this.decrement; ^this });
919 if (unicode == 16rF702, { this.decrement; ^this });
920 if ((char == 3.asAscii) || (char == $\r) || (char == $\n), { // enter key
921 if (keyString.notNil,{ // no error on repeated enter
922 this.valueAction_(keyString.asFloat);
923 });
924 ^this
925 });
926 if (char == 127.asAscii, { // delete key
927 keyString = nil;
928 this.string = object.asString;
929 this.stringColor = normalColor;
930 ^this
931 });
932 if (char.isDecDigit || "+-.eE".includes(char), {
933 if (keyString.isNil, {
934 keyString = String.new;
935 this.stringColor = typingColor;
936 });
937 keyString = keyString.add(char);
938 this.string = keyString;
939 ^this
940 });
941 ^nil // bubble if it's an invalid key
942 }
943
944 value { ^object }
945 value_ { arg val;
946 keyString = nil;
947 this.stringColor = normalColor;
948 object = val !? { val.clip(clipLo, clipHi) };
949 this.string = object.asString;
950 }
951 valueAction_ { arg val;
952 var prev;
953 prev = object;
954 this.value = val !? { val.clip(clipLo, clipHi) };
955 if (object != prev, { this.doAction });
956 }
957
958 boxColor {
959 this.deprecated(thisMethod, SCView.findMethod(\background));
960 ^this.background;
961 }
962 boxColor_ { arg color;
963 this.deprecated(thisMethod, SCView.findMethod(\background_));
964 this.background_(color)
965 }
966
967 properties {
968 ^super.properties ++ #[\boxColor]
969 }
970 defaultGetDrag {
971 ^object.asFloat
972 }
973 defaultCanReceiveDrag {
974 ^currentDrag.isNumber;
975 }
976 defaultReceiveDrag {
977 this.valueAction = currentDrag;
978 }
979
980 mouseDown { arg x, y, modifiers, buttonNumber, clickCount;
981 hit = Point(x,y);
982 if (scroll == true, {
983 inc = 1.0;
984 case
985 { modifiers & 131072 == 131072 } // shift defaults to step x 0.1
986 { inc = shift_step }
987 { modifiers & 262144 == 262144 } // control defaults to step x 10
988 { inc = ctrl_step };
989 });
990 mouseDownAction.value(this, x, y, modifiers, buttonNumber, clickCount)
991 }
992
993 mouseMove { arg x, y, modifiers;
994 var direction;
995 if (scroll == true, {
996 direction = 1.0;
997 // horizontal or vertical scrolling:
998 if ( (x - hit.x) < 0 or: { (y - hit.y) > 0 }) { direction = -1.0; };
999
1000 this.valueAction = (this.value + (inc * this.step * direction));
1001 hit = Point(x, y);
1002 });
1003 mouseMoveAction.value(this, x, y, modifiers);
1004 }
1005 }
00 Main : Process {
11 // do not change the next lines manually:
22 //==== replace with new version from bash script ====
3 classvar scVersionMajor=3, scVersionMinor=4, scVersionPostfix="";
3 classvar scVersionMajor=3, scVersionMinor=4, scVersionPostfix=".2";
44 //==== end replace ====
55
66 var <platform, argv;
145145 container.wakeUpParentsToBundle(bundle);
146146 this.sendObjectToBundle(bundle, container, extraArgs, index);
147147 };
148 nodeMap.wakeUpParentsToBundle(bundle);
148149 bundle.schedSend(server, clock ? TempoClock.default, quant);
149150 } {
150151 loaded = false;
404405 var ctl, rate, numChannels, canBeMapped;
405406 if(proxy.isNil) { ^this.unmap(key) };
406407 ctl = this.controlNames.detect { |x| x.name == key };
407 rate = ctl.rate ?? {
408 if(proxy.isNeutral) {
408 rate = ctl.rate ?? {
409 if(proxy.isNeutral) {
409410 if(this.isNeutral) { \audio } { this.rate }
410 } {
411 proxy.rate
411 } {
412 proxy.rate
412413 }
413414 };
414415 numChannels = ctl !? { ctl.defaultValue.asArray.size }; canBeMapped = proxy.initBus(rate, numChannels);
418419 } {
419420 "Could not link node proxies, no matching input found.".warn
420421 };
421 ^proxy; // returns first argument for further chaining
422 ^proxy // returns first argument for further chaining
422423 }
423424
424425
801802 if(loaded.not) { this.loadToBundle(bundle) };
802803 if(awake and: { this.isPlaying.not }) {
803804 this.prepareToBundle(nil, bundle, \addToHead);
804 this.sendAllToBundle(bundle)
805 this.sendAllToBundle(bundle);
805806 };
806807 };
807808
809810
810811 wakeUpParentsToBundle { | bundle, checkedAlready |
811812 nodeMap.wakeUpParentsToBundle(bundle, checkedAlready);
812 objects.do{ arg item; item.wakeUpParentsToBundle(bundle, checkedAlready) };
813 objects.do { arg item; item.wakeUpParentsToBundle(bundle, checkedAlready) };
813814 }
814815
815816
+0
-4
common/build/SCClassLibrary/Platform/iphone/extMain.sc less more
0 + Main
1 {
2 platformClass { ^IPhonePlatform }
3 }
+0
-26
common/build/SCClassLibrary/Platform/iphone/extString.sc less more
0 + String
1 {
2 loadPath { arg warnIfNotFound=true;
3 var obj,path;
4 path = this.standardizePath;
5 if(File.exists(path),{
6 {
7 obj = thisProcess.interpreter.executeFile(path);
8 //obj.didLoadFromPath(this);
9 }.try({ arg err;
10 ("In file: " + this).postln;
11 err.throw;
12 });
13 },{
14 if(warnIfNotFound,{
15 warn("String:loadPath file not found " + this + path);
16 });
17 });
18 if(obj.isNil and: warnIfNotFound, {
19 warn("String:loadPath found nil, empty contents or parse error in " + path);
20
21 //^ObjectNotFound.new(path)
22 });
23 ^obj
24 }
25 }
2929 graphical = false
3030 #the location of the rc file to source
3131 rcloc = nil
32
33 # debian-based systems do not activate vim plugins automatically, we must check
34 if %x[which vim-addons]!="" && %x[vim-addons -q status supercollider | grep installed]==""
35 puts "scvim has detected that you haven't activated the vim supercollider plugin."
36 puts "to enable scvim to work, please execute either "
37 puts " vim-addons install supercollider"
38 puts "to enable it for the current user, or "
39 puts " sudo vim-addons -w install supercollider"
40 puts "to enable it system-wide."
41 puts ""
42 puts "Would you like me to run \"vim-addons install supercollider\" for you?"
43 puts "Press 'y' and then Enter if so. Otherwise just press Enter to exit."
44 userreply = gets.chomp
45 if userreply == 'y'
46 %x[vim-addons install supercollider]
47 else
48 exit
49 end
50 end
3251
3352 opts = OptionParser.new do |opts|
3453 #the usage banner
2626 if(scvim_cache_dir_env.isNil){
2727 scvim_cache_dir = "~/.scvim".standardizePath;
2828 setenv("SCVIM_CACHE_DIR", scvim_cache_dir);
29 //inform("SCVim: I've set the cache dir based on the scvim dir");
3029 }{
3130 scvim_cache_dir = scvim_cache_dir_env;
32 //inform("SCVim: I've set the cache dir based on the environment variable");
3331 };
3432 StartUp.add{
35 if(autoFirstRun and:{ File.exists(scvim_cache_dir).not }){
36 Task{
37 "SCVim: generating help docs, it will take a few moments. (This only happens the first time you launch scvim. See SCVim help file for more info.)".inform;
38 this.updateCaches;
39 this.updateHelpCache;
40 "SCVim: finished generating help docs".inform;
41 }.play;
33 if(Platform.ideName=="scvim"){
34 if(autoFirstRun and:{ File.exists(scvim_cache_dir).not }){
35 Task{
36 "SCVim: generating help docs, it will take a few moments. (This only happens the first time you launch scvim. See SCVim help file for more info.)".inform;
37 this.updateCaches;
38 this.updateHelpCache;
39 "SCVim: finished generating help docs".inform;
40 }.play;
41 };
4242 };
4343 };
4444 }