From: <nsc...@us...> - 2008-08-21 16:18:41
|
Revision: 1865 http://ftm.svn.sourceforge.net/ftm/?rev=1865&view=rev Author: nschnell Date: 2008-08-21 15:42:09 +0000 (Thu, 21 Aug 2008) Log Message: ----------- added very first versions of Max 5 externals (for Alpha version based on FTM 2.3) Modified Paths: -------------- trunk/ftm/build/max/osx-macho/ftmexternals-max5.xcodeproj/schnell.mode1v3 trunk/ftm/build/max/osx-macho/ftmexternals-max5.xcodeproj/schnell.pbxuser trunk/ftm/build/max/osx-macho/ftmexternals.xcodeproj/project.pbxproj trunk/ftm/build/max/osx-macho/ftmlib-max5.xcodeproj/schnell.mode1v3 trunk/ftm/build/max/osx-macho/ftmlib-max5.xcodeproj/schnell.pbxuser trunk/ftm/build/max/osx-macho/ftmlib.xcodeproj/project.pbxproj Added Paths: ----------- trunk/ftm/externals/max5/ trunk/ftm/externals/max5/ftm.mess.c trunk/ftm/externals/max5/ftm.object.c trunk/ftm/externals/max5/ftm.vecdisplay.c Modified: trunk/ftm/build/max/osx-macho/ftmexternals-max5.xcodeproj/schnell.mode1v3 =================================================================== --- trunk/ftm/build/max/osx-macho/ftmexternals-max5.xcodeproj/schnell.mode1v3 2008-08-14 13:56:46 UTC (rev 1864) +++ trunk/ftm/build/max/osx-macho/ftmexternals-max5.xcodeproj/schnell.mode1v3 2008-08-21 15:42:09 UTC (rev 1865) @@ -197,48 +197,7 @@ <key>Notifications</key> <array/> <key>OpenEditors</key> - <array> - <dict> - <key>Content</key> - <dict> - <key>PBXProjectModuleGUID</key> - <string>5CD5DEC20E18215E00C85139</string> - <key>PBXProjectModuleLabel</key> - <string>ftm.jitter.c</string> - <key>PBXSplitModuleInNavigatorKey</key> - <dict> - <key>Split0</key> - <dict> - <key>PBXProjectModuleGUID</key> - <string>5CD5DEC30E18215E00C85139</string> - <key>PBXProjectModuleLabel</key> - <string>ftm.jitter.c</string> - <key>_historyCapacity</key> - <integer>0</integer> - <key>bookmark</key> - <string>5CD5DEC40E18215E00C85139</string> - <key>history</key> - <array> - <string>5CD5DEBD0E18213700C85139</string> - </array> - </dict> - <key>SplitCount</key> - <string>1</string> - </dict> - <key>StatusBarVisibility</key> - <true/> - </dict> - <key>Geometry</key> - <dict> - <key>Frame</key> - <string>{{0, 20}, {1120, 777}}</string> - <key>PBXModuleWindowStatusBarHidden2</key> - <false/> - <key>RubberWindowFrame</key> - <string>15 60 1120 818 0 0 1440 878 </string> - </dict> - </dict> - </array> + <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> @@ -558,9 +517,9 @@ <integer>5</integer> <key>WindowOrderList</key> <array> + <string>5CD5DEC20E18215E00C85139</string> <string>5CD5DBA70E17D83600C85139</string> <string>/Users/schnell/Development/ftm/build/max/osx-macho/ftmexternals-max5.xcodeproj</string> - <string>5CD5DEC20E18215E00C85139</string> </array> <key>WindowString</key> <string>0 59 1440 819 0 0 1440 878 </string> Modified: trunk/ftm/build/max/osx-macho/ftmexternals-max5.xcodeproj/schnell.pbxuser =================================================================== --- trunk/ftm/build/max/osx-macho/ftmexternals-max5.xcodeproj/schnell.pbxuser 2008-08-14 13:56:46 UTC (rev 1864) +++ trunk/ftm/build/max/osx-macho/ftmexternals-max5.xcodeproj/schnell.pbxuser 2008-08-21 15:42:09 UTC (rev 1865) @@ -61,10 +61,6 @@ PBXPerProjectTemplateStateSaveDate = 236462161; PBXWorkspaceStateSaveDate = 236462161; }; - perUserProjectItems = { - 5CD5DEBD0E18213700C85139 /* PBXTextBookmark */ = 5CD5DEBD0E18213700C85139 /* PBXTextBookmark */; - 5CD5DEC40E18215E00C85139 /* PBXTextBookmark */ = 5CD5DEC40E18215E00C85139 /* PBXTextBookmark */; - }; sourceControlManager = 5CD5DBA90E17D83700C85139 /* Source Control */; userBuildSettings = { }; @@ -163,29 +159,12 @@ sepNavIntBoundsRect = "{{0, 0}, {1061, 13472}}"; sepNavSelRange = "{21821, 0}"; sepNavVisRange = "{21301, 1255}"; + sepNavWindowFrame = "{{15, 4}, {1120, 874}}"; }; }; 5CD5DEB30E1820FC00C85139 /* todo */ = { activeExec = 0; }; - 5CD5DEBD0E18213700C85139 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - comments = "warning: passing argument 3 of 'maxext_init_raw' from incompatible pointer type"; - fRef = 5CD5DDA30E17FCAB00C85139 /* ftm.jitter.c */; - rLen = 1; - rLoc = 775; - rType = 1; - }; - 5CD5DEC40E18215E00C85139 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 5CD5DDA30E17FCAB00C85139 /* ftm.jitter.c */; - name = "ftm.jitter.c: 770"; - rLen = 0; - rLoc = 21821; - rType = 0; - vrLen = 1255; - vrLoc = 21301; - }; 5CEF80BA0AB157E500AE1943 /* additional */ = { activeExec = 0; }; Modified: trunk/ftm/build/max/osx-macho/ftmexternals.xcodeproj/project.pbxproj =================================================================== --- trunk/ftm/build/max/osx-macho/ftmexternals.xcodeproj/project.pbxproj 2008-08-14 13:56:46 UTC (rev 1864) +++ trunk/ftm/build/max/osx-macho/ftmexternals.xcodeproj/project.pbxproj 2008-08-21 15:42:09 UTC (rev 1865) @@ -4152,12 +4152,14 @@ F47D6B1508A36696001D9636 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + PRODUCT_NAME = install; }; name = Debug; }; F47D6B1608A36696001D9636 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + PRODUCT_NAME = install; }; name = Release; }; Modified: trunk/ftm/build/max/osx-macho/ftmlib-max5.xcodeproj/schnell.mode1v3 =================================================================== --- trunk/ftm/build/max/osx-macho/ftmlib-max5.xcodeproj/schnell.mode1v3 2008-08-14 13:56:46 UTC (rev 1864) +++ trunk/ftm/build/max/osx-macho/ftmlib-max5.xcodeproj/schnell.mode1v3 2008-08-21 15:42:09 UTC (rev 1865) @@ -271,6 +271,7 @@ <array> <string>0867D691FE84028FC02AAC07</string> <string>1C37FBAC04509CD000000102</string> + <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> @@ -280,7 +281,7 @@ </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> - <string>{{0, 0}, {185, 760}}</string> + <string>{{0, 0}, {185, 884}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> @@ -292,14 +293,14 @@ <key>GeometryConfiguration</key> <dict> <key>Frame</key> - <string>{{0, 0}, {202, 778}}</string> + <string>{{0, 0}, {202, 902}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>185</real> </array> <key>RubberWindowFrame</key> - <string>0 59 1440 819 0 0 1440 878 </string> + <string>0 59 1280 943 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> @@ -334,9 +335,9 @@ <key>GeometryConfiguration</key> <dict> <key>Frame</key> - <string>{{0, 0}, {1233, 0}}</string> + <string>{{0, 0}, {1073, 0}}</string> <key>RubberWindowFrame</key> - <string>0 59 1440 819 0 0 1440 878 </string> + <string>0 59 1280 943 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> @@ -354,18 +355,18 @@ <key>GeometryConfiguration</key> <dict> <key>Frame</key> - <string>{{0, 5}, {1233, 773}}</string> + <string>{{0, 5}, {1073, 897}}</string> <key>RubberWindowFrame</key> - <string>0 59 1440 819 0 0 1440 878 </string> + <string>0 59 1280 943 0 0 1280 1002 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> - <string>773pt</string> + <string>897pt</string> </dict> </array> <key>Proportion</key> - <string>1233pt</string> + <string>1073pt</string> </dict> </array> <key>Name</key> @@ -380,9 +381,9 @@ </array> <key>TableOfContents</key> <array> - <string>5CD5DDBC0E18010100C85139</string> + <string>5CD5DFB00E18492000C85139</string> <string>1CE0B1FE06471DED0097A5F4</string> - <string>5CD5DDBD0E18010100C85139</string> + <string>5CD5DFB10E18492000C85139</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> @@ -516,10 +517,15 @@ <integer>5</integer> <key>WindowOrderList</key> <array> + <string>5CD5DFB90E18492000C85139</string> + <string>5CD5DFBA0E18492000C85139</string> + <string>5CD5DFBB0E18492000C85139</string> + <string>1C78EAAD065D492600B07095</string> + <string>1CD10A99069EF8BA00B06720</string> <string>/Users/schnell/Development/ftm/build/max/osx-macho/ftmlib-max5.xcodeproj</string> </array> <key>WindowString</key> - <string>0 59 1440 819 0 0 1440 878 </string> + <string>0 59 1280 943 0 0 1280 1002 </string> <key>WindowToolsV3</key> <array> <dict> @@ -598,7 +604,7 @@ <key>TableOfContents</key> <array> <string>5CD5DB5F0E17D6D600C85139</string> - <string>5CD5DB600E17D6D600C85139</string> + <string>5CD5DE850E18200E00C85139</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> @@ -612,8 +618,12 @@ <false/> </dict> <dict> + <key>FirstTimeWindowDisplayed</key> + <false/> <key>Identifier</key> <string>windowTool.debugger</string> + <key>IsVertical</key> + <true/> <key>Layout</key> <array> <dict> @@ -636,8 +646,8 @@ <string>yes</string> <key>sizes</key> <array> - <string>{{0, 0}, {317, 164}}</string> - <string>{{317, 0}, {377, 164}}</string> + <string>{{0, 0}, {183, 251}}</string> + <string>{{183, 0}, {1097, 251}}</string> </array> </dict> <key>VerticalSplitView</key> @@ -652,8 +662,8 @@ <string>yes</string> <key>sizes</key> <array> - <string>{{0, 0}, {694, 164}}</string> - <string>{{0, 164}, {694, 216}}</string> + <string>{{0, 0}, {1280, 251}}</string> + <string>{{0, 251}, {1280, 650}}</string> </array> </dict> </dict> @@ -666,8 +676,6 @@ </dict> <key>GeometryConfiguration</key> <dict> - <key>DebugConsoleDrawerSize</key> - <string>{100, 120}</string> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> @@ -675,18 +683,34 @@ <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> - <string>{{0, 0}, {694, 380}}</string> + <string>{{0, 0}, {1280, 901}}</string> + <key>PBXDebugSessionStackFrameViewKey</key> + <dict> + <key>DebugVariablesTableConfiguration</key> + <array> + <string>Name</string> + <real>120</real> + <string>Value</string> + <real>85</real> + <string>Summary</string> + <real>867</real> + </array> + <key>Frame</key> + <string>{{183, 0}, {1097, 251}}</string> + <key>RubberWindowFrame</key> + <string>0 60 1280 942 0 0 1280 1002 </string> + </dict> <key>RubberWindowFrame</key> - <string>321 238 694 422 0 0 1440 878 </string> + <string>0 60 1280 942 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> - <string>100%</string> + <string>901pt</string> </dict> </array> <key>Proportion</key> - <string>100%</string> + <string>901pt</string> </dict> </array> <key>Name</key> @@ -696,22 +720,26 @@ <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> - <integer>1</integer> + <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> - <string>1C0AD2AB069F1E9B00FABCE6</string> + <string>5CD5DFB20E18492000C85139</string> <string>1C162984064C10D400B95A72</string> - <string>1C0AD2AC069F1E9B00FABCE6</string> + <string>5CD5DFB30E18492000C85139</string> + <string>5CD5DFB40E18492000C85139</string> + <string>5CD5DFB50E18492000C85139</string> + <string>5CD5DFB60E18492000C85139</string> + <string>5CD5DFB70E18492000C85139</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> - <string>321 238 694 422 0 0 1440 878 </string> + <string>0 60 1280 942 0 0 1280 1002 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> - <integer>0</integer> + <false/> </dict> <dict> <key>Identifier</key> @@ -817,8 +845,12 @@ <string>MENUSEPARATOR</string> </dict> <dict> + <key>FirstTimeWindowDisplayed</key> + <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> + <key>IsVertical</key> + <true/> <key>Layout</key> <array> <dict> @@ -826,7 +858,7 @@ <array> <dict> <key>BecomeActive</key> - <integer>1</integer> + <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> @@ -837,9 +869,9 @@ <key>GeometryConfiguration</key> <dict> <key>Frame</key> - <string>{{0, 0}, {650, 250}}</string> + <string>{{0, 0}, {650, 209}}</string> <key>RubberWindowFrame</key> - <string>516 632 650 250 0 0 1680 1027 </string> + <string>1301 750 650 250 1280 124 1440 900 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> @@ -858,21 +890,21 @@ <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> - <integer>1</integer> + <true/> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> - <string>1C78EAAE065D492600B07095</string> + <string>5CD5DFB80E18492000C85139</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> - <string>650 41 650 250 0 0 1280 1002 </string> + <string>1301 750 650 250 1280 124 1440 900 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> - <integer>0</integer> + <false/> </dict> <dict> <key>Identifier</key> Modified: trunk/ftm/build/max/osx-macho/ftmlib-max5.xcodeproj/schnell.pbxuser =================================================================== --- trunk/ftm/build/max/osx-macho/ftmlib-max5.xcodeproj/schnell.pbxuser 2008-08-14 13:56:46 UTC (rev 1864) +++ trunk/ftm/build/max/osx-macho/ftmlib-max5.xcodeproj/schnell.pbxuser 2008-08-21 15:42:09 UTC (rev 1865) @@ -3,17 +3,35 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { activeArchitecture = i386; activeBuildConfigurationName = Debug; + activeExecutable = 5CD5DFA90E18490A00C85139 /* debug runtime */; activeTarget = 8D07F2BC0486CC7A007CD1D0 /* ftmlib */; addToTargets = ( ); codeSenseManager = 5CD5DB650E17D6D800C85139 /* Code sense */; + executables = ( + 5CD5DFA90E18490A00C85139 /* debug runtime */, + ); perUserDictionary = { + PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 22, + 300, + 722, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXExecutablesDataSource_ActiveFlagID, + PBXExecutablesDataSource_NameID, + PBXExecutablesDataSource_CommentsID, + ); + }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, - 994, + 834, 20, 48, 43, @@ -52,16 +70,30 @@ PBXFileDataSource_Warnings_ColumnID, ); }; - PBXPerProjectTemplateStateSaveDate = 236462087; - PBXWorkspaceStateSaveDate = 236462087; + PBXPerProjectTemplateStateSaveDate = 236472524; + PBXWorkspaceStateSaveDate = 236472524; }; sourceControlManager = 5CD5DB640E17D6D800C85139 /* Source Control */; userBuildSettings = { }; }; + 5C0B80C0082E1D0500E7F7D3 /* maxext.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 20176}}"; + sepNavSelRange = "{5017, 0}"; + sepNavVisRange = "{4586, 739}"; + }; + }; 5C209E120D0EDF8200BF135F /* libftm */ = { activeExec = 0; }; + 5C5F07D1078218BA00A59DE2 /* ftmext.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1379, 25408}}"; + sepNavSelRange = "{31869, 0}"; + sepNavVisRange = "{32155, 472}"; + }; + }; 5C7009230B836A3F001663C7 /* libftmlight */ = { activeExec = 0; }; @@ -79,6 +111,57 @@ isa = PBXCodeSenseManager; indexTemplatePath = ""; }; + 5CD5DFA90E18490A00C85139 /* debug runtime */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 1; + configStateDict = { + "PBXLSLaunchAction-0" = { + PBXLSLaunchAction = 0; + PBXLSLaunchStartAction = 1; + PBXLSLaunchStdioStyle = 2; + PBXLSLaunchStyle = 0; + class = PBXLSRunLaunchConfig; + commandLineArgs = ( + ); + displayName = "Executable Runner"; + environment = { + }; + identifier = com.apple.Xcode.launch.runConfig; + remoteHostInfo = ""; + startActionInfo = ""; + }; + }; + customDataFormattersEnabled = 1; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + launchableReference = 5CD5DFAA0E18490A00C85139 /* MaxMSP Runtime.app */; + libgmallocEnabled = 0; + name = "debug runtime"; + savedGlobals = { + }; + sourceDirectories = ( + ); + variableFormatDictionary = { + }; + }; + 5CD5DFAA0E18490A00C85139 /* MaxMSP Runtime.app */ = { + isa = PBXFileReference; + lastKnownFileType = wrapper.application; + name = "MaxMSP Runtime.app"; + path = "/Applications/Max5/MaxMSP Runtime.app"; + sourceTree = "<absolute>"; + }; 8D07F2BC0486CC7A007CD1D0 /* ftmlib */ = { activeExec = 0; }; Modified: trunk/ftm/build/max/osx-macho/ftmlib.xcodeproj/project.pbxproj =================================================================== --- trunk/ftm/build/max/osx-macho/ftmlib.xcodeproj/project.pbxproj 2008-08-14 13:56:46 UTC (rev 1864) +++ trunk/ftm/build/max/osx-macho/ftmlib.xcodeproj/project.pbxproj 2008-08-21 15:42:09 UTC (rev 1865) @@ -1038,7 +1038,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "#rm -Rf $FRAMEWORK_PATH/FTMlib.framework\n#cp -Rf $BUILT_PRODUCTS_DIR/FTMlib.framework $FRAMEWORK_PATH\nrm -Rf $EXTERNALS_DIR/FTMlib.framework\ncp -Rf $BUILT_PRODUCTS_DIR/FTMlib.framework $EXTERNALS_DIR\n\nmkdir $EXTERNALS_DIR/FTMLib.framework/Resources/java/\n\nif [ -e \"../osx-java/build/$CONFIGURATION/libftmJNILib.jnilib\" ] ; then\n\tcp -f \"../osx-java/build/$CONFIGURATION/libftmJNILib.jnilib\" $EXTERNALS_DIR/FTMLib.framework/Resources/java/\n\ncd $EXTERNALS_DIR/FTMLib.framework/Resources/java/\n\nFTMLIB_FRAMEWORK=`otool -L libftmJNILib.jnilib | grep FTM | awk '{print $1}'`\n\necho \"[patching dynamic library\"\necho \" from '$FTMLIB_FRAMEWORK'\"\necho \" to '@loader_path/../../FTMLib'\"\necho \" in 'libftmJNILib.jnilib']\"\n\ninstall_name_tool -change $FTMLIB_FRAMEWORK '@loader_path/../../FTMLib' libftmJNILib.jnilib\n\nfi\n"; + shellScript = "rm -Rf $FRAMEWORK_PATH/FTMlib.framework\ncp -Rf $BUILT_PRODUCTS_DIR/FTMlib.framework $FRAMEWORK_PATH\nrm -Rf $EXTERNALS_DIR/FTMlib.framework\ncp -Rf $BUILT_PRODUCTS_DIR/FTMlib.framework $EXTERNALS_DIR\n\nmkdir $EXTERNALS_DIR/FTMLib.framework/Resources/java/\n\nif [ -e \"../osx-java/build/$CONFIGURATION/libftmJNILib.jnilib\" ] ; then\n\tcp -f \"../osx-java/build/$CONFIGURATION/libftmJNILib.jnilib\" $EXTERNALS_DIR/FTMLib.framework/Resources/java/\n\ncd $EXTERNALS_DIR/FTMLib.framework/Resources/java/\n\nFTMLIB_FRAMEWORK=`otool -L libftmJNILib.jnilib | grep FTM | awk '{print $1}'`\n\necho \"[patching dynamic library\"\necho \" from '$FTMLIB_FRAMEWORK'\"\necho \" to '@loader_path/../../FTMLib'\"\necho \" in 'libftmJNILib.jnilib']\"\n\ninstall_name_tool -change $FTMLIB_FRAMEWORK '@loader_path/../../FTMLib' libftmJNILib.jnilib\n\nfi\n"; }; 5C132586078C2B510008A86A /* ShellScript */ = { isa = PBXShellScriptBuildPhase; Added: trunk/ftm/externals/max5/ftm.mess.c =================================================================== --- trunk/ftm/externals/max5/ftm.mess.c (rev 0) +++ trunk/ftm/externals/max5/ftm.mess.c 2008-08-21 15:42:09 UTC (rev 1865) @@ -0,0 +1,1635 @@ +/* + * FTM externals + * Copyright (C) 2004 by IRCAM-Centre Georges Pompidou, Paris, France. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * See file COPYING.LIB + for further informations on licensing terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <string.h> + +#ifndef WIN32 +#include <alloca.h> +#else +#include <malloc.h> +#endif + +#include <string.h> + +#include "ftmlib.h" + +#include "ext.h" // standard Max include, always required +#include "ext_obex.h" // required for new style Max object +#include "jpatcher_api.h" +#include "jgraphics.h" + +#define MAX_NUMLINES 128 +#define MAX_NUMCHARS_LINE 1024 + +#define FTMMESS_INVALID -1 +#define FTMMESS_RESET 0 +#define FTMESS_FLASHING 1 +#define FTMMESS_FSIZE(f) ((int)(f&0xFF)) +#define FTMMESS_FINDEX(f) ((int)((f)>>16)) + +static fts_symbol_t sym_ftm_mess = NULL; +static fts_symbol_t sym_restore_line = NULL; +static fts_symbol_t sym_restore_init = NULL; + +static fts_status_description_t not_initialized_description = {"not initialized"}; +static fts_status_t not_initialized_status = ¬_initialized_description; + +typedef struct +{ + fts_symbol_t *ptr; + int alloc; + int size; +} lines_t; + +typedef struct +{ + char *ptr; + int alloc; + int size; +} text_t; + +typedef struct ftmmess +{ + ftmext_t head; + + int loadbang; + enum {trigger_left, trigger_all} trigger; + int untuple; + + int n_inlets; + int n_inlets_next; + int n_dollars; + + fts_array_t args; + fts_array_t args_tail; /* fake array referring to input array for $| */ + fts_array_t *lists; /* array of list inputs */ + fts_hashtable_t privates; + + fts_expression_t *init_expression; + fts_status_t init_parser_status; + fts_status_t init_status; + fts_symbol_t init_sym; + fts_array_t init_args; + fts_array_t *init_lists; + + fts_expression_t *expression; + fts_status_t parser_status; + fts_status_t evaluation_status; /* evaluation status (shows runtime evaluation error) */ + + int changed; /* 1 if text changed after activation */ + int loadlines; + + text_t text; + lines_t lines; + + fts_mutex_t mutex; + + int pressed; + + long inlet; + void **inlets; + void *outlet; + //void *x_qelem; +} ftmmess_t; + +#define ftmmess_get_box(e) ((e)->head.head.head.z_box) + +/*************************************************************** + * + * list input caches + * + */ + +#define DEF_SYM_LIST_INPUT 64 +static int n_sym_lists = 0; +static fts_symbol_t sym_lists[DEF_SYM_LIST_INPUT]; + +static fts_symbol_t +get_lists_symbol_by_index(int i) +{ + if(i >= n_sym_lists) + { + char str[4]; + snprintf(str, 4, "*%d", i + 1); + return fts_new_symbol(str); + } + + return sym_lists[i]; +} + +/************************************************************ + * + * lines + * + */ +#define LINES_BLOCK_SIZE 2 +#define lines_get_ptr(l) ((l)->ptr) +#define lines_get_size(l) ((l)->size) + +static void +lines_init(lines_t *lines) +{ + lines->ptr = NULL; + lines->alloc = 0; + lines->size = 0; +} + +static void +lines_reset(lines_t *lines) +{ + lines->size = 0; +} + +static void +lines_set_size(lines_t *lines, int size) +{ + int alloc = size; + + if(alloc > lines->alloc) + { + while(alloc > lines->alloc) + lines->alloc += LINES_BLOCK_SIZE; + + lines->ptr = (fts_symbol_t *)fts_realloc(lines->ptr, sizeof(fts_symbol_t) * lines->alloc); + } + + lines->size = size; +} + +static void +lines_add_line(lines_t *lines, fts_symbol_t line) +{ + int size = lines->size + 1; + + if(size > lines->alloc) + { + lines->alloc = (size > 2 * lines->alloc)? (2 * size): (2 * lines->alloc); + lines->ptr = (fts_symbol_t *)fts_realloc(lines->ptr, lines->alloc * sizeof(fts_symbol_t)); + } + + lines->ptr[size - 1] = line; + lines->size = size; +} + +static void +lines_set_from_string(lines_t *lines, char *str) +{ + char buf[1024 + 1 + 16]; + int n_par = 0; + int n_token = 0; + int n_sep = 0; + int n_blanks = 0; + int len = 0; + char *line = buf + 8; + char c = 'x'; + enum {c_line, c_sep, c_blank, c_char, c_end} last = c_line; + int i; + + lines->size = 0; + + while(c != '\0') + { + c = *str++; + + if(c == '\r' || c == '\0') + { + /* char is end of line */ + + /* no blanks before new line or end */ + len -= n_blanks; + n_blanks = 0; + + if(last == c_line) + continue; + + if(c == '\r') + last = c_line; + else if(c == '\0') + last = c_end; + } + else if(c == ',' || c == ';') + { + /* char is separator */ + + /* no blanks before separator */ + len -= n_blanks; + n_blanks = 0; + + if(n_token == 0) + continue; + + last = c_sep; + } + else if(c == ' ' || c == '\t') + { + /* char is blank */ + line[len++] = ' '; + + if(last == c_char) + last = c_blank; + + n_blanks++; + + continue; + } + else + { + /* char is token */ + if(last != c_char) + n_token++; + + if (c == ')' && n_par > -8) + n_par--; + else if(c == '(' && n_par < 8) + n_par++; + + line[len++] = c; + last = c_char; + + n_blanks = 0; + + continue; + } + + /* avoid accidental emtpy lines at the end */ + if(last == c_line && str[0] == '\0') + { + c = '\0'; + last = c_end; + } + + /* fix last character */ + if(last == c_end && len > 0) + { + while(line[len-1] == ' '|| line[len-1] == '\r'|| line[len-1] == '\t' || line[len-1] == ',') + len--; + + last = c_end; + } + + /* fix parentheses */ + if(n_par < 0 && (last == c_sep || last == c_line || last == c_end)) + { + if(line[0] != ' ' && n_sep == 0) + { + for(i=0; i<-n_par; i++) + { + /* prepend parentheses */ + line--; + line[0] = '('; + len++; + } + } + + n_par = 0; + } + else if(n_par > 0 && (last == c_sep || last == c_end)) + { + for(i=0; i<n_par; i++) + line[len++] = ')'; + + n_par = 0; + } + + if(last == c_sep) + { + /* expression separator */ + n_sep++; /* count separators */ + n_token = 0; /* restart counting tokens */ + line[len++] = c; + } + else if(last == c_line || last == c_end) + { + if(len > 0) + { + if(len > 1024) + len = 1024; + + line[len] = '\0'; + + lines_add_line(lines, fts_new_symbol(line)); + } + + /* reset line */ + line = buf + 8; + len = 0; + } + } +} + +static void +lines_destroy(lines_t *lines) +{ + fts_free(lines->ptr); +} + +/******************************************************************** + * + * text + * + */ +#define TEXT_BLOCK_SIZE 256 +#define text_get_ptr(t) ((t)->ptr) +#define text_get_size(t) ((t)->size) + +static void +text_init(text_t *text) +{ + text->ptr = NULL; + text->alloc = 0; + text->size = 0; +} + +static void +text_reset(text_t *text) +{ + text->size = 0; +} + +static void +text_set_size(text_t *text, int size) +{ + int alloc = size + 1; + + if(alloc > text->alloc) + { + while(alloc > text->alloc) + text->alloc += TEXT_BLOCK_SIZE; + + text->ptr = (char *)fts_realloc(text->ptr, sizeof(char) * text->alloc); + } + + text->ptr[size] = '\0'; + text->size = size; +} + +static void +text_append_char(text_t *text, char c) +{ + int size = text->size; + + text_set_size(text, size + 1); + + text->ptr[size] = c; +} + +static void +text_append_string(text_t *text, const char *str) +{ + if(str != NULL) + { + int n = strlen(str); + int size = text->size; + + text_set_size(text, size + n); + strcpy(text->ptr + size, str); + } +} + +static void +text_append_lines(text_t *text, lines_t *lines) +{ + fts_symbol_t *syms = lines_get_ptr(lines); + int n = lines_get_size(lines); + + if(n > 0) + { + int i; + + text_append_string(text, fts_symbol_name(syms[0])); + + for(i=1; i<n; i++) + { + text_append_char(text, '\r'); + text_append_string(text, fts_symbol_name(syms[i])); + } + text_append_char(text, '\r'); + } +} + +static void +text_destroy(text_t *text) +{ + fts_free(text->ptr); +} + +/******************************************************** + * + * FTM Max/MSP message sending + * + */ +static void +outlet_atom(void *outlet, fts_atom_t *a) +{ + if(fts_is_int(a)) + outlet_int(outlet, fts_get_int(a)); + else if(fts_is_float(a)) + outlet_float(outlet, fts_get_float(a)); + else if(fts_is_symbol(a)) + outlet_anything(outlet, fts_get_symbol(a), 0, NULL); + else if(fts_is_object(a)) + outlet_anything(outlet, ftm_sym_obj, 1, a); +} + +static int +send_to_named(fts_symbol_t dest, int ac, const fts_atom_t *at) +{ + void *thing = dest->s_thing; + + if(thing != NULL) + { + if(ac > 0 && fts_is_symbol(at)) + { + fts_symbol_t s = fts_get_symbol(at); + return (typedmess(thing, s, ac - 1, (fts_atom_t *)at + 1) != NULL); + } + else + return (typedmess(thing, fts_s_list, ac, (fts_atom_t *)at) != NULL); + } + + return 0; +} + +static fts_status_t +expression_callback(int ac, const fts_atom_t *at, const fts_atom_t *dest, void *o) +{ + ftmmess_t *self = (ftmmess_t *)o; + int out = 0; + + if(fts_is_void(dest)) + out = 1; + if(fts_is_int(dest)) + out = fts_get_int(dest); + else if(fts_is_object(dest)) + { + fts_object_t *target = fts_get_object(dest); + + if(ac > 0 && fts_is_symbol(at)) + { + fts_symbol_t selector = fts_get_symbol(at); + + /* leave critical section for sending message */ + fts_mutex_unlock(&self->mutex); + fts_send_message(target, selector, ac - 1, at + 1, fts_nix); + fts_mutex_lock(&self->mutex); + + return fts_ok; + } + } + + if(out == 1) + { + if(self->untuple != 0 && ac == 1 && fts_is_tuple(at)) + { + fts_tuple_t *tuple = (fts_tuple_t *)fts_get_object(at); + ac = fts_tuple_get_size(tuple); + at = fts_tuple_get_atoms(tuple); + } + + if(ac > 0) + { + /* leave critical section for callback */ + fts_mutex_unlock(&self->mutex); + + if (fts_is_symbol(at)) + outlet_anything(self->outlet, fts_get_symbol(at), ac - 1, (fts_atom_t *)at + 1); + else if(ac == 1) + outlet_atom(self->outlet, (fts_atom_t *)at); + else + outlet_list(self->outlet, NULL, ac, (fts_atom_t *)at); + + /* re-enter critical section for evaluation of next term */ + fts_mutex_lock(&self->mutex); + } + } + else if(fts_is_symbol(dest)) + { + fts_symbol_t name = fts_get_symbol(dest); + + /* leave critical section for sending message */ + fts_mutex_unlock(&self->mutex); + send_to_named(name, ac, at); + fts_mutex_lock(&self->mutex); + } + else + ftmext_error((ftmext_t *)self, "multiple outlets not yet implemented"); + + return fts_ok; +} + + +static void +expression_eval(ftmmess_t *self) +{ + if(self->parser_status == fts_ok) + { + int n = fts_array_get_size(&self->args); + fts_atom_t *values = fts_array_get_atoms(&self->args); + fts_patcher_t *scope = ftmext_get_scope((ftmext_t *)self); + fts_status_t status; + + fts_expression_set_privates(self->expression, &self->privates); + status = fts_expression_reduce(self->expression, scope, n, values, expression_callback, (void *)self); + + if(status != fts_ok && status != fts_ignore) + { + ftmext_error((ftmext_t *)self, "%s in \"%s\"", fts_status_get_description(status), self->text.ptr); + self->evaluation_status = status; + } + else + self->evaluation_status = fts_ok; + } + else if(self->parser_status != fts_ok) + ftmext_error((ftmext_t *)self, "invalid expression: %s", fts_status_get_description(self->parser_status)); +} + +static void +ftmmess_bang(ftmmess_t *self) +{ + fts_mutex_lock(&self->mutex); + expression_eval(self); + fts_mutex_unlock(&self->mutex); +} + +static void +ftmmess_loadbang(ftmmess_t *self) +{ + if(self->loadbang) + { + fts_mutex_lock(&self->mutex); + expression_eval(self); + fts_mutex_unlock(&self->mutex); + } +} + +static void +ftmmess_reset(ftmmess_t *self) +{ + lines_reset(&self->lines); + text_reset(&self->text); + + fts_expression_set(self->expression, 0, NULL); + self->parser_status = fts_ok; +} + +/******************************************************************** + * + * persistence + * + */ +static fts_symbol_t +symbol_add_leading_underscore(fts_symbol_t sym) +{ + char *str = (char *)fts_symbol_name(sym); + + if(str[0] != '_') + { + int len = strlen(str); + char *buf = (char *)alloca(sizeof(char) * (len + 2)); + + buf[0] = '_'; + strcpy(buf + 1, str); + + return fts_new_symbol(buf); + } + + return sym; +} + +static fts_symbol_t +symbol_remove_leading_underscore(fts_symbol_t sym) +{ + char *str = (char *)fts_symbol_name(sym); + + if(str[0] == '_') + return fts_new_symbol(str + 1); + + return sym; +} + +static void +ftmmess_save(ftmmess_t *self, void *binbuf) +{ + int n_lines = lines_get_size(&self->lines); + fts_symbol_t *lines = lines_get_ptr(&self->lines); + fts_atom_t a[21]; + short i; + + /* + fts_set_int(a + 2, r.left); + fts_set_int(a + 3, r.top); + fts_set_int(a + 4, r.right - r.left); + fts_set_int(a + 5, r.bottom - r.top); + fts_set_int(a + 6, self->font); + fts_set_int(a + 7, self->fsize); + fts_set_int(a + 8, self->backColor.red / 257); + fts_set_int(a + 9, self->backColor.green / 257); + fts_set_int(a + 10, self->backColor.blue / 257); + fts_set_int(a + 11, self->foreColor.red / 257); + fts_set_int(a + 12, self->foreColor.green / 257); + fts_set_int(a + 13, self->foreColor.blue / 257); + fts_set_int(a + 14, n_lines); + fts_set_int(a + 15, self->n_inlets_next); + fts_set_int(a + 16, self->trigger); + fts_set_int(a + 17, self->loadbang); + fts_set_int(a + 18, self->untuple); + */ + + /* add here if anything */ + //fts_set_symbol(a + 19, maxext_sym_arrow_right); + //fts_set_int(a + 20, scope_depth); + //binbuf_insert(binbuf, 0, 21, a); + + maxext_save_begin((ftmext_t *)self, binbuf); + + if(self->init_sym != NULL) + { + fts_set_symbol(a, maxext_sym_hash_T); + fts_set_symbol(a + 1, sym_restore_init); + fts_set_symbol(a + 2, symbol_add_leading_underscore(self->init_sym)); + binbuf_insert(binbuf, 0, 3, a); + } + + for(i=0; i<n_lines; i++) + { + fts_set_symbol(a, maxext_sym_hash_T); + fts_set_symbol(a + 1, sym_restore_line); + fts_set_symbol(a + 2, symbol_add_leading_underscore(lines[i])); + binbuf_insert(binbuf, 0, 3, a); + } + + maxext_save_end((ftmext_t *)self); +} + +static void +ftmmess_pstate(ftmmess_t *self, void *binbuf) +{ + fts_atom_t a[12]; + + fts_set_symbol(a, sym_ftm_mess); + //fts_set_int(a + 1, self->backColor.red / 257); /* rgb colors in 0 - 65535 */ + //fts_set_int(a + 2, self->backColor.green / 257); + //fts_set_int(a + 3, self->backColor.blue / 257); + //fts_set_int(a + 4, self->foreColor.red / 257); + //fts_set_int(a + 5, self->foreColor.green / 257); + //fts_set_int(a + 6, self->foreColor.blue / 257); + fts_set_int(a + 7, self->n_inlets_next); + fts_set_int(a + 8, self->trigger); + fts_set_int(a + 9, self->loadbang); + fts_set_int(a + 10, self->untuple); + + if(self->init_sym == NULL) + binbuf_insert(binbuf, 0, 11, a); + else + { + fts_set_symbol(a + 11, self->init_sym); + fts_set_int(a + 12, self->init_status == fts_ok); + binbuf_insert(binbuf, 0, 13, a); + } +} + +/******************************************************************** + * + * user methods + * + */ + +static void +ftmmess_anything(ftmmess_t *self, fts_symbol_t s, int ac, fts_atom_t *at) +{ + int inlet = proxy_getinlet((t_object *)self); + int i; + + fts_mutex_lock(&self->mutex); + + if(s == NULL) + { + fts_array_set(self->lists + inlet, ac, at); + + for(i=0; i<ac; i++) + fts_array_set_element(&self->args, inlet + i, at + i); + } + else + { + fts_atom_t a; + + fts_set_symbol(&a, s); + fts_array_set(self->lists + inlet, 1, &a); + fts_array_append(self->lists + inlet, ac, at); + + fts_array_set_element(&self->args, inlet, &a); + + for(i=0; i<ac; i++) + fts_array_set_element(&self->args, inlet + 1 + i, at + i); + } + + /* update fake array for $| */ + if(self->args.size > 1) + { + self->args_tail.atoms = self->args.atoms + 1; + self->args_tail.size = self->args.size - 1; + } + else + { + self->args_tail.atoms = NULL; + self->args_tail.size = 0; + } + + if(inlet == 0 || self->trigger == trigger_all) + expression_eval(self); + + fts_array_set_size(&self->args, self->n_inlets); + + fts_mutex_unlock(&self->mutex); +} + +static void +ftmmess_object(ftmmess_t *self, fts_symbol_t s, int ac, fts_atom_t *at) +{ + ftmmess_anything(self, NULL, 1, at); +} + +static void +ftmmess_list(ftmmess_t *self, fts_symbol_t s, int ac, fts_atom_t *at) +{ + ftmmess_anything(self, NULL, ac, at); +} + +static void +ftmmess_float(ftmmess_t *self, double f) +{ + fts_atom_t a; + + fts_set_float(&a, f); + ftmmess_anything(self, NULL, 1, &a); +} + +static void +ftmmess_int(ftmmess_t *self, int i) +{ + fts_atom_t a; + + fts_set_int(&a, i); + ftmmess_anything(self, NULL, 1, &a); +} + +static void +ftmmess_assist(ftmmess_t *self, void *box, long msg, long arg, char *dstString) +{ + if(self->parser_status == fts_ok && self->init_status == fts_ok) + { + if(msg == ASSIST_INLET) + { + if(arg == 0) + sprintf(dstString, "ftm.mess: set $1, evaluate and output"); + else if(self->trigger == trigger_left) + sprintf(dstString, "ftm.mess: set $%d", arg + 1); + else + sprintf(dstString, "ftm.mess: set $%d, evaluate and output", arg + 1); + } + else if(msg == ASSIST_OUTLET) + { + if(self->trigger == trigger_left) + sprintf(dstString, "ftm.mess: message evaluation result (left inlet triggers)"); + else + sprintf(dstString, "ftm.mess: message evaluation result (all inlets trigger)"); + } + } + else if(self->parser_status != fts_ok) + sprintf(dstString, "ftm.mess: %s", fts_status_get_description(self->parser_status)); + else if(self->init_status != fts_ok) + sprintf(dstString, "ftm.mess: init: %s", fts_status_get_description(self->init_status)); +} + +/************************************************************ + * + * expression + * + */ +static int +count_dollars(char *str) +{ + int max_index = 0; + int len = strlen(str); + int dollar = 0; + int index = 0; + int j; + + for(j=0; j<len; j++) + { + char c = str[j]; + + if(c == '$') + { + index = 0; + dollar = 1; + + /* get "$" or "$*" */ + if(j < len - 1 && str[j + 1] == '*') + j++; + } + else if(c >= '0' && c <= '9' && dollar != 0) + { + index *= 10; + index += (c - '0'); + } + else + dollar = 0; + + if(index > max_index) + max_index = index; + } + + return max_index; +} + +static fts_symbol_t +get_list_symbol_by_index(int i) +{ + if(i >= n_sym_lists) + { + char str[4]; + snprintf(str, 4, "*%d", i + 1); + return fts_new_symbol(str); + } + + return sym_lists[i]; +} + +static int +get_list_index(fts_symbol_t sym) +{ + char *str = fts_symbol_name(sym); + int idx = -1; + + if(str[0] == '*') + { + int i = 1; + + idx = 0; + + while(str[i] != '\0' && str[i] >= '0' && str[i] <= '9') + { + idx *= 10; + idx += str[i] - '0'; + i++; + } + } + + return idx - 1; +} + +static void +init_input(ftmmess_t *self) +{ + fts_atom_t *init_args = fts_array_get_atoms(&self->init_args); + int n_init_args = fts_array_get_size(&self->init_args); + int n_inlets = self->n_inlets; + fts_atom_t k, v; + fts_atom_t *a; + int i; + + if(n_init_args > n_inlets) + n_init_args = n_inlets; + + /* init inputs */ + fts_array_set(&self->args, n_init_args, init_args); + fts_array_set_size(&self->args, n_inlets); + a = fts_array_get_atoms(&self->args); + + /* set uninitialized values to zero */ + for(i=n_init_args; i<n_inlets; i++) + fts_set_int(a + i, 0); + + /* initialize all input private $* */ + fts_set_symbol(&k, fts_s_times); + fts_set_pointer(&v, &self->args); + fts_hashtable_put(&self->privates, &k, &v); + + /* initialize list tail input private $| */ + fts_set_symbol(&k, fts_s_bit_or); + fts_set_pointer(&v, &self->args_tail); + fts_hashtable_put(&self->privates, &k, &v); + + /* initialize list input privates: $*1, $*2, $*3, etc. */ + for(i=0; i<self->n_inlets; i++) + { + fts_array_copy(self->init_lists + i, self->lists + i); + fts_set_symbol(&k, get_list_symbol_by_index(i)); + fts_set_pointer(&v, self->lists + i); + fts_hashtable_put(&self->privates, &k, &v); + } +} + +static fts_status_t +init_input_callback(int ac, const fts_atom_t *at, const fts_atom_t *dest, void *data) +{ + ftmmess_t *self = (ftmmess_t *)data; + + if(ac > 2 && fts_is_symbol(at) && fts_is_symbol(at + 1) && fts_get_symbol(at + 1) == fts_s_equal) + { + fts_symbol_t sym = fts_get_symbol(at); + char idx = get_list_index(sym); + + if(sym == fts_s_times) + fts_array_set(&self->init_args, ac - 2, at + 2); + else if(sym == fts_s_power) + { + int i; + + for(i=0; i<self->n_inlets; i++) + fts_array_set(self->init_lists + i, ac - 2, at + 2); + } + else if(idx >= 0) + { + if(idx < self->n_inlets) + fts_array_set(self->init_lists + idx, ac - 2, at + 2); + } + else if(idx == -1) + return fts_status_format("invalid list identifier '%s'", fts_symbol_name(sym)); + else + fts_hashtable_put(&self->privates, at, at + 2); + } + else + fts_array_set(&self->init_args, ac, at); + + return fts_ok; +} + +static void +init_input_evaluate(ftmmess_t *self) +{ + fts_patcher_t *scope = ftmext_get_scope((ftmext_t *)self); + int i; + + /* clear init arguments */ + fts_array_clear(&self->init_args); + + /* clear init lists */ + for(i=0; i<self->n_inlets; i++) + fts_array_clear(self->init_lists + i); + + /* clear privates */ + fts_hashtable_clear(&self->privates); + + self->init_status = self->init_parser_status; + + if(self->init_status == fts_ok && scope != NULL) + self->init_status = fts_expression_reduce(self->init_expression, scope, 0, NULL, init_input_callback, (void *)self); + + init_input(self); +} + +static void +init_input_name_callback(void *listener, fts_symbol_t name) +{ + ftmmess_t *self = (ftmmess_t *)listener; + + init_input_evaluate(self); + + //qelem_set(self->x_qelem); +} + +static void +ftmmess_parse_expression(ftmmess_t *self) +{ + int n = lines_get_size(&self->lines); + + if(n > 0) + { + char *str; + int size; + char *buff; + fts_array_t token; + fts_tokenizer_t tokenizer; + fts_atom_t a; + + /* set text from lines */ + text_set_size(&self->text, 0); + text_append_lines(&self->text, &self->lines); + + /* copy text to buffer */ + str = text_get_ptr(&self->text); + size = text_get_size(&self->text); + buff = (char *)alloca(sizeof(char) * (size + 2)); + strcpy(buff, str); + buff[size] = '\0'; + buff[size + 1] = '\0'; /* tokenizer needs double null termination */ + + /* run tokenizer */ + fts_tokenizer_init_buffer(&tokenizer, buff, size + 2); + + fts_array_init(&token, 0, NULL); + while(fts_tokenizer_next(&tokenizer, &a) != 0) + fts_array_append(&token, 1, &a); + + fts_tokenizer_destroy(&tokenizer); + + /* run parser */ + self->parser_status = fts_expression_set(self->expression, fts_array_get_size(&token), fts_array_get_atoms(&token)); + + if(self->parser_status == fts_ok) + { + int n_dollars = count_dollars(str); + + if(n_dollars > 2) + self->n_inlets_next = n_dollars; + else + self->n_inlets_next = 2; + + self->n_dollars = n_dollars; + + init_input(self); + } + } +} + +/******************************************************************** + * + * methods + * + */ +static void +ftmmess_set_init(ftmmess_t *self, fts_symbol_t s, short ac, fts_atom_t *at) +{ + fts_patcher_t *scope = ftmext_get_scope((ftmext_t *)self); + + if(ac > 0 && fts_is_symbol(at) && fts_get_symbol(at) == fts_s_none) + { + ac = 0; + at = NULL; + } + + self->init_parser_status = fts_expression_parse_from_atoms(self->init_expression, ac, at, &self->init_sym); + fts_expression_add_listener(self->init_expression, scope, self, init_input_name_callback); + + init_input_evaluate(self); + + //qelem_set(self->x_qelem); +} + +static void +ftmmess_restore_line(t_object *o, fts_symbol_t s, short ac, fts_atom_t *at) +{ + ftmmess_t *self = (ftmmess_t *) o; + + if(ac > 0 && fts_is_symbol(at)) + { + fts_symbol_t sym = fts_get_symbol(at); + char str[1024]; + + /* Max/MSP hack to avoid wild #-lead absargs replacement */ + sym = symbol_remove_leading_underscore(sym); + + /* replace #-lead absargs properly */ + if(maxext_loader_string_replace_absargs((ftmext_t *)self, fts_symbol_name(sym), str, 1024) > 0) + sym = fts_new_symbol(str); + + lines_add_line(&self->lines, sym); + self->loadlines--; + + if(self->loadlines == 0) + ftmmess_parse_expression(self); + } +} + +static void +ftmmess_restore_init(t_object *o, fts_symbol_t s, short ac, fts_atom_t *at) +{ + ftmmess_t *self = (ftmmess_t *) o; + + if(ac > 0 && fts_is_symbol(at)) + { + fts_symbol_t sym = fts_get_symbol(at); + fts_atom_t a; + char str[1024]; + + /* Max/MSP hack to avoid wild #-lead absargs replacement */ + sym = symbol_remove_leading_underscore(sym); + + /* replace #-lead absargs properly */ + if(maxext_loader_string_replace_absargs((ftmext_t *)self, fts_symbol_name(sym), str, 1024) > 0) + sym = fts_new_symbol(str); + + fts_set_symbol(&a, sym); + ftmmess_set_init(self, NULL, 1, &a); + } +} + +static void +ftmmess_redefine(ftmmess_t *self) +{ + fts_patcher_t *scope = ftmext_get_scope((ftmext_t *)self); + + self->init_status = self->init_parser_status; + + /* re-evaluate init arg expression when scope is available */ + if(self->init_status == fts_ok && scope != NULL) + self->init_status = fts_expression_reduce(self->init_expression, scope, 0, NULL, init_input_callback, (void *)self); + + init_input(self); +} + +static char * +string_from_list(fts_memorystream_t *stream, int ac, fts_atom_t *at) +{ + char *str = NULL; + + if(ac == 1 && fts_is_symbol(at)) + str = fts_symbol_name(fts_get_symbol(at)); + else + { + fts_memorystream_reset(stream); + fts_spost_primitive_atoms((fts_bytestream_t *)stream, ac, at); + fts_bytestream_output_char((fts_bytestream_t *)stream, '\0'); + str = (char *)fts_memorystream_get_bytes(stream); + } + + return str; +} + +static void +ftmmess_set_expression(t_object *o, fts_symbol_t s, short ac, fts_atom_t *at) +{ + ftmmess_t *self = (ftmmess_t *)o; + + if(ac > 0) + { + static fts_memorystream_t *memory_stream = NULL; + char *str; + int len; + + if(memory_stream == NULL) + memory_stream = (fts_memorystream_t *)fts_object_create( fts_memorystream_class, 0, 0); + + str = string_from_list(memory_stream, ac, at); + len = strlen(str); + + if(len > 0) + { + lines_set_from_string(&self->lines, str); + ftmmess_parse_expression(self); + } + else + { + lines_reset(&self->lines); + ftmmess_reset(self); + } + + //patcher_dirty(self->patcher); + //fitToText(self); + //qelem_set(self->x_qelem); + } +} + +static void +ftmmess_set_inlets(t_object *o, long i) +{ + ftmmess_t *self = (ftmmess_t *)o; + + if(i < 2) + self->n_inlets_next = 2; + else + self->n_inlets_next = i; +} + +static void +ftmmess_set_trigger(t_object *o, long i) +{ + ftmmess_t *self = (ftmmess_t *)o; + + self->trigger = i; +} + +static void +ftmmess_set_loadbang(t_object *o, long i) +{ + ftmmess_t *self = (ftmmess_t *)o; + + self->loadbang = (i != 0); +} + +static void +ftmmess_set_untuple(t_object *o, long i) +{ + ftmmess_t *self = (ftmmess_t *)o; + + self->untuple = (i != 0); +} + +static void +ftmmess_paint(ftmmess_t *self, t_object *view) +{ + if(self->text.ptr != NULL) + { + t_jgraphics *g = (t_jgraphics*) patcherview_get_jgraphics(view); + t_jfont *jf = jfont_create(jbox_get_fontname((t_object *)self)->s_name, jbox_get_font_slant((t_object *)self), jbox_get_font_weight((t_object *)self), jbox_get_fontsize((t_object *)self)); + t_jtextlayout *jtl = jtextlayout_create(); + t_jrgba textcolor; + t_rect rect; + int onset = 2; + + jbox_get_rect_for_view((t_object *)self, view, &rect); + + if(self->pressed == 1) + onset = 3; + + jtextlayout_set(jtl, self->text.ptr, jf, onset, onset, rect.width - 4, rect.height - 4, JGRAPHICS_TEXT_JUSTIFICATION_LEFT, 0); + + textcolor.red = textcolor.green = textcolor.blue = 0; + object_attr_getcolor((t_object *)self, gensym("textcolor"), &textcolor); + + textcolor.alpha = 1; + jtextlayout_settextcolor(jtl, &textcolor); + jtextlayout_draw(jtl, g); + + jtextlayout_destroy(jtl); + jfont_destroy(jf); + } +} + +void +ftmmess_getdrawparams(ftmmess_t *self, t_object *patcherview, t_jboxdrawparams *params) +{ + if(self->pressed == 0) + { + params->d_boxfillcolor.red = 0.5; + params->d_boxfillcolor.green = 0.5; + params->d_boxfillcolor.blue = 0.5; + params->d_boxfillcolor.alpha = 0.2; + + params->d_bordercolor.red = 0.5; + params->d_bordercolor.green = 0.5; + params->d_bordercolor.blue = 0.5; + params->d_bordercolor.alpha = 0.0; + + params->d_borderthickness = 0.5; + } + else + { + params->d_boxfillcolor.red = 0.3; + params->d_boxfillcolor.green = 0.3; + params->d_boxfillcolor.blue = 0.3; + params->d_boxfillcolor.alpha = 0.3; + + params->d_bordercolor.red = 0.5; + params->d_bordercolor.green = 0.5; + params->d_bordercolor.blue = 0.5; + params->d_bordercolor.alpha = 0.0; + + params->d_borderthickness = 0.5; + } + + params->d_cornersize = 10.0; +} + +/******************************************************************* + * + * interaction + * + */ +static void +ftmmess_mousedown(ftmmess_t *self, t_object *patcherview, t_pt pt, long modifiers) +{ + ftmmess_bang(self); + self->pressed = 1; + jbox_redraw((t_jbox *)self); +} + +static void +ftmmess_mouseup(ftmmess_t *self, t_object *patcherview, t_pt pt, long modifiers) +{ + self->pressed = 0; + jbox_redraw((t_jbox *)self); +} + +static void +ftmmess_invis(ftmmess_t *self) +{ +} + +static void +ftmmess_vis(ftmmess_t *self) +{ +} + +/******************************************************************** + * + * class + * + */ +static t_max_err +ftmmess_stdargs(t_dictionary *d, t_symbol *s, long ac, t_atom *at) +{ + if(d != NULL) + { + if(ac > 3 && fts_is_int(at) && fts_is_int(at + 1) && fts_is_int(at + 2) && fts_is_int(at + 3)) + dictionary_appendatoms(d, gensym("patching_rect"), 4, at); + + if(ac > 5 && fts_is_int(at + 4) && fts_is_int(at + 5)) + { + int old_fontidx = fts_get_int(at + 4); + int old_fontsize = fts_get_int(at + 5); + t_symbol *fontname = fontinfo_getname((short)old_fontidx); + double fontsize = fontinfo_getsize(old_fontsize); + + dictionary_appendsym(d, gensym("fontname"), fontname); + dictionary_appendfloat(d, gensym("fontsize"), fontsize); + } + + if(ac > 8 && fts_is_number(at + 6) && fts_is_number(at + 7) && fts_is_number(at + 8)) + { + t_jrgba color; + + color.red = fts_get_number_int(at + 8) / 255.0; + color.green = fts_get_number_int(at + 9) / 255.0; + color.blue = fts_get_number_int(at + 10) / 255.0; + color.alpha = 1.0; + + dictionary_appendjrgba(d, gensym("color"), &color); + } + + if(ac > 11 && fts_is_number(at + 9) && fts_is_number(at + 10) && fts_is_number(at + 11)) + { + t_jrgba color; + + color.red = fts_get_number_int(at + 8) / 255.0; + color.green = fts_get_number_int(at + 9) / 255.0; + color.blue = fts_get_number_int(at + 10) / 255.0; + color.alpha = 1.0; + + dictionary_appendjrgba(d, gensym("textcolor"), &color); + } + + if(ac > 12 && fts_is_int(at + 12)) + dictionary_appendatom(d, gensym("numlines"), at + 12); + + if(ac > 13 && fts_is_int(at + 13)) + dictionary_appendatom(d, gensym("numinlets"), at + 13); + + if(ac > 14 && fts_is_int(at + 14)) + dictionary_appendatom(d, gensym("trigger"), at + 14); + + if(ac > 15 && fts_is_int(at + 15)) + dictionary_appendatom(d, gensym("loadbang"), at + 15); + + if(ac > 16 && fts_is_int(at + 16)) + dictionary_appendatom(d, gensym("untuple"), at + 16); + } + + return MAX_ERR_NONE; +} + +static void * +ftmmess_new(t_symbol *name, short ac, t_atom *at) +{ + t_dictionary *d = object_dictionaryarg(ac, at); + ftmmess_t *self = NULL; + + if (d != NULL) + { + t_object *patcher = maxext_sym_hash_P->s_thing; + ftmext_class_t *cl = ftmext_class_get_by_name(name); + long flags; + int i; + + self = (ftmmess_t *)object_alloc(cl->handle); + + maxext_init_raw((ftmext_t *)self, cl, patcher); + + fts_mutex_init(&self->mutex); + + self->loadbang = 0; + self->loadlines = 0; + self->n_inlets = 2; + self->n_inlets_next = 2; + self->trigger = trigger_left; + self->untuple = 0; + self->parser_status = fts_ok; + + self->lists = NULL; + self->init_lists = NULL; + + self->loadlines = 0; + + /* init expression stuff */ + text_init(&self->text); + text_set_size(&self->text, 0); + lines_init(&self->lines); + fts_expression_new( 0, 0, &self->expression); + lines_set_size(&self->lines, 0); + + self->init_sym = NULL; + fts_expression_new(0, NULL, &self->init_expression); + fts_array_init(&self->init_args, 0, NULL); + fts_expression_new(0, NULL, &self->init_expression); + self->init_status = fts_ok; + self->init_parser_status = fts_ok; + self->evaluation_status = not_initialized_status; + + fts_hashtable_init(&self->privates, FTS_HASHTABLE_MEDIUM); + + self->n_dollars = 0; + fts_array_init(&self->args, 0, NULL); + + dictionary_getlong(d, gensym("numlines"), (long *)&self->loadlines); + dictionary_getlong(d, gensym("numinlets"), (long *)&self->n_inlets); + + if(self->n_inlets < 2) + self->n_inlets = 2; + + self->n_inlets_next = self->n_inlets; + + self->lists = (fts_array_t *)fts_malloc(self->n_inlets * sizeof(fts_array_t)); + for(i=0; i<self->n_inlets; i++) + fts_array_init(self->lists + i, 0, NULL); + + self->init_lists = (fts_array_t *)fts_malloc(self->n_inlets * sizeof(fts_array_t)); + for(i=0; i<self->n_inlets; i++) + fts_array_init(self->init_lists + i, 0, NULL); + + dictionary_getlong(d, gensym("trigger"), (long *)&self->trigger); + dictionary_getlong(d, gensym("loadbang"), (long *)&self->loadbang); + dictionary_getlong(d, gensym("untuple"), (long *)&self->untuple); + + /* init fake array for $| */ + self->args_tail = self->args; + + /* graphics */ + self->pressed = 0; + + flags = 0 + | JBOX_DRAWFIRSTIN + // | JBOX_NODRAWBOX + | JBOX_DRAWINLAST + | JBOX_TRANSPARENT + // | JBOX_NOGROW + // | JBOX_GROWY + | JBOX_GROWBOTH + // | JBOX_HILITE + // | JBOX_BACKGROUND + | JBOX_DRAWBACKGROUND + // | JBOX_NOFLOATINSPECTOR + // | JBOX_TEXTFIELD + // | JBOX_MOUSEDRAGDELTA + // | JBOX_TEXTFIELD + ; + + jbox_new((t_jbox *)self, flags, ac, at); + ((t_jbox *)self)->b_firstin = (t_object *)self; + + self->inlets = (void **)fts_malloc(sizeof(void *) * (self->n_inlets - 1)); + + for(i=self->n_inlets-2; i>=0; i--) + self->inlets[i] = proxy_new(self, i + 1, &self->inlet); + + self->outlet = outlet_new((t_object *)self, NULL); + + attr_dictionary_process(self, d); + jbox_ready((t_jbox *)self); + + maxext_sym_hash_T->s_thing = (t_object *)self; + } + + return self; +} + +static void +ftmmess_free(ftmmess_t *self) +{ + int i; + + //qelem_free(self->x_qelem); + + fts_name_listener_remove_bindings(self); + + fts_array_destroy(&self->init_args); + fts_hashtable_destroy(&self->privates); + + fts_array_destroy(&self->args); + + if(self->lists != NULL) + { + for(i=0; i<self->n_inlets; i++) + fts_array_destroy(self->lists + i); + + fts_free(self->lists); + } + + if(self->init_lists != NULL) + { + for(i=0; i<self->n_inlets; i++) + fts_array_destroy(self->init_lists + i); + + fts_free(self->init_lists); + } + + text_destroy(&self->text); + lines_destroy(&self->lines); + + fts_expression_delete(self->expression); + fts_expression_delete(self->init_expression); + + for(i=0; i<self->n_inlets-1; i++) + freeobject(self->inlets[i]); + + fts_free(self->inlets); + + maxext_delete((ftmext_t *)self); + fts_mutex_destroy(&self->mutex); + + jbox_free((t_jbox *)self); +} + +int +main(void) +{ + if(ftmlib_init(FTM_VERSION_MAJOR, FTM_VERSION_MINOR)) + { + t_class *c = class_new("ftm.mess", (method)ftmmess_new, (method)ftmmess_free, sizeof(ftmmess_t), NULL, A_GIMME, 0); + ftmext_class_t *ftmmess_class = NULL; + int i; + + c->c_flags |= CLASS_FLAG_NEWDICTIONARY; + jbox_initclass(c, JBOX_COLOR | JBOX_FIXWIDTH | JBOX_FONTATTR); + + sym_ftm_mess = fts_new_symbol("ftm.mess"); + + sym_restore_line = fts_new_symbol("_#line"); + sym_restore_init = fts_new_symbol("_#init"); + + for(i=0; i<DEF_SYM_LIST_INPUT; i++) + sym_lists[i] = get_lists_symbol_by_index(i); + + n_sym_lists = DEF_SYM_LIST_INPUT; + + class_addmethod(c, (method)ftmmess_bang, "bang", 0); + class_addmethod(c, (method)ftmmess_loadbang, "loadbang", A_CANT, 0); + + class_addmethod(c, (method)ftmmess_stdargs, "stdargs", A_CANT, 0); + class_addmethod(c, (method)ftmmess_save, "save", A_CANT, 0); + + class_addmethod(c, (method)ftmmess_paint, "paint", A_CANT, 0); + class_addmethod(c, (method)ftmmess_getdrawparams, "getdrawparams", A_CANT, 0); + class_addmethod(c, (method)ftmmess_mousedown, "mousedown", A_CANT, 0); + class_addmethod(c, (method)ftmmess_mouseup, "mouseup", A_CANT, 0); + + /* persistence & loadbang */ + class_addmethod(c, (method)ftmmess_restore_line, "_#line", A_GIMME, 0); + class_addmethod(c, (method)ftmmess_restore_init, "_#init", A_GIMME, 0); + class_addmethod(c, (method)ftmmess_redefine, ftm_str_redefine, 0); + class_addmethod(c, (method)maxext_restore_ftm, maxext_str_restore_ftm, A_GIMME, 0); + class... [truncated message content] |