example projects

This commit is contained in:
redlock 2011-03-04 00:56:33 +01:00
parent 06b87d2fab
commit 9f92360b1b
106 changed files with 8484 additions and 0 deletions

View File

@ -0,0 +1,3 @@
require "LICK/lick"

View File

@ -0,0 +1,742 @@
x11_color_table = {
-- taken from the SuperCollider Color documentation:
["alice blue"]={240, 248, 255},
["AliceBlue"]={240, 248, 255},
["antique white"]={250, 235, 215},
["AntiqueWhite"]={250, 235, 215},
["AntiqueWhite1"]={255, 239, 219},
["AntiqueWhite2"]={238, 223, 204},
["AntiqueWhite3"]={205, 192, 176},
["AntiqueWhite4"]={139, 131, 120},
["aquamarine"]={127, 255, 212},
["aquamarine1"]={127, 255, 212},
["aquamarine2"]={118, 238, 198},
["aquamarine3"]={102, 205, 170},
["aquamarine4"]={69, 139, 116},
["azure"]={240, 255, 255},
["azure1"]={240, 255, 255},
["azure2"]={224, 238, 238},
["azure3"]={193, 205, 205},
["azure4"]={131, 139, 139},
["beige"]={245, 245, 220},
["bisque"]={255, 228, 196},
["bisque1"]={255, 228, 196},
["bisque2"]={238, 213, 183},
["bisque3"]={205, 183, 158},
["bisque4"]={139, 125, 107},
["black"]={0, 0, 0},
["blanched almond"]={255, 235, 205},
["BlanchedAlmond"]={255, 235, 205},
["blue"]={0, 0, 255},
["blue violet"]={138, 43, 226},
["blue1"]={0, 0, 255},
["blue2"]={0, 0, 238},
["blue3"]={0, 0, 205},
["blue4"]={0, 0, 139},
["BlueViolet"]={138, 43, 226},
["brown"]={165, 42, 42},
["brown1"]={255, 64, 64},
["brown2"]={238, 59, 59},
["brown3"]={205, 51, 51},
["brown4"]={139, 35, 35},
["burlywood"]={222, 184, 135},
["burlywood1"]={255, 211, 155},
["burlywood2"]={238, 197, 145},
["burlywood3"]={205, 170, 125},
["burlywood4"]={139, 115, 85},
["cadet blue"]={95, 158, 160},
["CadetBlue"]={95, 158, 160},
["CadetBlue1"]={152, 245, 255},
["CadetBlue2"]={142, 229, 238},
["CadetBlue3"]={122, 197, 205},
["CadetBlue4"]={83, 134, 139},
["chartreuse"]={127, 255, 0},
["chartreuse1"]={127, 255, 0},
["chartreuse2"]={118, 238, 0},
["chartreuse3"]={102, 205, 0},
["chartreuse4"]={69, 139, 0},
["chocolate"]={210, 105, 30},
["chocolate1"]={255, 127, 36},
["chocolate2"]={238, 118, 33},
["chocolate3"]={205, 102, 29},
["chocolate4"]={139, 69, 19},
["coral"]={255, 127, 80},
["coral1"]={255, 114, 86},
["coral2"]={238, 106, 80},
["coral3"]={205, 91, 69},
["coral4"]={139, 62, 47},
["cornflower blue"]={100, 149, 237},
["CornflowerBlue"]={100, 149, 237},
["cornsilk"]={255, 248, 220},
["cornsilk1"]={255, 248, 220},
["cornsilk2"]={238, 232, 205},
["cornsilk3"]={205, 200, 177},
["cornsilk4"]={139, 136, 120},
["cyan"]={0, 255, 255},
["cyan1"]={0, 255, 255},
["cyan2"]={0, 238, 238},
["cyan3"]={0, 205, 205},
["cyan4"]={0, 139, 139},
["dark goldenrod"]={184, 134, 11},
["dark green"]={0, 100, 0},
["dark khaki"]={189, 183, 107},
["dark olive green"]={85, 107, 47},
["dark orange"]={255, 140, 0},
["dark orchid"]={153, 50, 204},
["dark salmon"]={233, 150, 122},
["dark sea green"]={143, 188, 143},
["dark slate blue"]={72, 61, 139},
["dark slate gray"]={47, 79, 79},
["dark slate grey"]={47, 79, 79},
["dark turquoise"]={0, 206, 209},
["dark violet"]={148, 0, 211},
["DarkGoldenrod"]={184, 134, 11},
["DarkGoldenrod1"]={255, 185, 15},
["DarkGoldenrod2"]={238, 173, 14},
["DarkGoldenrod3"]={205, 149, 12},
["DarkGoldenrod4"]={139, 101, 8},
["DarkGreen"]={0, 100, 0},
["DarkKhaki"]={189, 183, 107},
["DarkOliveGreen"]={85, 107, 47},
["DarkOliveGreen1"]={202, 255, 112},
["DarkOliveGreen2"]={188, 238, 104},
["DarkOliveGreen3"]={162, 205, 90},
["DarkOliveGreen4"]={110, 139, 61},
["DarkOrange"]={255, 140, 0},
["DarkOrange1"]={255, 127, 0},
["DarkOrange2"]={238, 118, 0},
["DarkOrange3"]={205, 102, 0},
["DarkOrange4"]={139, 69, 0},
["DarkOrchid"]={153, 50, 204},
["DarkOrchid1"]={191, 62, 255},
["DarkOrchid2"]={178, 58, 238},
["DarkOrchid3"]={154, 50, 205},
["DarkOrchid4"]={104, 34, 139},
["DarkSalmon"]={233, 150, 122},
["DarkSeaGreen"]={143, 188, 143},
["DarkSeaGreen1"]={193, 255, 193},
["DarkSeaGreen2"]={180, 238, 180},
["DarkSeaGreen3"]={155, 205, 155},
["DarkSeaGreen4"]={105, 139, 105},
["DarkSlateBlue"]={72, 61, 139},
["DarkSlateGray"]={47, 79, 79},
["DarkSlateGray1"]={151, 255, 255},
["DarkSlateGray2"]={141, 238, 238},
["DarkSlateGray3"]={121, 205, 205},
["DarkSlateGray4"]={82, 139, 139},
["DarkSlateGrey"]={47, 79, 79},
["DarkTurquoise"]={0, 206, 209},
["DarkViolet"]={148, 0, 211},
["deep pink"]={255, 20, 147},
["deep sky blue"]={0, 191, 255},
["DeepPink"]={255, 20, 147},
["DeepPink1"]={255, 20, 147},
["DeepPink2"]={238, 18, 137},
["DeepPink3"]={205, 16, 118},
["DeepPink4"]={139, 10, 80},
["DeepSkyBlue"]={0, 191, 255},
["DeepSkyBlue1"]={0, 191, 255},
["DeepSkyBlue2"]={0, 178, 238},
["DeepSkyBlue3"]={0, 154, 205},
["DeepSkyBlue4"]={0, 104, 139},
["dim gray"]={105, 105, 105},
["dim grey"]={105, 105, 105},
["DimGray"]={105, 105, 105},
["DimGrey"]={105, 105, 105},
["dodger blue"]={30, 144, 255},
["DodgerBlue"]={30, 144, 255},
["DodgerBlue1"]={30, 144, 255},
["DodgerBlue2"]={28, 134, 238},
["DodgerBlue3"]={24, 116, 205},
["DodgerBlue4"]={16, 78, 139},
["firebrick"]={178, 34, 34},
["firebrick1"]={255, 48, 48},
["firebrick2"]={238, 44, 44},
["firebrick3"]={205, 38, 38},
["firebrick4"]={139, 26, 26},
["floral white"]={255, 250, 240},
["FloralWhite"]={255, 250, 240},
["forest green"]={34, 139, 34},
["ForestGreen"]={34, 139, 34},
["gainsboro"]={220, 220, 220},
["ghost white"]={248, 248, 255},
["GhostWhite"]={248, 248, 255},
["gold"]={255, 215, 0},
["gold1"]={255, 215, 0},
["gold2"]={238, 201, 0},
["gold3"]={205, 173, 0},
["gold4"]={139, 117, 0},
["goldenrod"]={218, 165, 32},
["goldenrod1"]={255, 193, 37},
["goldenrod2"]={238, 180, 34},
["goldenrod3"]={205, 155, 29},
["goldenrod4"]={139, 105, 20},
["gray"]={190, 190, 190},
["gray0"]={0, 0, 0},
["gray1"]={3, 3, 3},
["gray10"]={26, 26, 26},
["gray100"]={255, 255, 255},
["gray11"]={28, 28, 28},
["gray12"]={31, 31, 31},
["gray13"]={33, 33, 33},
["gray14"]={36, 36, 36},
["gray15"]={38, 38, 38},
["gray16"]={41, 41, 41},
["gray17"]={43, 43, 43},
["gray18"]={46, 46, 46},
["gray19"]={48, 48, 48},
["gray2"]={5, 5, 5},
["gray20"]={51, 51, 51},
["gray21"]={54, 54, 54},
["gray22"]={56, 56, 56},
["gray23"]={59, 59, 59},
["gray24"]={61, 61, 61},
["gray25"]={64, 64, 64},
["gray26"]={66, 66, 66},
["gray27"]={69, 69, 69},
["gray28"]={71, 71, 71},
["gray29"]={74, 74, 74},
["gray3"]={8, 8, 8},
["gray30"]={77, 77, 77},
["gray31"]={79, 79, 79},
["gray32"]={82, 82, 82},
["gray33"]={84, 84, 84},
["gray34"]={87, 87, 87},
["gray35"]={89, 89, 89},
["gray36"]={92, 92, 92},
["gray37"]={94, 94, 94},
["gray38"]={97, 97, 97},
["gray39"]={99, 99, 99},
["gray4"]={10, 10, 10},
["gray40"]={102, 102, 102},
["gray41"]={105, 105, 105},
["gray42"]={107, 107, 107},
["gray43"]={110, 110, 110},
["gray44"]={112, 112, 112},
["gray45"]={115, 115, 115},
["gray46"]={117, 117, 117},
["gray47"]={120, 120, 120},
["gray48"]={122, 122, 122},
["gray49"]={125, 125, 125},
["gray5"]={13, 13, 13},
["gray50"]={127, 127, 127},
["gray51"]={130, 130, 130},
["gray52"]={133, 133, 133},
["gray53"]={135, 135, 135},
["gray54"]={138, 138, 138},
["gray55"]={140, 140, 140},
["gray56"]={143, 143, 143},
["gray57"]={145, 145, 145},
["gray58"]={148, 148, 148},
["gray59"]={150, 150, 150},
["gray6"]={15, 15, 15},
["gray60"]={153, 153, 153},
["gray61"]={156, 156, 156},
["gray62"]={158, 158, 158},
["gray63"]={161, 161, 161},
["gray64"]={163, 163, 163},
["gray65"]={166, 166, 166},
["gray66"]={168, 168, 168},
["gray67"]={171, 171, 171},
["gray68"]={173, 173, 173},
["gray69"]={176, 176, 176},
["gray7"]={18, 18, 18},
["gray70"]={179, 179, 179},
["gray71"]={181, 181, 181},
["gray72"]={184, 184, 184},
["gray73"]={186, 186, 186},
["gray74"]={189, 189, 189},
["gray75"]={191, 191, 191},
["gray76"]={194, 194, 194},
["gray77"]={196, 196, 196},
["gray78"]={199, 199, 199},
["gray79"]={201, 201, 201},
["gray8"]={20, 20, 20},
["gray80"]={204, 204, 204},
["gray81"]={207, 207, 207},
["gray82"]={209, 209, 209},
["gray83"]={212, 212, 212},
["gray84"]={214, 214, 214},
["gray85"]={217, 217, 217},
["gray86"]={219, 219, 219},
["gray87"]={222, 222, 222},
["gray88"]={224, 224, 224},
["gray89"]={227, 227, 227},
["gray9"]={23, 23, 23},
["gray90"]={229, 229, 229},
["gray91"]={232, 232, 232},
["gray92"]={235, 235, 235},
["gray93"]={237, 237, 237},
["gray94"]={240, 240, 240},
["gray95"]={242, 242, 242},
["gray96"]={245, 245, 245},
["gray97"]={247, 247, 247},
["gray98"]={250, 250, 250},
["gray99"]={252, 252, 252},
["green"]={0, 255, 0},
["green yellow"]={173, 255, 47},
["green1"]={0, 255, 0},
["green2"]={0, 238, 0},
["green3"]={0, 205, 0},
["green4"]={0, 139, 0},
["GreenYellow"]={173, 255, 47},
["grey"]={190, 190, 190},
["grey0"]={0, 0, 0},
["grey1"]={3, 3, 3},
["grey10"]={26, 26, 26},
["grey100"]={255, 255, 255},
["grey11"]={28, 28, 28},
["grey12"]={31, 31, 31},
["grey13"]={33, 33, 33},
["grey14"]={36, 36, 36},
["grey15"]={38, 38, 38},
["grey16"]={41, 41, 41},
["grey17"]={43, 43, 43},
["grey18"]={46, 46, 46},
["grey19"]={48, 48, 48},
["grey2"]={5, 5, 5},
["grey20"]={51, 51, 51},
["grey21"]={54, 54, 54},
["grey22"]={56, 56, 56},
["grey23"]={59, 59, 59},
["grey24"]={61, 61, 61},
["grey25"]={64, 64, 64},
["grey26"]={66, 66, 66},
["grey27"]={69, 69, 69},
["grey28"]={71, 71, 71},
["grey29"]={74, 74, 74},
["grey3"]={8, 8, 8},
["grey30"]={77, 77, 77},
["grey31"]={79, 79, 79},
["grey32"]={82, 82, 82},
["grey33"]={84, 84, 84},
["grey34"]={87, 87, 87},
["grey35"]={89, 89, 89},
["grey36"]={92, 92, 92},
["grey37"]={94, 94, 94},
["grey38"]={97, 97, 97},
["grey39"]={99, 99, 99},
["grey4"]={10, 10, 10},
["grey40"]={102, 102, 102},
["grey41"]={105, 105, 105},
["grey42"]={107, 107, 107},
["grey43"]={110, 110, 110},
["grey44"]={112, 112, 112},
["grey45"]={115, 115, 115},
["grey46"]={117, 117, 117},
["grey47"]={120, 120, 120},
["grey48"]={122, 122, 122},
["grey49"]={125, 125, 125},
["grey5"]={13, 13, 13},
["grey50"]={127, 127, 127},
["grey51"]={130, 130, 130},
["grey52"]={133, 133, 133},
["grey53"]={135, 135, 135},
["grey54"]={138, 138, 138},
["grey55"]={140, 140, 140},
["grey56"]={143, 143, 143},
["grey57"]={145, 145, 145},
["grey58"]={148, 148, 148},
["grey59"]={150, 150, 150},
["grey6"]={15, 15, 15},
["grey60"]={153, 153, 153},
["grey61"]={156, 156, 156},
["grey62"]={158, 158, 158},
["grey63"]={161, 161, 161},
["grey64"]={163, 163, 163},
["grey65"]={166, 166, 166},
["grey66"]={168, 168, 168},
["grey67"]={171, 171, 171},
["grey68"]={173, 173, 173},
["grey69"]={176, 176, 176},
["grey7"]={18, 18, 18},
["grey70"]={179, 179, 179},
["grey71"]={181, 181, 181},
["grey72"]={184, 184, 184},
["grey73"]={186, 186, 186},
["grey74"]={189, 189, 189},
["grey75"]={191, 191, 191},
["grey76"]={194, 194, 194},
["grey77"]={196, 196, 196},
["grey78"]={199, 199, 199},
["grey79"]={201, 201, 201},
["grey8"]={20, 20, 20},
["grey80"]={204, 204, 204},
["grey81"]={207, 207, 207},
["grey82"]={209, 209, 209},
["grey83"]={212, 212, 212},
["grey84"]={214, 214, 214},
["grey85"]={217, 217, 217},
["grey86"]={219, 219, 219},
["grey87"]={222, 222, 222},
["grey88"]={224, 224, 224},
["grey89"]={227, 227, 227},
["grey9"]={23, 23, 23},
["grey90"]={229, 229, 229},
["grey91"]={232, 232, 232},
["grey92"]={235, 235, 235},
["grey93"]={237, 237, 237},
["grey94"]={240, 240, 240},
["grey95"]={242, 242, 242},
["grey96"]={245, 245, 245},
["grey97"]={247, 247, 247},
["grey98"]={250, 250, 250},
["grey99"]={252, 252, 252},
["honeydew"]={240, 255, 240},
["honeydew1"]={240, 255, 240},
["honeydew2"]={224, 238, 224},
["honeydew3"]={193, 205, 193},
["honeydew4"]={131, 139, 131},
["hot pink"]={255, 105, 180},
["HotPink"]={255, 105, 180},
["HotPink1"]={255, 110, 180},
["HotPink2"]={238, 106, 167},
["HotPink3"]={205, 96, 144},
["HotPink4"]={139, 58, 98},
["indian red"]={205, 92, 92},
["IndianRed"]={205, 92, 92},
["IndianRed1"]={255, 106, 106},
["IndianRed2"]={238, 99, 99},
["IndianRed3"]={205, 85, 85},
["IndianRed4"]={139, 58, 58},
["ivory"]={255, 255, 240},
["ivory1"]={255, 255, 240},
["ivory2"]={238, 238, 224},
["ivory3"]={205, 205, 193},
["ivory4"]={139, 139, 131},
["khaki"]={240, 230, 140},
["khaki1"]={255, 246, 143},
["khaki2"]={238, 230, 133},
["khaki3"]={205, 198, 115},
["khaki4"]={139, 134, 78},
["lavender"]={230, 230, 250},
["lavender blush"]={255, 240, 245},
["LavenderBlush"]={255, 240, 245},
["LavenderBlush1"]={255, 240, 245},
["LavenderBlush2"]={238, 224, 229},
["LavenderBlush3"]={205, 193, 197},
["LavenderBlush4"]={139, 131, 134},
["lawn green"]={124, 252, 0},
["LawnGreen"]={124, 252, 0},
["lemon chiffon"]={255, 250, 205},
["LemonChiffon"]={255, 250, 205},
["LemonChiffon1"]={255, 250, 205},
["LemonChiffon2"]={238, 233, 191},
["LemonChiffon3"]={205, 201, 165},
["LemonChiffon4"]={139, 137, 112},
["light blue"]={173, 216, 230},
["light coral"]={240, 128, 128},
["light cyan"]={224, 255, 255},
["light goldenrod"]={238, 221, 130},
["light goldenrod yellow"]={250, 250, 210},
["light gray"]={211, 211, 211},
["light grey"]={211, 211, 211},
["light pink"]={255, 182, 193},
["light salmon"]={255, 160, 122},
["light sea green"]={32, 178, 170},
["light sky blue"]={135, 206, 250},
["light slate blue"]={132, 112, 255},
["light slate gray"]={119, 136, 153},
["light slate grey"]={119, 136, 153},
["light steel blue"]={176, 196, 222},
["light yellow"]={255, 255, 224},
["LightBlue"]={173, 216, 230},
["LightBlue1"]={191, 239, 255},
["LightBlue2"]={178, 223, 238},
["LightBlue3"]={154, 192, 205},
["LightBlue4"]={104, 131, 139},
["LightCoral"]={240, 128, 128},
["LightCyan"]={224, 255, 255},
["LightCyan1"]={224, 255, 255},
["LightCyan2"]={209, 238, 238},
["LightCyan3"]={180, 205, 205},
["LightCyan4"]={122, 139, 139},
["LightGoldenrod"]={238, 221, 130},
["LightGoldenrod1"]={255, 236, 139},
["LightGoldenrod2"]={238, 220, 130},
["LightGoldenrod3"]={205, 190, 112},
["LightGoldenrod4"]={139, 129, 76},
["LightGoldenrodYellow"]={250, 250, 210},
["LightGray"]={211, 211, 211},
["LightGrey"]={211, 211, 211},
["LightPink"]={255, 182, 193},
["LightPink1"]={255, 174, 185},
["LightPink2"]={238, 162, 173},
["LightPink3"]={205, 140, 149},
["LightPink4"]={139, 95, 101},
["LightSalmon"]={255, 160, 122},
["LightSalmon1"]={255, 160, 122},
["LightSalmon2"]={238, 149, 114},
["LightSalmon3"]={205, 129, 98},
["LightSalmon4"]={139, 87, 66},
["LightSeaGreen"]={32, 178, 170},
["LightSkyBlue"]={135, 206, 250},
["LightSkyBlue1"]={176, 226, 255},
["LightSkyBlue2"]={164, 211, 238},
["LightSkyBlue3"]={141, 182, 205},
["LightSkyBlue4"]={96, 123, 139},
["LightSlateBlue"]={132, 112, 255},
["LightSlateGray"]={119, 136, 153},
["LightSlateGrey"]={119, 136, 153},
["LightSteelBlue"]={176, 196, 222},
["LightSteelBlue1"]={202, 225, 255},
["LightSteelBlue2"]={188, 210, 238},
["LightSteelBlue3"]={162, 181, 205},
["LightSteelBlue4"]={110, 123, 139},
["LightYellow"]={255, 255, 224},
["LightYellow1"]={255, 255, 224},
["LightYellow2"]={238, 238, 209},
["LightYellow3"]={205, 205, 180},
["LightYellow4"]={139, 139, 122},
["lime green"]={50, 205, 50},
["LimeGreen"]={50, 205, 50},
["linen"]={250, 240, 230},
["magenta"]={255, 0, 255},
["magenta1"]={255, 0, 255},
["magenta2"]={238, 0, 238},
["magenta3"]={205, 0, 205},
["magenta4"]={139, 0, 139},
["maroon"]={176, 48, 96},
["maroon1"]={255, 52, 179},
["maroon2"]={238, 48, 167},
["maroon3"]={205, 41, 144},
["maroon4"]={139, 28, 98},
["medium aquamarine"]={102, 205, 170},
["medium blue"]={0, 0, 205},
["medium orchid"]={186, 85, 211},
["medium purple"]={147, 112, 219},
["medium sea green"]={60, 179, 113},
["medium slate blue"]={123, 104, 238},
["medium spring green"]={0, 250, 154},
["medium turquoise"]={72, 209, 204},
["medium violet red"]={199, 21, 133},
["MediumAquamarine"]={102, 205, 170},
["MediumBlue"]={0, 0, 205},
["MediumOrchid"]={186, 85, 211},
["MediumOrchid1"]={224, 102, 255},
["MediumOrchid2"]={209, 95, 238},
["MediumOrchid3"]={180, 82, 205},
["MediumOrchid4"]={122, 55, 139},
["MediumPurple"]={147, 112, 219},
["MediumPurple1"]={171, 130, 255},
["MediumPurple2"]={159, 121, 238},
["MediumPurple3"]={137, 104, 205},
["MediumPurple4"]={93, 71, 139},
["MediumSeaGreen"]={60, 179, 113},
["MediumSlateBlue"]={123, 104, 238},
["MediumSpringGreen"]={0, 250, 154},
["MediumTurquoise"]={72, 209, 204},
["MediumVioletRed"]={199, 21, 133},
["midnight blue"]={25, 25, 112},
["MidnightBlue"]={25, 25, 112},
["mint cream"]={245, 255, 250},
["MintCream"]={245, 255, 250},
["misty rose"]={255, 228, 225},
["MistyRose"]={255, 228, 225},
["MistyRose1"]={255, 228, 225},
["MistyRose2"]={238, 213, 210},
["MistyRose3"]={205, 183, 181},
["MistyRose4"]={139, 125, 123},
["moccasin"]={255, 228, 181},
["navajo white"]={255, 222, 173},
["NavajoWhite"]={255, 222, 173},
["NavajoWhite1"]={255, 222, 173},
["NavajoWhite2"]={238, 207, 161},
["NavajoWhite3"]={205, 179, 139},
["NavajoWhite4"]={139, 121, 94},
["navy"]={0, 0, 128},
["navy blue"]={0, 0, 128},
["NavyBlue"]={0, 0, 128},
["old lace"]={253, 245, 230},
["OldLace"]={253, 245, 230},
["olive drab"]={107, 142, 35},
["OliveDrab"]={107, 142, 35},
["OliveDrab1"]={192, 255, 62},
["OliveDrab2"]={179, 238, 58},
["OliveDrab3"]={154, 205, 50},
["OliveDrab4"]={105, 139, 34},
["orange"]={255, 165, 0},
["orange red"]={255, 69, 0},
["orange1"]={255, 165, 0},
["orange2"]={238, 154, 0},
["orange3"]={205, 133, 0},
["orange4"]={139, 90, 0},
["OrangeRed"]={255, 69, 0},
["OrangeRed1"]={255, 69, 0},
["OrangeRed2"]={238, 64, 0},
["OrangeRed3"]={205, 55, 0},
["OrangeRed4"]={139, 37, 0},
["orchid"]={218, 112, 214},
["orchid1"]={255, 131, 250},
["orchid2"]={238, 122, 233},
["orchid3"]={205, 105, 201},
["orchid4"]={139, 71, 137},
["pale goldenrod"]={238, 232, 170},
["pale green"]={152, 251, 152},
["pale turquoise"]={175, 238, 238},
["pale violet red"]={219, 112, 147},
["PaleGoldenrod"]={238, 232, 170},
["PaleGreen"]={152, 251, 152},
["PaleGreen1"]={154, 255, 154},
["PaleGreen2"]={144, 238, 144},
["PaleGreen3"]={124, 205, 124},
["PaleGreen4"]={84, 139, 84},
["PaleTurquoise"]={175, 238, 238},
["PaleTurquoise1"]={187, 255, 255},
["PaleTurquoise2"]={174, 238, 238},
["PaleTurquoise3"]={150, 205, 205},
["PaleTurquoise4"]={102, 139, 139},
["PaleVioletRed"]={219, 112, 147},
["PaleVioletRed1"]={255, 130, 171},
["PaleVioletRed2"]={238, 121, 159},
["PaleVioletRed3"]={205, 104, 137},
["PaleVioletRed4"]={139, 71, 93},
["papaya whip"]={255, 239, 213},
["PapayaWhip"]={255, 239, 213},
["peach puff"]={255, 218, 185},
["PeachPuff"]={255, 218, 185},
["PeachPuff1"]={255, 218, 185},
["PeachPuff2"]={238, 203, 173},
["PeachPuff3"]={205, 175, 149},
["PeachPuff4"]={139, 119, 101},
["peru"]={205, 133, 63},
["pink"]={255, 192, 203},
["pink1"]={255, 181, 197},
["pink2"]={238, 169, 184},
["pink3"]={205, 145, 158},
["pink4"]={139, 99, 108},
["plum"]={221, 160, 221},
["plum1"]={255, 187, 255},
["plum2"]={238, 174, 238},
["plum3"]={205, 150, 205},
["plum4"]={139, 102, 139},
["powder blue"]={176, 224, 230},
["PowderBlue"]={176, 224, 230},
["purple"]={160, 32, 240},
["purple1"]={155, 48, 255},
["purple2"]={145, 44, 238},
["purple3"]={125, 38, 205},
["purple4"]={85, 26, 139},
["red"]={255, 0, 0},
["red1"]={255, 0, 0},
["red2"]={238, 0, 0},
["red3"]={205, 0, 0},
["red4"]={139, 0, 0},
["rosy brown"]={188, 143, 143},
["RosyBrown"]={188, 143, 143},
["RosyBrown1"]={255, 193, 193},
["RosyBrown2"]={238, 180, 180},
["RosyBrown3"]={205, 155, 155},
["RosyBrown4"]={139, 105, 105},
["royal blue"]={65, 105, 225},
["RoyalBlue"]={65, 105, 225},
["RoyalBlue1"]={72, 118, 255},
["RoyalBlue2"]={67, 110, 238},
["RoyalBlue3"]={58, 95, 205},
["RoyalBlue4"]={39, 64, 139},
["saddle brown"]={139, 69, 19},
["SaddleBrown"]={139, 69, 19},
["salmon"]={250, 128, 114},
["salmon1"]={255, 140, 105},
["salmon2"]={238, 130, 98},
["salmon3"]={205, 112, 84},
["salmon4"]={139, 76, 57},
["sandy brown"]={244, 164, 96},
["SandyBrown"]={244, 164, 96},
["sea green"]={46, 139, 87},
["SeaGreen"]={46, 139, 87},
["SeaGreen1"]={84, 255, 159},
["SeaGreen2"]={78, 238, 148},
["SeaGreen3"]={67, 205, 128},
["SeaGreen4"]={46, 139, 87},
["seashell"]={255, 245, 238},
["seashell1"]={255, 245, 238},
["seashell2"]={238, 229, 222},
["seashell3"]={205, 197, 191},
["seashell4"]={139, 134, 130},
["sienna"]={160, 82, 45},
["sienna1"]={255, 130, 71},
["sienna2"]={238, 121, 66},
["sienna3"]={205, 104, 57},
["sienna4"]={139, 71, 38},
["sky blue"]={135, 206, 235},
["SkyBlue"]={135, 206, 235},
["SkyBlue1"]={135, 206, 255},
["SkyBlue2"]={126, 192, 238},
["SkyBlue3"]={108, 166, 205},
["SkyBlue4"]={74, 112, 139},
["slate blue"]={106, 90, 205},
["slate gray"]={112, 128, 144},
["slate grey"]={112, 128, 144},
["SlateBlue"]={106, 90, 205},
["SlateBlue1"]={131, 111, 255},
["SlateBlue2"]={122, 103, 238},
["SlateBlue3"]={105, 89, 205},
["SlateBlue4"]={71, 60, 139},
["SlateGray"]={112, 128, 144},
["SlateGray1"]={198, 226, 255},
["SlateGray2"]={185, 211, 238},
["SlateGray3"]={159, 182, 205},
["SlateGray4"]={108, 123, 139},
["SlateGrey"]={112, 128, 144},
["snow"]={255, 250, 250},
["snow1"]={255, 250, 250},
["snow2"]={238, 233, 233},
["snow3"]={205, 201, 201},
["snow4"]={139, 137, 137},
["spring green"]={0, 255, 127},
["SpringGreen"]={0, 255, 127},
["SpringGreen1"]={0, 255, 127},
["SpringGreen2"]={0, 238, 118},
["SpringGreen3"]={0, 205, 102},
["SpringGreen4"]={0, 139, 69},
["steel blue"]={70, 130, 180},
["SteelBlue"]={70, 130, 180},
["SteelBlue1"]={99, 184, 255},
["SteelBlue2"]={92, 172, 238},
["SteelBlue3"]={79, 148, 205},
["SteelBlue4"]={54, 100, 139},
["tan"]={210, 180, 140},
["tan1"]={255, 165, 79},
["tan2"]={238, 154, 73},
["tan3"]={205, 133, 63},
["tan4"]={139, 90, 43},
["thistle"]={216, 191, 216},
["thistle1"]={255, 225, 255},
["thistle2"]={238, 210, 238},
["thistle3"]={205, 181, 205},
["thistle4"]={139, 123, 139},
["tomato"]={255, 99, 71},
["tomato1"]={255, 99, 71},
["tomato2"]={238, 92, 66},
["tomato3"]={205, 79, 57},
["tomato4"]={139, 54, 38},
["turquoise"]={64, 224, 208},
["turquoise1"]={0, 245, 255},
["turquoise2"]={0, 229, 238},
["turquoise3"]={0, 197, 205},
["turquoise4"]={0, 134, 139},
["violet"]={238, 130, 238},
["violet red"]={208, 32, 144},
["VioletRed"]={208, 32, 144},
["VioletRed1"]={255, 62, 150},
["VioletRed2"]={238, 58, 140},
["VioletRed3"]={205, 50, 120},
["VioletRed4"]={139, 34, 82},
["wheat"]={245, 222, 179},
["wheat1"]={255, 231, 186},
["wheat2"]={238, 216, 174},
["wheat3"]={205, 186, 150},
["wheat4"]={139, 126, 102},
["white"]={255, 255, 255},
["white smoke"]={245, 245, 245},
["WhiteSmoke"]={245, 245, 245},
["yellow"]={255, 255, 0},
["yellow green"]={154, 205, 50},
["yellow1"]={255, 255, 0},
["yellow2"]={238, 238, 0},
["yellow3"]={205, 205, 0},
["yellow4"]={139, 139, 0},
["YellowGreen"]={154, 205, 50}
}

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>Circle</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>Circle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; drawable circle</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self, x, y, r, s, color)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw(style)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw the circle<br></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>Drawable</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>Drawable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; base class for all drawable stuff</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self, x, y, color)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wrapX(min, max)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;can be called via wrapX(max) or wrapX(min,max)<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wrapY(min, max)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;can be called via wrapY(max) or wrapY(min,max)<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wrap(str, min, max)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal wrapper<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set(str, val)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;supercollider style 'set'<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw()</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;not yet implemented<br></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>Line</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>Line&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; draw a line</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self, x, y, tx, ty)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>Object</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>Object&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; base class</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>SCObject</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>SCObject&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bass class for supercollider communication</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>SCSynth</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>SCSynth&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; supercollider synthesizer class</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self, nodename, freq)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set(control, val)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set a control, TODO: variable lenght of argument-pairs<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.time(),</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bundle",<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;play()</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sends an OSC message to the supercollider to start the synth<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.time(),</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bundle",<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free()</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frees the node on the supercollider server<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.time()+0.8,</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bundle",<br></BODY></HTML>

View File

@ -0,0 +1,70 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="1038.35">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1"><b>Guidelines for new live_libs classes</b></p>
<p class="p2"><br></p>
<p class="p3"><b>1. Howto write a new class</b></p>
<p class="p2"><br></p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span>&lt;class name&gt; =<span class="Apple-converted-space">  </span>Class(&lt;constructor&gt;)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>creates a class with function in constructor</p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-tab-span"> </span>&lt;class name&gt;:inherit(&lt;other class name&gt;)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>if you want to inherit from any class.Everything should inherit directly or indirectly from object, because here the instance is added to the _internal_object_table</p>
<p class="p2"><br></p>
<p class="p3">If you want to call the constructor of the superclass write the following in the constructor of the current class:</p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span>&lt;super class name&gt;.&lt;construct&gt;(self, &lt;arguments&gt;)</p>
<p class="p2"><br></p>
<p class="p3">More on Classes and HUMP: http://vrld.github.com/hump/</p>
<p class="p2"><br></p>
<p class="p3"><b>2. Commenting</b></p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span>In order to work the comment parser needs the following comment 'marks':</p>
<p class="p2"><br></p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-tab-span"> </span>-- @ &lt;class name&gt;:&lt;short description&gt;</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>This marks a new class. The following line should be the class definition</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Note: only one line comments are working</p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-tab-span"> </span>-- # &lt;description&gt;</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>This marks a new method.</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Note: the limitations of class comments apply</p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-tab-span"> </span>any '--' without marks will not be included in the helpfile</p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span><b>Example</b>:</p>
<p class="p3"><i><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>-- @Drawable: base class for all drawable stuff</i></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Drawable = Class(function(self, x, y, color)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>self.color = color or hlpr.color("white",255)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>-- call constructor of Object class</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Object.construct(self)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>self.position = Vector(x or 0,y or 0)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>end)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Drawable:inherit(Object)</p>
<p class="p2"><br></p>
<p class="p3"><i><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>-- #can be called via wrapX(max) or wrapX(min,max)</i></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>function Drawable:wrapX(min, max)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>if min and max then</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>self:wrap("x", min, max)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>elseif min and not max then<span class="Apple-converted-space"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>self:wrap("x", 0, min)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>end</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>end</p>
<p class="p2"><br></p>
<p class="p2"><br></p>
</body>
</html>

View File

@ -0,0 +1,51 @@
Guidelines for new live_libs classes
1. Howto write a new class
<class name> = Class(<constructor>)
creates a class with function in constructor
<class name>:inherit(<other class name>)
if you want to inherit from any class. Everything should inherit directly or indirectly from object, because here the instance is added to the _internal_object_table
If you want to call the constructor of the superclass write the following in the constructor of the current class:
<super class name>.<construct>(self, <arguments>)
More on Classes and HUMP: http://vrld.github.com/hump/
2. Commenting
In order to work the comment parser needs the following comment 'marks':
-- @ <class name>:<short description>
This marks a new class.
Note: only oneliners are working
-- # <description>
This marks a new method.
Note: limitation of class comments apply
any '--' without marks will not be included in the helpfile
Example:
-- @Drawable: base class for all drawable stuff
Drawable = Class(function(self, x, y, color)
self.color = color or hlpr.color("white",255)
-- call constructor of Object class
Object.construct(self)
self.position = Vector(x or 0,y or 0)
end)
Drawable:inherit(Object)
-- #can be called via wrapX(max) or wrapX(min,max)
function Drawable:wrapX(min, max)
if min and max then
self:wrap("x", min, max)
elseif min and not max then
self:wrap("x", 0, min)
end
end

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>live_libs_doc</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>live_libs documentation</h3><a href="guidelines.html">Guidelines for new classes and commenting</a><h4>Classes:</h4><a href="classes/Object.html">Object</a> <br><a href="classes/SCObject.html">SCObject</a> <br><a href="classes/SCSynth.html">SCSynth</a> <br><a href="classes/Drawable.html">Drawable</a> <br><a href="classes/Circle.html">Circle</a> <br><a href="classes/Line.html">Line</a> <br></BODY></HTML>

View File

@ -0,0 +1,109 @@
-- parse the classes to readable html
module(..., package.seeall)
filename = "LICK/lib/object.lua"
help_filename = "LICK/lib/docs/"
-- some styles
local style = "<style type=\"text/css\">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style>"
local header1 = "<HTML><HEAD><TITLE>"
local header2 = "</TITLE>"..style.."</HEAD><BODY>"
local footer = "</BODY></HTML>"
local _newclasstitle = "<h3>"
local newclasstitle_ = "</h3>"
local tab = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
-- generates the html file
function generate()
class_file = love.filesystem.newFile( filename )
class_file:open('r')
local output = ""
output = header1.."test"..header2
local found_methods = 0
local found_classes = 0
local classes = {}
for line in class_file:lines() do
local b,e = string.find(line,"@")
local b1,e1 = string.find(line,"Class")
if b and e then
if found_classes > 0 then
output = output..footer
writeClassFile(name, output)
local output = ""
end
dp,ep = string.find(line, ":")
name = line:sub(e+1, dp-1 or 0)
print(name)
table.insert(classes,name)
output = header1..name..header2
output = output .._newclasstitle .. name..tab..tab..line:sub(dp+1) ..newclasstitle_
found_methods = 0
found_classes = found_classes + 1
elseif b1 and e1 and not string.find(line,"require") then
output = output .."<h4>"..tab..line:sub(e1+2).."</h4>"..tab..tab.."<i> Constructor</i>"
end
local b,e = string.find(line,"#")
if method then
local dp,ep = string.find(line, ":")
ep = ep or 1
if found == 0 then
output = output .."<h3>Methods</h3>"
found_methods = found_methods + 1
end
output = output.."<h4>".. tab ..line:sub(ep+1).."</h4>"..tab..tab..method
method = nil
end
if b and e then
method = line:sub(e+1).."<br>"
--output = output..line:sub(e+1).."<br>"
end
end
output = output..footer
writeClassFile(name, output)
-- generate index.html
index = header1.."live_libs_doc"..header2
index = index.."<h3>live_libs documentation</h3>"
index = index .. "<a href=\"guidelines.html\">Guidelines for new classes and commenting</a>"
index = index.. "<h4>Classes:</h4>"
for i,v in ipairs(classes) do
index = index.."<a href=\"classes/"..v..".html".."\">"..v.."</a> <br>"
end
index = index..footer
writeFile("index", index)
end
function writeClassFile(name, output)
dir = love.filesystem.getWorkingDirectory( )
--print("touch "..dir.."/"..help_filename)
local path = dir.."/live_testproject/"..help_filename.."classes/"..name..".html"
os.execute("touch "..path)
local helpfile = io.open(path, "w" )
helpfile:write(output)
helpfile:close()
end
function writeFile(name, output)
dir = love.filesystem.getWorkingDirectory( )
--print("touch "..dir.."/"..help_filename)
local path = dir.."/live_testproject/"..help_filename..name..".html"
os.execute("touch "..path)
local helpfile = io.open(path, "w" )
helpfile:write(output)
helpfile:close()
end

View File

@ -0,0 +1,281 @@
-- hlpr libary: it's not about nice coding, ist about fast and easy coding
-- by Rukano and Headchant, 2011
pi = math.pi
setColor = love.graphics.setColor
rectangle = love.graphics.rectangle
getWidth = love.graphics.getWidth
getHeight = love.graphics.getHeight
push = love.graphics.push
pop = love.graphics.pop
translate = love.graphics.translate
rotate = love.graphics.rotate
scale = love.graphics.scale
circle = love.graphics.circle
sin = math.sin
deg = math.deg
rad = math.rad
require "LICK/lib/color"
module(...,package.seeall)
function color(r, g,b,a)
local color={}
local alpha=a or 255
local name=r or "azure"
if type(r) == "string" then
alpha = g or alpha
color = x11_color_table[name]
else
color[1]=r
color[2]=g
color[3]=b
end
color[4]=alpha
return color
end
-- clip withing range (by redlock)
function clip(n,min,max)
return math.min(math.max(n, min or -math.huge), max or math.huge)
end
-- wrap within range, updated version
function wrap(n, min, max)
local min = min or 0
return ((n - min) % ((max or 0) - min)) + min
end
-- setColor white
function white()
love.graphics.setColor(255,255,255,255)
end
-- setColor black
function black()
love.graphics.setColor(0,0,0,255)
end
-- shorter setColor white
function w()
white()
end
-- shorter setColor black
function b()
black()
end
-- fill the screen with translucent black
function clear(alpha)
love.graphics.setColor(0,0,0,alpha)
love.graphics.rectangle("fill", 0,0,800,600)
end
-- shorter clear
function cls(alpha)
clear(alpha)
end
-- one time clear
function cls_once()
love.graphics.setColor(0,0,0,255)
love.graphics.rectangle("fill", 0,0,800,600)
end
-- returns random values from -1 to 1, g sets the equidistance
function norm_random()
return 2 * math.random() - 1
end
-- shorte norm_random
function n_rnd()
return norm_random()
end
-- drunk, brownnoise/drunk walk: x = x +/- random(width)
function drunk(x, width, g)
x = x or 0
width = width or 1
g = g or 100
return (x + width*norm_random())
end
-- drnk, shorter version of drunk, start is only used the first time
-- this makes some sense whatsoever...
function drnk(width)
local last = 0
return function()
last = last + width * norm_random()
return last
end
end
-- scaling functions:
function linlin(n,inMin,inMax,outMin,outMax,clip)
-- ported and adapted from:
-- SuperCollider SimpleNumber:linlin
local n=n or 0 -- to avoid giving back nil
local clip=clip or "minmax" -- default:clip minmax
if (inMin == nil) or (inMax == nil) or (outMin == nil) or (outMax == nil) then
-- just in case you forgot the parameters...
return n
end
if clip == "minmax" then
if n <= inMin then
return minoutMin
elseif n >= inMax then
return outMax
end
elseif clip == "min" then
if n <= inMin then
return outMin
end
elseif clip == "max" then
if n >= inMax then
return outMax
end
end
-- here is the magic!
n = (((n-inMin)/(inMax-inMin)) * (outMax-outMin)) + outMin
return n
end
function linexp(n,inMin,inMax,outMin,outMax,clip)
-- ported and adapted from:
-- SuperCollider SimpleNumber:linexp
local n=n or 0.00001 -- to avoid giving back nil
local clip=clip or "minmax" -- default:clip minmax
if (inMin == nil) or (inMax == nil) or (outMin == nil) or (outMax == nil) then
-- just in case...
return n
end
if clip == "minmax" then
if n <= inMin then
return outMin
elseif n >= inMax then
return outMax
end
elseif clip == "min" then
if n <= inMin then
return outMin
end
elseif clip == "max" then
if n >= inMax then
return outMax
end
end
-- here is the magic!
n = math.pow(outMax/outMin, (n-inMin)/(inMax-inMin)) * outMin
return n
end
function explin(n,inMin,inMax,outMin,outMax,clip)
-- ported and adapted from:
-- SuperCollider SimpleNumber:explin
local n=n or 0.00001 -- to avoid giving back nil
local clip=clip or "minmax" -- default:clip minmax
if (inMin == nil) or (inMax == nil) or (outMin == nil) or (outMax == nil) then
-- just in case...
return n
end
if clip == "minmax" then
if n <= inMin then
return outMin
elseif n >= inMax then
return outMax
end
elseif clip == "min" then
if n <= inMin then
return outMin
end
elseif clip == "max" then
if n >= inMax then
return outMax
end
end
-- here is the magic!
n = (((math.log(n/inMin)) / (math.log(inMax/inMin))) * (outMax-outMin)) + outMin
return n
end
function expexp(n,inMin,inMax,outMin,outMax,clip)
-- ported and adapted from:
-- SuperCollider SimpleNumber:expexp
local n=n or 0.00001 -- to avoid giving back nil
local clip=clip or "minmax" -- default:clip minmax
if (inMin == nil) or (inMax == nil) or (outMin == nil) or (outMax == nil) then
-- just in case...
return n
end
if clip == "minmax" then
if n <= inMin then
return outMin
elseif n >= inMax then
return outMax
end
elseif clip == "min" then
if n <= inMin then
return outMin
end
elseif clip == "max" then
if n >= inMax then
return outMax
end
end
-- here is the magic!
n = math.pow(outMax/outMin, math.log(n/inMin) / math.log(inMax/inMin)) * outMin
return n
end
-- returns easy sine oscillator
function sin()
local x = 0
return function(dt)
x = x + (dt or 0)
if x > 2 * pi then x = x - 2*pi end
return math.sin(x)
end
end
-- updates all objects in the _object table
function update_objects()
for i,v in ipairs(_internal_object_table) do
v:update(dt)
end
end
-- rotate around center
function rotateCenter(angle)
local angle=angle or 0
local w, h = getWidth(), getHeight()
translate(w/2, h/2)
rotate(angle)
translate(-w/2, -h/2)
end
-- return a random table entry
function choose(table)
return table[math.random(#table)]
end

View File

@ -0,0 +1,48 @@
HUMP - Helper Utilities for Massive Progression
===============================================
__HUMP__ is a small collection of tools for developing games with L&Ouml;VE.
Contents:
------------
* *vector.lua*: powerful vector class (pure lua)
* *class.lua*: "class" system supporting function inheritance (pure lua)
* *camera.lua*: translate-, zoom- and rotatable camera
* *gamestate.lua*: class to handle gamestates
* *ringbuffer.lua*: a circular container
* *sequence.lua*: utility to handle ingame cutscenes and such
Documentation
=============
You can find the documentation here: [http://vrld.github.com/hump/](http://vrld.github.com/hump/ "project page")
License
=======
Yay, *free software*:
> Copyright (c) 2010 Matthias Richter
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> Except as contained in this notice, the name(s) of the above copyright holders
> shall not be used in advertising or otherwise to promote the sale, use or
> other dealings in this Software without prior written authorization.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.

View File

@ -0,0 +1,90 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local setmetatable, require, love = setmetatable, require, love
module(...)
local vector = require(_PACKAGE..'vector')
local camera = {}
camera.__index = camera
function new(pos, zoom, rot)
local pos = pos or vector(love.graphics.getWidth(), love.graphics.getHeight()) / 2
local zoom = zoom or 1
local rot = rot or 0
return setmetatable({pos = pos, zoom = zoom, rot = rot}, camera)
end
function camera:rotate(phi)
self.rot = self.rot + phi
end
function camera:translate(t)
self.pos = self.pos + t
end
camera.move = camera.translate
function camera:predraw()
local center = vector(love.graphics.getWidth(), love.graphics.getHeight()) / (self.zoom * 2)
love.graphics.push()
love.graphics.scale(self.zoom)
love.graphics.translate(center:unpack())
love.graphics.rotate(self.rot)
love.graphics.translate((-self.pos):unpack())
end
function camera:postdraw()
love.graphics.pop()
end
function camera:draw(func)
self:predraw()
func()
self:postdraw()
end
function camera:toCameraCoords(p)
local w,h = love.graphics.getWidth(), love.graphics.getHeight()
local p = (p - self.pos):rotate_inplace(self.rot)
return vector(p.x * self.zoom + w/2, p.y * self.zoom + h/2)
end
function camera:toWorldCoords(p)
local w,h = love.graphics.getWidth(), love.graphics.getHeight()
local p = vector((p.x-w/2) / self.zoom, (p.y-h/2) / self.zoom):rotate_inplace(-self.rot)
return p + self.pos
end
function camera:mousepos()
return self:toWorldCoords(vector(love.mouse.getPosition()))
end
-- camera() as a shortcut to new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

View File

@ -0,0 +1,82 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local setmetatable, getmetatable = setmetatable, getmetatable
local type, assert, pairs = type, assert, pairs
local tostring, string_format = tostring, string.format
module(...)
local function __NULL__() end
function new(constructor)
-- check name and constructor
local name = '<unnamed class>'
if type(constructor) == "table" then
if constructor.name then name = constructor.name end
constructor = constructor[1]
end
assert(not constructor or type(constructor) == "function",
string_format('%s: constructor has to be nil or a function', name))
-- build class
local c = {}
c.__index = c
c.__tostring = function() return string_format("<instance of %s>", name) end
c.construct = constructor or __NULL__
c.Construct = constructor or __NULL__
c.inherit = inherit
c.Inherit = inherit
local meta = {
__call = function(self, ...)
local obj = {}
self.construct(obj, ...)
return setmetatable(obj, self)
end,
__tostring = function() return tostring(name) end
}
return setmetatable(c, meta)
end
function inherit(class, interface, ...)
if not interface then return end
-- __index and construct are not overwritten as for them class[name] is defined
for name, func in pairs(interface) do
if not class[name] and type(func) == "function" then
class[name] = func
end
end
inherit(class, ...)
end
-- class() as shortcut to class.new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

View File

@ -0,0 +1,154 @@
--[[
Copyright (c) 2010-2011 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local error, assert, love = error, assert, love
module(...)
local function __NULL__() end
-- default gamestate produces error on every callback
local function __ERROR__() error("Gamestate not initialized. Use Gamestate.switch()") end
current = {
enter = __ERROR__,
leave = __NULL__,
update = __ERROR__,
draw = __ERROR__,
focus = __ERROR__,
keyreleased = __ERROR__,
keypressed = __ERROR__,
mousepressed = __ERROR__,
mousereleased = __ERROR__,
joystickpressed = __ERROR__,
joystickreleased = __ERROR__,
quit = __ERROR__,
}
function new()
return {
enter = __NULL__,
leave = __NULL__,
update = __NULL__,
draw = __NULL__,
focus = __NULL__,
keyreleased = __NULL__,
keypressed = __NULL__,
mousepressed = __NULL__,
mousereleased = __NULL__,
joystickpressed = __NULL__,
joystickreleased = __NULL__,
quit = __NULL__,
}
end
function switch(to, ...)
assert(to, "Missing argument: Gamestate to switch to")
current:leave()
local pre = current
current = to
return current:enter(pre, ...)
end
local _update
function update(...)
if _update then _update(...) end
return current:update(...)
end
local _draw
function draw(...)
if _draw then _draw(...) end
return current:draw(...)
end
local _focus
function focus(...)
if _focus then _focus(...) end
return current:focus(...)
end
local _keypressed
function keypressed(...)
if _keypressed then _keypressed(...) end
return current:keypressed(...)
end
local _keyreleased
function keyreleased(...)
if _keyreleased then _keyreleased(...) end
return current:keyreleased(...)
end
local _mousepressed
function mousepressed(...)
if _mousereleased then _mousepressed(...) end
return current:mousepressed(...)
end
local _mousereleased
function mousereleased(...)
if _mousereleased then _mousereleased(...) end
return current:mousereleased(...)
end
local _joystickpressed
function joystickpressed(...)
if _joystickpressed then _joystickpressed(...) end
return current:joystickpressed(...)
end
local _joystickreleased
function joystickreleased(...)
if _joystickreleased then _joystickreleased(...) end
return current:joystickreleased(...)
end
local _quit
function quit(...)
if _quit then _quit(...) end
return current:quit(...)
end
function registerEvents()
_update = love.update
love.update = update
_draw = love.draw
love.draw = draw
_focus = love.focus
love.focus = focus
_keypressed = love.keypressed
love.keypressed = keypressed
_keyreleased = love.keyreleased
love.keyreleased = keyreleased
_mousepressed = love.mousepressed
love.mousepressed = mousepressed
_mousereleased = love.mousereleased
love.mousereleased = mousereleased
_joystickpressed = love.joystickpressed
love.joystickpressed = joystickpressed
_joystickreleased = love.joystickreleased
love.joystickreleased = joystickreleased
_quit = love.quit
love.quit = quit
end

View File

@ -0,0 +1,99 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local setmetatable, getmetatable, table = setmetatable, getmetatable, table
module(...)
local ringbuffer = {}
ringbuffer.__index = ringbuffer
function new(...)
local rb = {}
rb.items = {...}
rb.current = 1
return setmetatable(rb, ringbuffer)
end
function ringbuffer:insert(item, ...)
if not item then return end
-- insert rest before self so order is restored, e.g.:
-- {1,<2>,3}:insert(4,5) -> {1,<2>,3}:insert(5) -> {1,<2>,5,3} -> {1,<2>,4,5,3}
self:insert(...)
table.insert(self.items, self.current+1, item)
end
function ringbuffer:append(item, ...)
if not item then return end
self.items[#self.items+1] = item
return self:append(...)
end
function ringbuffer:removeAt(k)
-- wrap position
local pos = (self.current + k) % #self.items
while pos < 1 do pos = pos + #self.items end
-- remove item
local item = table.remove(self.items, pos)
-- possibly adjust current pointer
if pos < self.current then self.current = self.current - 1 end
if self.current > #self.items then self.current = 1 end
-- return item
return item
end
function ringbuffer:remove()
return table.remove(self.items, self.current)
end
function ringbuffer:get()
return self.items[self.current]
end
function ringbuffer:size()
return #self.items
end
function ringbuffer:next()
self.current = (self.current % #self.items) + 1
return self:get()
end
function ringbuffer:prev()
self.current = self.current - 1
if self.current < 1 then
self.current = #self.items
end
return self:get()
end
-- Ringbuffer() as a shortcut to Ringbuffer.new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

View File

@ -0,0 +1,83 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local assert, type = assert, type
local pairs, ipairs = pairs, ipairs
local min = math.min
module(...)
functions = {}
function update(dt)
local to_remove = {}
for func, delay in pairs(functions) do
delay = delay - dt
if delay <= 0 then
to_remove[#to_remove+1] = func
else
functions[func] = delay
end
end
for _,func in ipairs(to_remove) do
functions[func] = nil
func(func)
end
end
function add(delay, func)
assert(type(func) == "function", "second argument needs to be a function")
functions[func] = delay
end
function addPeriodic(delay, func, count)
assert(type(func) == "function", "second argument needs to be a function")
if count then
return add(delay, function(f) func(func) count = count - 1 if count > 0 then add(delay, f) end end)
end
return add(delay, function(f) func(func) add(delay, f) end)
end
function clear()
functions = {}
end
function Interpolator(length, func)
assert(type(func) == "function", "second argument needs to be a function")
local t = 0
return function(dt, ...)
t = t + dt
return t <= length and func((t-dt)/length, ...) or nil
end
end
function Oscillator(length, func)
assert(type(func) == "function", "second argument needs to be a function")
local t = 0
return function(dt, ...)
t = t + dt
while t > length do t = t - length end
return func(t/length, ...)
end
end

View File

@ -0,0 +1,156 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local setmetatable, getmetatable = setmetatable, getmetatable
local assert, type, tonumber = assert, type, tonumber
local sqrt, cos, sin = math.sqrt, math.cos, math.sin
module(...)
local vector = {}
vector.__index = vector
function new(x,y)
local v = {x = x or 0, y = y or 0}
setmetatable(v, vector)
return v
end
function isvector(v)
return getmetatable(v) == vector
end
function vector:clone()
return new(self.x, self.y)
end
function vector:unpack()
return self.x, self.y
end
function vector:__tostring()
return "("..tonumber(self.x)..","..tonumber(self.y)..")"
end
function vector.__unm(a)
return new(-a.x, -a.y)
end
function vector.__add(a,b)
assert(isvector(a) and isvector(b), "Add: wrong argument types (<vector> expected)")
return new(a.x+b.x, a.y+b.y)
end
function vector.__sub(a,b)
assert(isvector(a) and isvector(b), "Sub: wrong argument types (<vector> expected)")
return new(a.x-b.x, a.y-b.y)
end
function vector.__mul(a,b)
if type(a) == "number" then
return new(a*b.x, a*b.y)
elseif type(b) == "number" then
return new(b*a.x, b*a.y)
else
assert(isvector(a) and isvector(b), "Mul: wrong argument types (<vector> or <number> expected)")
return a.x*b.x + a.y*b.y
end
end
function vector.__div(a,b)
assert(isvector(a) and type(b) == "number", "wrong argument types (expected <vector> / <number>)")
return new(a.x / b, a.y / b)
end
function vector.__eq(a,b)
return a.x == b.x and a.y == b.y
end
function vector.__lt(a,b)
return a.x < b.x or (a.x == b.x and a.y < b.y)
end
function vector.__le(a,b)
return a.x <= b.x and a.y <= b.y
end
function vector.permul(a,b)
assert(isvector(a) and isvector(b), "permul: wrong argument types (<vector> expected)")
return new(a.x*b.x, a.y*b.y)
end
function vector:len2()
return self * self
end
function vector:len()
return sqrt(self*self)
end
function vector.dist(a, b)
assert(isvector(a) and isvector(b), "dist: wrong argument types (<vector> expected)")
return (b-a):len()
end
function vector:normalize_inplace()
local l = self:len()
self.x, self.y = self.x / l, self.y / l
return self
end
function vector:normalized()
return self / self:len()
end
function vector:rotate_inplace(phi)
local c, s = cos(phi), sin(phi)
self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y
return self
end
function vector:rotated(phi)
return self:clone():rotate_inplace(phi)
end
function vector:perpendicular()
return new(-self.y, self.x)
end
function vector:projectOn(v)
assert(isvector(v), "invalid argument: cannot project onto anything other than a new.")
return (self * v) * v / v:len2()
end
function vector:cross(other)
assert(isvector(other), "cross: wrong argument types (<vector> expected)")
return self.x * other.y - self.y * other.x
end
-- vector() as shortcut to vector.new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1,4 @@
-- init live_libs
Vector = require "LICK/lib/hump/vector"
require "LICK/lib/object"
require "LICK/lib/loveosc"

View File

@ -0,0 +1,8 @@
loveOSC is a fork of luaOSC(http://luaforge.net/projects/luaosc/) which implements the Open Sound Control Protocol (http://opensoundcontrol.org/) but substitutes the LPACK dependency with VSTRUCT for greater portability
The testproject sends a OSC message to a server on port 57110, which is Supercolliders OSC port. It also receives OSC messages on port 7771.
Features:
- Client, sending/encoding OSC messages/bundles
- Server, receiving/decoding/handle OSC messages

View File

@ -0,0 +1,340 @@
--[[
-- luaosc Copyright (C) 2009 Jost Tobias Springenberg <k-gee@wrfl.de> --
This file is part of luaosc.
luaosc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
luaosc 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
--]]
-- This is a luaOSC Fork from Jost Tobias Springenberg, additional code and modifications by Tilmann Hars, Headchant.com, Copyright 2010
local socket = require "socket"
local base = _G
local string = require("string")
local vstruct = require "LICK/lib/loveosc/vstruct"
local pack = vstruct.pack
local upack = vstruct.unpack
--------------------------------
-- some constants
--------------------------------
osc.client = {}
osc.client.host = "localhost"
osc.client.port = 57110
osc.client.timeout = 0
PROTOCOL = "OSC/1.0"
ADJUSTMENT_FACTOR = 2208988800
IMMEDIATE = string.rep('0', 31) .. '1'
function osc.client:send( data )
local ip, port = assert(socket.dns.toip(osc.client.host)), osc.client.port
-- create a new UDP object
local udp = assert(socket.udp())
udp:settimeout(0)
--print(encode(data))
assert(udp:sendto(encode(data), ip, port), "could not send data")
--assert(udp:sendto(data, ip, port), "could not send data")
-- retrieve the answer and print results, warning: crashes love
--print(udp:receive() or "")
end
--------------------------------
-- interface functions:
-- decode(string)
-- and encode(table)
--------------------------------
function decode(data)
if #data == 0 then
return nil
end
if string.match(data, "^#bundle") then
return decode_bundle(data)
else
return decode_message(data)
end
end
function encode(data)
local msg = ""
local idx = 1
if data == nil then
return nil
end
if data[1] == "#bundle" then
msg = msg .. encode_string(data[1])
--print("1 "..msg.."\n")
msg = msg .. encode_timetag(data[2])
--print("2 "..msg.."\n")
idx = 3
while idx <= #data do
local submsg = encode(data[idx])
msg = msg .. encode_int(#submsg) .. submsg
--print(idx.." "..submsg.."\n")
idx = idx + 1
end
return msg
else
local typestring = ","
local encodings = ""
idx = idx + 1
msg = msg .. encode_string(data[1])
for t, d in iter_pairwise(data, idx) do
typestring = typestring .. t
encodings = encodings .. collect_encoding_for_message(t, d)
end
--print("else "..msg..encode_string(typestring) .. encodings.."\n")
return msg .. encode_string(typestring) .. encodings
end
end
--------------------------------
-- auxilliary functions
--------------------------------
digits = {}
for i=0,9 do digits[i] = string.char(string.byte('0')+i) end
for i=10,36 do digits[i] = string.char(string.byte('A')+i-10) end
function numberstring(number, bas)
local s = ""
repeat
local remainder = base.math.mod(number,bas)
s = digits[remainder]..s
number = (number-remainder)/bas
until number==0
return s
end
function next_string(astring)
-- this is a workaraound because the lua pttern matching is
-- not as powerful as pcre and I did not want to include another
-- dependecy to an external re lib
local pos = 0
local num_nzero = 0
local num_zero = 0
local result = ""
if astring == nil then
-- ensure that string is not empty
base.error("error: string is empty - probably malformated message")
end
-- we match every character with the help of gmatch
for m in string.gmatch(astring, ".") do
pos = pos + 1
-- and then check if it is correctly padded with '\0's
if m ~= '\0' and num_zero == 0 then
num_nzero = (num_nzero + 1) % 4
result = result .. m
elseif num_zero ~= 0 and (num_zero + num_nzero) % 4 == 0 then
return result, pos
elseif m == '\0' then
num_zero = num_zero + 1
result = result .. m
else
return nil
end
end
end
function iter_pairwise(atable, startvalue)
local index = startvalue - 2
return function()
index = index + 2
return atable[index], atable[index+1]
end
end
function collect_encoding_for_message(t, data)
if t == 'i' then
return encode_int(data)
elseif t == 'f' then
return encode_float(data)
elseif t == 's' then
return encode_string(data)
elseif t == 'b' then
return encode_blob(data)
end
end
function collect_decoding_from_message(t, data, message)
table.insert(message, t)
if t == 'i' then
table.insert(message, decode_int(data))
return string.sub(data, 5)
elseif t == 'f' then
table.insert(message, decode_float(data))
return string.sub(data, 5)
elseif t == 's' then
local match, last = next_string(data)
table.insert(message, match)
return string.sub(data, last)
elseif t == 'b' then
local length = decode_int(data)
table.insert(message, string.sub(data, 4, length))
return string.sub(data, 4 + length + 1)
end
end
function get_addr_from_data(data)
local addr_raw_string,last = next_string(data)
local result = ""
if addr_raw_string == nil then
-- if we could not find an addr something went wrong
base.error("error: could not extract address from OSC message")
end
-- delete possible trailing zeros
for t in string.gmatch(addr_raw_string, "[^%z]") do
result = result .. t
end
return result, string.sub(data, last)
end
function get_types_from_data(data)
local typestring, last = next_string(data)
local result = {}
if typestring == nil then
return {}
end
-- split typestring into an iterable table
for t in string.gmatch(typestring, "[^,%z]") do
table.insert(result, t)
end
return result, string.sub(data, last)
end
--------------------------------
-- decoding functions
--------------------------------
function decode_message(data)
local types, addr, tmp_data = nil
local message = {}
addr, tmp_data = get_addr_from_data(data)
types, tmp_data = get_types_from_data(tmp_data)
-- ensure that we at least found something
if addr == nil or types == nil then
return nil
end
for _,t in base.ipairs(types) do
tmp_data = collect_decoding_from_message(t, tmp_data, message)
end
return message
end
function decode_bundle(data)
local match, last = next_string(data)
local tmp_data = nil
local msg = {}
local sec, frac
-- skip first string data since it will only contian #bundle
tmp_data = string.sub(data, 9)
-- check that there is a part of the message left
if not tmp_data then
return nil
end
table.insert(msg, "#bundle")
_, sec, frac = upack("> u4 > u4", {string.sub(tmp_data, 1, 8)})
-- note this is an awful way of decoding to a bin string and
-- then decoding the frac again TODO: make this nicer
frac = numberstring(frac, 2)
if sec == 0 and frac == IMMEDIATE then
table.insert(msg, 0)
else
table.insert(msg, sec - ADJUSTMENT_FACTOR + decode_frac(frac) )
end
tmp_data = string.sub(tmp_data, 9)
while #tmp_data > 0 do
local length = decode_int(string.sub(tmp_data,1,4))
table.insert(msg, decode(string.sub(tmp_data, 5, 4 + length)))
tmp_data = string.sub(tmp_data, 9 + length)
end
return msg
end
function decode_frac(bin)
local frac = 0
for i=#bin,1 do
frac = (frac + string.sub(bin, i-1, i)) / 2
end
return frac
end
function decode_float(bin)
local pos, res = upack("> f4", {bin})
return res
end
function decode_int(bin)
local pos, res = upack("> i4", {bin} )
return res
end
--------------------------------
-- encoding
--------------------------------
function encode_string(astring)
local fillbits = (4 - #astring % 4)
return astring .. string.rep('\0', fillbits)
end
function encode_int(num)
return pack("> i4",{ num })
end
function encode_blob(blob)
return encode_int(#blob) .. encode_string(#blob)
end
function encode_timetag(tpoint)
if tpoint == 0 then
return IMMEDIATE
else
local sec = math.floor(tpoint)
local frac = tpoint - sec
return pack("> u4 > u4", {sec + ADJUSTMENT_FACTOR , encode_frac(frac)})
end
end
function encode_frac(num)
local bin = ""
local frac = num
while #bin < 32 do
bin = bin .. base.math.floor(frac * 2)
frac = (frac * 2) - base.math.floor(frac * 2)
end
return bin
end
function encode_float(num)
return pack("> f4", {num})
end

View File

@ -0,0 +1,3 @@
osc = {}
require "LICK/lib/loveosc/client"
require "LICK/lib/loveosc/server"

View File

@ -0,0 +1,81 @@
--[[
-- luaosc Copyright (C) 2009 Jost Tobias Springenberg <k-gee@wrfl.de> --
This file is part of luaosc.
luaosc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
luaosc 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
--]]
-- This is a luaOSC Fork from Jost Tobias Springenberg, additional code and modifications by Tilmann Hars, Headchant.com, Copyright 2010
require "socket"
osc.server = {}
osc.server.host = "localhost"
osc.server.port = 7771
osc.server.socket = socket.udp() or error('error could not create lua socket object')
osc.server.socket:setsockname(osc.server.host, osc.server.port)
osc.server.socket:settimeout(0)
-- call this in LÖVE update
function osc.server:update(dt)
local message, from = osc.server.socket:receive(1024)
-- invoke handler function
if message ~= nil then
local success, result = pcall(decode, message)
if not success then
print("Error in decoding: \n" .. result)
else
success, result = pcall(handle, from, result)
if not success then
print("Error in your handler function: \n" .. result)
end
end
end
if message == "exit" then
return
end
end
-- use this to start the server in lua only (not with LÖVE!)
function osc.server:start()
local length = 1024
while 1 do
local message, from = self.socket:receivefrom(1024)
-- invoke handler function
if message ~= nil then
local success, result = base.pcall(osc.decode, message)
if not success then
base.io.stderr:write("Error in decoding: \n" .. result)
else
success, result = base.pcall(self.handle, from, result)
if not success then
base.io.stderr:write("Error in your handler function: \n" .. result)
end
end
end
if message == "exit" then
return
end
end
end
function osc.server:setHandler(hdle)
handle = hdle
end

View File

@ -0,0 +1,30 @@
1.0
---
Bugfixes to read error handling
Ability to return unpacked values rather than tables
1.0 beta 4
----------
Added the ability to say 's' with no width to read until EOF.
Modified struct.unpack and struct.pack to return the number of bytes
read/written as a second value. Note that this is not the same as the r/w
pointer delta if seeks are involved.
1.0 beta 3
----------
Lots of bugfixing and general cleanup
Improved error reporting
API name changes
1.0 beta 2
----------
Added the counted string format "c".
Added float and double support, courtesy of Peter "Corsix" Cawley.
Updated the test framework.
Fixed a bug in format m that could result in data loss when manipulating fields
of 7 bytes or more width.
1.0 beta 1
----------
Released to the world.

View File

@ -0,0 +1,19 @@
Copyright © 2008 Ben "ToxicFrog" Kelly
FP module copyright © 2008 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,290 @@
Contents
========
1. Overview
2. API
3. Warning!
4. The Format String
Naming
Grouping
Repetition
5. Format Specifiers
6. Credits
1. Overview
===========
VStruct is a library for Lua 5.1. It provides functions for manipulating binary
data, in particular for unpacking binary files or byte buffers into Lua values
and for packing Lua values back into files or buffers. Supported data types
include:
- signed and unsigned integers of arbitrary byte width
- booleans and bitmasks
- plain and null-terminated strings
- fixed and floating point reals (the latter requires C module support)
In addition, the library supports seeking, alignment, and byte order controls,
repetition, grouping of data into tables, and naming of values within tables.
2. API
======
exports:
vstruct.pack(fmt, [fd], data)
vstruct.unpack(fmt, <fd or string>, [unpacked])
vstruct.explode(int)
vstruct.implode(table)
vstruct.cursor(string)
vstruct.compile.read(format)
vstruct.compile.write(format)
pack takes a format string and a table of data and packs the contents into a
buffer. If the fd argument is present, it will write the data directly to it
using standard file io methods (write and seek), and return the fd; otherwise
it will construct and return a string. In either case it also returns (as a
second value) the number of bytes written - note that if the format involved
seeks, this is not the same as the amount by which the write pointer moved
or the size of the packed string.
unpack takes a format string and a buffer or file to unpack from, and returns
the unpacked data as a table. It also returns (as a second value) the number of
bytes read - note that if the format string involved seeks, this is not the same
as the difference between read pointer positions. If the _unpacked_ argument is
true, it will return the unpacked data as a series of values rather than as a
table, equivalent to using the standard Lua function unpack() on the return
value. Note that this means it will not return the number of bytes read as an
additional value.
explode converts a bitmask into a list of booleans, and implode does the
converse. In such lists, list[1] is the least significant bit, and list[n] the
most significant.
cursor wraps a string in something that looks, at first glance, like a file.
This permits strings to be wrapped and passed to the vstruct IO functions. The
wrapped string supports :seek, and has limited support for :read (the only
supported calling mode is :read(num_bytes)) and :write (as :write(buffer)).
compile.read takes a format string and returns a function, which can later be
passed a file (or file-like object - see vstruct.cursor) to perform a read
operation. In effect, the following code:
f = vstruct.compile.read(fmt)
d = f(fd)
Is equivalent to:
d = vstruct.unpack(fd, fmt)
f can of course be called repeatedly, with different or the same fds each time.
compile.write is the converse of compile.read. The emitted function expects a
file and a table of data elements, so that:
f = vstruct.compile.write(fmt)
f(fd, data)
Is equivalent to:
vstruct.pack(fd, fmt, data)
As with compile.read, the emitted function is fully re-usable.
3. Warning!
===========
When reading and writing numeric formats, vstruct is inherently limited by lua's
number format, which is by default the IEEE 754 double. What this means in
practice is that formats cipPu may be subject to data loss when read in widths
of 7 bytes or more, if they contain more than 52 significant bits. (The same is
true of numeric constants declared in Lua itself, of course, and other libraries
which store values in lua numbers).
Formats bfmsxz are unaffected by this, as they either do not use lua numbers or
are guaranteed to fit inside them.
4. The Format String
====================
The format string contains any number of endianness controls, seek controls,
format specifiers, and grouping/naming sequences, seperated by whitespace,
commas, or semicolons (or any mix thereof, although you are encouraged to choose
one and stick to it for the sake of consistency). Each of these is detailed
below.
In the documentation below, the convention is that A represents an address and W
a width in bytes. At present only base-10 numerals are supported.
Naming
------
Under normal operation, when unpacking, the library simply stores unpacked
values sequentially into a list, which is returned. Similarly, when packing, it
expects a list of values which will be packed in order. However, values can be
named, in which case the unpacked value will be stored in a field with that
name, and when packing, it will use the value stored with that key. This is done
by prefixing the format specifier with the name (which can be any sequence of
letters, numbers, and _, provided it does not start with a number) followed by a
':'. For example, the following format would generate a table with three keys,
'x', 'y', and 'z':
"x:u4 y:u4 z:u4"
And, when packing, would expect a table with those three keys and store their
corresponding values.
If the same name is specified multiple times, or is combined with repetition
(see below), only the last read value is stored there.
Named and anonymous values can be freely mixed; the named values will be
assigned to their given fields and the anonymous ones to sequential indices.
Grouping
--------
Rather than generating or expecting a flat table, the library can be instructed to
create or read from a table containing subtables. This is done by surrounding the
group of values you wish to be packed with '{' and '}' in the format string. For example,
the following format string:
"{ u4 i4 } { s32 u4 }"
Would, rather than generating a list of four values, generate a list containing two
lists of two values each.
Similarly, when packing, it would expect not a flat list, but a list of sublists, from
which the values to be packed will be drawn.
Groups can be named, so formats like:
"flags:m1 coords:{ x:u4 y:u4 z:u4 }"
Are permitted and meaningful.
Repetition
----------
A {} group can be repeated by prefixing or suffixing it with a count, seperated
from the group by a '*'. For example:
"4 * { u4 }"
"{ u4 } * 4"
"{ u4 } { u4 } { u4 } { u4 }"
Are all equivalent. Note that the whitespace in the above examples is optional.
In cases where you want to repeat format specifiers without implying a grouping,
you can use (). For example:
"4 * (u4 b1)"
Is equivalent to:
"u4 b1 u4 b1 u4 b1 u4"
Like grouping, these can be nested.
5. Format Specifiers
====================
Endianness Controls
-------------------
The formats i, m, and u are affected by the endianness setting, which controls
the order in which bytes are read and written within a field. The following
characters in a format string adjust the endianness setting:
<
Sets the endianness to little-endian (eg, Intel processors)
>
Sets the endianness to big-endian (eg, PPC and Motorola processors)
=
Sets the endianness to the native endianness.
Seek Controls
-------------
These characters are used to seek to specific locations in the input or output.
Note that they only work on buffers or file-like objects that support the seek()
method; for streams which cannot be sought on, use the 'x' (skip/null-pad)
data format instead.
@A
Seek to absolute address A.
+A
Seek forward A bytes.
-A
Seek backwards A bytes.
aW
Align to word width W (ie, seek to the next address which is a multiple of W)
Data Format Specifiers
----------------------
bW Boolean.
Read: as uW, but returns true if the result is non-zero and false otherwise.
Write: as uW with input 1 if true and 0 otherwise.
cW Counted string.
Read: uW to determine the length of the string W', followed by sW'.
Write: the length of the string as uW, followed by the string itself.
The counted string is a common idiom where a string is immediately prefixed
with its length, as in:
size_t len;
char[] str;
The counted string format can be used to easily read and write these. The
width provided is the width of the len field, which is treated as an
unsigned int. Only the string itself is returned (when unpacking) or
required (when packing).
The len field is affected by endianness, as in format u.
fW IEEE 754 floating point.
Valid widths are 4 (float) and 8 (double). No quads yet, sorry!
Affected by endianness.
iW Signed integer.
Read: a signed integer of width W bytes.
Write: a signed integer of width W bytes.
Floating point values will be truncated.
Affected by endianness.
mW Bitmask.
Read: as uW, but explodes the result into a list of booleans, one per bit.
Write: implodes the input value, then writes it as uW.
Affected by endianness.
See also: vstruct.implode, vstruct.explode.
pW Signed fixed point rational.
Width is in the format "I.F"; the value before the dot is the number of
bytes in the integer part, and the value after, in the fractional part.
Read: a fixed point rational of I+F bytes.
Write: a fixed point rational of I+F bytes. Values which cannot be exactly
represented in the specified width are truncated.
Affected by endianness.
PW Signed fixed point rational with bit-aligned subfields
Equivalent to pW, except that the decimal point does not need to be byte
aligned; for example, formats such as P20.12 are possible.
Note that underlying reads must still occur in byte multiples. Using a W
such that I+F is not a multiple of 8 is an error.
sW String.
Read: reads exactly W bytes and returns them as a string. If W is omitted,
reads until EOF.
Write:
If W is omitted, uses the string length.
If W is shorter than the string length, truncates the string.
If W is greater than the string length, null pads the string.
uW Unsigned integer.
Read: an unsigned integer of width W bytes.
Write: an unsigned integer of width W bytes.
Floating point values will be truncated.
Negative values will be taken absolute.
Affected by endianness.
xW Skip/pad.
Read: read and discard the next W bytes.
Write: write W zero bytes.
zW Null terminated string.
Read: reads exactly W bytes. Returns everything up to the first zero byte.
If W is omitted, reads up to the next zero byte.
Write: writes exactly W bytes.
If the input is shorter than W, zero pads the output.
If as long or longer, truncates to W-1 and writes a zero byte at the end.
If W is omitted, uses the string length plus one (ie, writes the string
out entire and then null terminates it).
6. Credits
==========
While most of the library code was written by me (Ben Kelly), the existence
of this library owes itself to many others:
The floating point code was contributed by Peter Cawley on lua-l.
The original inspiration came from Roberto Ierusalimschy's "struct" library
and Luiz Henrique de Figueiredo's "lpack" library, as well as the "struct"
available in Python.
sanooj, from #lua, has done so much testing and bug reporting that at this
point he's practically a co-author.
The overall library design and interface are the result of much discussion
with rici, sanooj, Keffo, snogglethorpe, Spark, kozure, Vornicus, McMartin, and
probably several others I've forgotten about on IRC (#lua on freenode and #code
on nightstar).
Finally, without Looking Glass Studios to make System Shock, and Team TSSHP
(in particular Jim "hairyjim" Cameron) to reverse engineer it, I wouldn't have
had a reason to write this library in the first place.

View File

@ -0,0 +1,48 @@
-- shared formats - seeking, endianness
-- these should all return nil so that they do not mutate the data list
-- Copyright © 2008 Ben "ToxicFrog" Kelly; see COPYING
local common = {}
-- determine if the host system is big-endian or not, by dumping an empty
-- function and looking at the endianness flag
-- this is kind of hackish
local function bigendian()
return string.byte(string.dump(function() end)) == string.char(0x00)
end
common.is_bigendian = bigendian()
-- seek controls
function common.seekto(fd, w)
fd:seek("set", w)
end
function common.seekforward(fd, w)
fd:seek("cur", w)
end
function common.seekback(fd, w)
fd:seek("cur", -w)
end
function common.a(fd,w)
local a = fd:seek()
if a % w ~= 0 then
fd:seek("cur", w - (a % w))
end
end
-- endianness controls
function common.littleendian(fd, w)
common.is_bigendian = false
end
function common.bigendian(fd, w)
common.is_bigendian = true
end
function common.hostendian(fd, w)
common.is_bigendian = bigendian()
end
return common

View File

@ -0,0 +1,134 @@
-- functions for turning a format string into a callable function
-- they work by calling parse(), passing it the format string and
-- a table of code generators appropriate for whether we are reading
-- or writing.
-- The resulting code is then prefixed with some setup code and postfixed
-- with a return value and loadstring() is called on it to generate a function
-- Copyright <20> 2008 Ben "ToxicFrog" Kelly; see COPYING
local require,loadstring,setfenv,type,select,unpack,setmetatable
= require,loadstring,setfenv,type,select,unpack,setmetatable
local print,assert,error,xpcall,pairs,where
= print,assert,error,xpcall,pairs,debug.traceback
module((...))
local parse = require(_PACKAGE.."parser")
local function nulsafe_error(s)
return error(s:gsub('%z', '_'))
end
local function xpcall2(f, err, ...)
local args = {n=select('#', ...), ...}
return xpcall(function() return f(unpack(args, 1, args.n)) end, err)
end
local function err_generate(message, format, trace)
nulsafe_error([[
struct: internal error in code generator
This is an internal error in the struct library
Please report it as a bug and include the following information:
-- error message
]]..message.."\n\n"..[[
-- format string
]]..format.."\n\n"..[[
-- stack trace
]]..trace)
end
local function err_compile(message, format, source)
nulsafe_error([[
struct: syntax error in emitted lua source
This is an internal error in the struct library
Please report it as a bug and include the following information:
-- loadstring error
]]..message.."\n\n"..[[
-- format string
]]..format.."\n\n"..[[
-- emitted source
]]..source.."\n\n"..[[
-- stack trace
]])
end
local function err_execute(message, format, source, trace)
nulsafe_error([[
struct: runtime error in generated function
This is at some level an internal error in the struct library
It could be a genuine error in the emitted code (in which case this is a code
generation bug)
Alternately, it could be that you gave it a malformed format string, a bad
file descriptor, or data that does not match the given format (in which case
it is an argument validation bug and you should be getting an error anyways).
Please report this as a bug and include the following information:
-- execution error
]]..message.."\n\n"..[[
-- format string
]]..format.."\n\n"..[[
-- emitted source
]]..source.."\n\n"..[[
-- stack trace
]]..trace)
end
local function compile(format, gen, env)
local status,source = xpcall(function()
return parse(format, gen, true)
end,
function(message)
return { message, where("",2) }
end)
if not status then
if type(source[1]) == "function" then
error(source[1]()..source[2])
end
err_generate(source[1], format, source[2])
end
local fn,err = loadstring(source)
if not fn then
err_compile(err, format, source)
end
setfenv(fn, env)
local fn = function(...)
local status,ret,len = xpcall2(fn, function(message)
return { message, where("",2) }
end, ...)
-- call succeeded without errors
if status then return ret,len end
local message,where = ret[1],ret[2]
-- call generated a deliberate error; call the provided closure
-- it will either emit an error code or re-throw
if type(message) == "function" then return nil,message() end
-- call generated an internal error; re-throw with extra debug info
err_execute(message, format, source, where)
end
return fn
end
local gen_unpack = require(_PACKAGE.."gen_unpack")
local io_unpack = require(_PACKAGE.."io_unpack")
function _M.unpack(format)
return compile(format, gen_unpack, io_unpack)
end
local gen_pack = require(_PACKAGE.."gen_pack")
local io_pack = require(_PACKAGE.."io_pack")
function _M.pack(format)
return compile(format, gen_pack, io_pack)
end
return _M

View File

@ -0,0 +1,80 @@
-- cursor - a wrapper for strings that makes them look like files
-- exports: seek read write
-- read only supports numeric amounts
-- Copyright © 2008 Ben "ToxicFrog" Kelly; see COPYING
local cursor = {}
-- like fseek
-- seeking past the end of the string is permitted
-- reads will return EOF, writes will fill in the intermediate space with nuls
-- seeking past the start of the string is a soft error
function cursor:seek(whence, offset)
whence = whence or "cur"
offset = offset or 0
if whence == "set" then
self.pos = offset
elseif whence == "cur" then
self.pos = self.pos + offset
elseif whence == "end" then
self.pos = #self.str + offset
else
error "bad argument #1 to seek"
end
if self.pos < 0 then
self.pos = 0
return nil,"attempt to seek prior to start of file"
end
return self.pos
end
-- read n bytes from the current position
-- reads longer than the string can satisfy return as much as it can
-- reads while the position is at the end return nil,"eof"
function cursor:read(n)
if self.pos >= #self.str then
return nil,"eof"
end
if n == "*a" then
n = #self.str
end
local buf = self.str:sub(self.pos+1, self.pos + n)
self.pos = math.min(self.pos + n, #self.str)
return buf
end
-- write the contents of the buffer at the current position, overwriting
-- any data already present
-- if the write pointer is past the end of the string, also fill in the
-- intermediate space with nuls
function cursor:write(buf)
if self.pos > #self.str then
self.str = self.str .. string.char(0):rep(self.pos - #self.str)
end
self.str = self.str:sub(1, self.pos)
.. buf
.. self.str:sub(self.pos + #buf + 1, -1)
self.pos = self.pos + #buf
return self
end
function cursor:__call(source)
assert(type(source) == "string", "invalid first argument to cursor()")
return setmetatable(
{ str = source, pos = 0 },
cursor)
end
cursor.__index = cursor
setmetatable(cursor, cursor)
return cursor

View File

@ -0,0 +1,121 @@
-- floating point module
-- Copyright © 2008 Peter "Corsix" Cawley and Ben "ToxicFrog" Kelly; see COPYING
local fp = {}
local name = (...):gsub('%.[^%.]+$', '')
local struct = require (name)
local common = require (name..".common")
local function reader(data, size_exp, size_fraction)
local fraction, exponent, sign
local endian = common.is_bigendian and ">" or "<"
-- Split the unsigned integer into the 3 IEEE fields
local bits = struct.unpack(endian.."m"..#data, data, true)
local fraction = struct.implode({unpack(bits, 1, size_fraction)}, size_fraction)
local exponent = struct.implode({unpack(bits, size_fraction+1, size_fraction+size_exp)}, size_exp)
local sign = bits[#bits] and -1 or 1
-- special case: exponent is all 1s
if exponent == 2^size_exp-1 then
-- significand is 0? +- infinity
if fraction == 0 then
return sign * math.huge
-- otherwise it's NaN
else
return 0/0
end
end
-- restore the MSB of the significand, unless it's a subnormal number
if exponent ~= 0 then
fraction = fraction + (2 ^ size_fraction)
else
exponent = 1
end
-- remove the exponent bias
exponent = exponent - 2 ^ (size_exp - 1) + 1
-- Decrease the size of the exponent rather than make the fraction (0.5, 1]
exponent = exponent - size_fraction
return sign * math.ldexp(fraction, exponent)
end
local function writer(value, size_exp, size_fraction)
local fraction, exponent, sign
local width = (size_exp + size_fraction + 1)/8
local endian = common.is_bigendian and ">" or "<"
local bias = 2^(size_exp-1)-1
if value < 0
or 1/value == -math.huge then -- handle the case of -0
sign = true
value = -value
else
sign = false
end
-- special case: value is infinite
if value == math.huge then
exponent = bias+1
fraction = 0
-- special case: value is NaN
elseif value ~= value then
exponent = bias+1
fraction = 2^(size_fraction-1)
--special case: value is 0
elseif value == 0 then
exponent = -bias
fraction = 0
else
fraction,exponent = math.frexp(value)
-- subnormal number
if exponent+bias <= 1 then
fraction = fraction * 2^(size_fraction+(exponent+bias)-1)
exponent = -bias
else
-- remove the most significant bit from the fraction and adjust exponent
fraction = fraction - 0.5
exponent = exponent - 1
-- turn the fraction into an integer
fraction = fraction * 2^(size_fraction+1)
end
end
-- add the exponent bias
exponent = exponent + bias
local bits = struct.explode(fraction)
local bits_exp = struct.explode(exponent)
for i=1,size_exp do
bits[size_fraction+i] = bits_exp[i]
end
bits[size_fraction+size_exp+1] = sign
return struct.pack(endian.."m"..width, {bits})
end
-- Create readers and writers for the IEEE sizes
fp.sizes = {
[4] = {1, 8, 23},
[8] = {1, 11, 52},
}
fp.r = {}
fp.w = {}
for width, sizes in pairs(fp.sizes) do
fp.r[width] = function(uint) return reader(uint, sizes[2], sizes[3]) end
fp.w[width] = function(valu) return writer(valu, sizes[2], sizes[3]) end
end
return fp

View File

@ -0,0 +1,132 @@
local require,table
= require,table
module((...))
local parse = require(_PACKAGE.."parser")
local gen = {}
gen.preamble = [[
local fd,data = ...
local stack = {}
local index = 1
local start = fd:seek()
local len = 0
local function push(key)
if not key then
key = index
index = index + 1
end
stack[#stack+1] = { index, data }
data = data[key]
index = 1
end
local function pop(key)
local saved = stack[#stack]
stack[#stack] = nil
index = saved[1]
data = saved[2]
end
local function update_len()
len = len + fd:seek() - start
end
local function update_start()
start = fd:seek()
end
hostendian()
]]
gen.postamble = [[
update_len()
return fd,len
]]
-- control:
-- <<type>>(fd, <<args>>)
function gen.control(token)
local tr = {
["<"] = "littleendian";
[">"] = "bigendian";
["="] = "hostendian";
["+"] = "seekforward";
["-"] = "seekback";
["@"] = "seekto";
}
local fn = tr[token[1]] or token[1]
local args = token[2]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return "update_len(); "..fn.."(fd, "..args..")".."; update_start()"
end
-- atom:
-- <<type>>(fd, data[index], <<args>>)
-- ++index
function gen.atom(token)
local fn = token[1]
local args = token[2]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return fn.."(fd, data[index], "..args..")\nindex = index+1"
end
-- table:
-- push()
-- <<table contents>>
-- pop()
function gen.table(token)
return "push()\n"
..parse(token[1]:sub(2,-2), gen)
.."\npop()"
end
-- group:
-- <<group contents>>
function gen.group(token)
return parse(token[1]:sub(2,-2), gen)
end
-- named atom:
-- <<type>>(fd, data.<<name>>, <<args>>)
function gen.name_atom(token)
local fn = token[2]
local args = token[3]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return fn.."(fd, data."..token[1]..", "..args..")"
end
-- named table:
-- push(<<name>>)
-- <<table contents>>
-- pop()
function gen.name_table(token)
return "push('"..token[1].."')\n"
..parse(token[2]:sub(2,-2), gen)
.."\npop()"
end
function gen.prerepeat(token, get)
local next = get()
local src = gen[next.type](next, get)
return "for _idx=1,"..token[1].." do\n\n"..src.."\nend"
end
function gen.postrepeat(token, get, asl)
local src = table.remove(asl)
return "for _idx=1,"..token[1].." do\n\n"..src.."\nend"
end
return gen

View File

@ -0,0 +1,117 @@
local require,table
= require,table
module((...))
local parse = require(_PACKAGE.."parser")
local gen = {}
gen.preamble = [[
local fd = (...)
local stack = {}
local pack = {}
local start = fd:seek()
local len = 0
local function push()
stack[#stack+1],pack = pack,{}
end
local function pop(key)
local target = stack[#stack]
key = key or #target+1
target[key],pack = pack,target
stack[#stack] = nil
end
local function update_len()
len = len + fd:seek() - start
end
local function update_start()
start = fd:seek()
end
hostendian()
]]
gen.postamble = [[
update_len()
return pack,len
]]
-- control:
-- <<type>>(fd, <<args>>)
function gen.control(token)
local tr = {
["<"] = "littleendian";
[">"] = "bigendian";
["="] = "hostendian";
["+"] = "seekforward";
["-"] = "seekback";
["@"] = "seekto";
}
local fn = tr[token[1]] or token[1]
local args = token[2]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return "update_len(); "..fn.."(fd, "..args..")".."; update_start()"
end
-- atom:
-- pack[#pack+1] = <<type>>(fd, <<args>>)
function gen.atom(token)
local fn = token[1]
local args = token[2]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return "pack[#pack+1] = "..fn.."(fd, "..args..")"
end
-- table:
-- push()
-- <<table contents>>
-- pop()
function gen.table(token)
return "push()\n"
..parse(token[1]:sub(2,-2), gen)
.."\npop()"
end
-- group:
-- <<group contents>>
function gen.group(token)
return parse(token[1]:sub(2,-2), gen)
end
function gen.name_atom(token)
local fn = token[2]
local args = token[3]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return "pack."..token[1].." = "..fn.."(fd, "..args..")"
end
function gen.name_table(token)
return "push()\n"
..parse(token[2]:sub(2,-2), gen)
.."\npop('"..token[1].."')\n"
end
function gen.prerepeat(token, get)
local next = get()
local src = gen[next.type](next, get)
return "for _idx=1,"..token[1].." do\n\n"..src.."\nend"
end
function gen.postrepeat(token, get, asl)
local src = table.remove(asl)
return "for _idx=1,"..token[1].." do\n\n"..src.."\nend"
end
return gen

View File

@ -0,0 +1,94 @@
-- vstruct, the versatile struct library
-- Copyright <20> 2008 Ben "ToxicFrog" Kelly; see COPYING
local table,math,type,require,assert,_unpack = table,math,type,require,assert,unpack
local print = print
module((...))
cursor = require (_NAME..".cursor")
compile = require (_NAME..".compile")
function math.trunc(n)
if n < 0 then
return math.ceil(n)
else
return math.floor(n)
end
end
-- turn an int into a list of booleans
-- the length of the list will be the smallest number of bits needed to
-- represent the int
function explode(int, size)
assert(int, "struct.explode: missing argument")
size = size or 0
local mask = {}
while int ~= 0 or #mask < size do
table.insert(mask, int % 2 ~= 0)
int = math.trunc(int/2)
end
return mask
end
-- turn a list of booleans into an int
-- the converse of explode
function implode(mask, size)
size = size or #mask
local int = 0
for i=size,1,-1 do
int = int*2 + ((mask[i] and 1) or 0)
end
return int
end
-- given a source, which is either a string or a file handle,
-- unpack it into individual data based on the format string
function unpack(fmt, source, untable)
-- wrap it in a cursor so we can treat it like a file
if type(source) == 'string' then
source = cursor(source)
end
assert(fmt and source and type(fmt) == "string", "struct: invalid arguments to unpack")
-- the lexer will take our format string and generate code from it
-- it returns a function that when called with our source, will
-- unpack the data according to the format string and return all
-- values from said unpacking in a list
if untable then
--local t = compile.unpack(fmt)(source)
--print(t)
-- print(_unpack(t))
return _unpack((compile.unpack(fmt)(source)))
else
return compile.unpack(fmt)(source)
end
end
-- given a format string and a list of data, pack them
-- if 'fd' is omitted, pack them into and return a string
-- otherwise, write them directly to the given file
function pack(fmt, fd, data)
local str_fd
if not data then
data = fd
fd = ""
end
if type(fd) == 'string' then
fd = cursor("")
str_fd = true
end
assert(fmt and fd and data and type(fmt) == "string", "struct: invalid arguments to pack")
local fd,len = compile.pack(fmt)(fd, data)
return (str_fd and fd.str) or fd,len
end
return struct

View File

@ -0,0 +1,127 @@
-- write formats
-- return true if they have consumed a value from the input stream
-- return false/nil otherwise (ie, the next value will be preserved
-- for subsequent calls, eg skip/pad)
-- Copyright © 2008 Ben "ToxicFrog" Kelly; see COPYING
local require,error,setmetatable,string,print,math,unpack,io
= require,error,setmetatable,string,print,math,unpack,io
module((...))
local struct = require (_PACKAGE:sub(1,-2))
local common = require (_PACKAGE.."common")
local fp = require (_PACKAGE.."fp")
local pack = setmetatable({}, { __index = common })
-- boolean
function pack.b(fd, d, w)
return pack.u(fd, (d and 1) or 0, w)
end
-- counted string
-- a string immediately prefaced with its length as a uint
function pack.c(fd, d, w)
pack.u(fd, #d, w)
return pack.s(fd, d)
end
-- floating point
function pack.f(fd, d, w)
if not fp.w[w] then
error("struct.pack: illegal floating point width")
end
-- local f = fp.w[w](d)
-- print(f, type(f))
return pack.s(fd, fp.w[w](d), w)
end
-- signed int
function pack.i(fd, d, w)
if d < 0 then
d = 2^(w*8) + d
end
return pack.u(fd, d, w)
end
-- bitmask
-- we use a string here because using an unsigned will lose data on bitmasks
-- wider than lua's native number format
function pack.m(fd, d, w)
local buf = ""
for i=1,w*8,8 do
local bits = { unpack(d, i, i+7) }
local byte = string.char(struct.implode(bits, 8))
if pack.is_bigendian then
buf = byte..buf
else
buf = buf..byte
end
end
return pack.s(fd, buf, w)
end
-- fixed point bit aligned
function pack.P(fd, d, dp, fp)
if (dp+fp) % 8 ~= 0 then
error "total width of fixed point value must be byte multiple"
end
return pack.i(fd, d * 2^fp, (dp+fp)/8)
end
-- fixed point byte aligned
function pack.p(fd, d, dp, fp)
return pack.P(fd, d, dp*8, fp*8)
end
-- fixed length string
-- length 0 is write string as is
-- length >0 is write exactly w bytes, truncating or padding as needed
function pack.s(fd, d, w)
w = w or #d
if w == 0 then return end
if #d < w then
d = d..string.char(0):rep(w-#d)
end
return fd:write(d:sub(1,w))
end
-- unsigned int
function pack.u(fd, d, w)
local s = ""
for i=1,w do
if pack.is_bigendian then
s = string.char(d % 2^8) .. s
else
s = s .. string.char(d % 2^8)
end
d = math.trunc(d/2^8)
end
return pack.s(fd, s, w)
end
-- skip/pad
-- this is technically a control format, so it has a different signature
-- specifically, there is no "data" argument
function pack.x(fd, w)
return pack.s(fd, "", w)
end
-- null terminated string
-- w==nil is write string as is + termination
-- w>0 is write exactly w bytes, truncating/padding and terminating
function pack.z(fd, d, w)
w = w or #d+1
if #d >= w then
d = d:sub(1, w-1)
end
return pack.s(fd, d.."\0", w)
end
return pack

View File

@ -0,0 +1,165 @@
-- read formats
-- return a value if applicable, which will be packed
-- otherwise return nil
-- Copyright <20> 2008 Ben "ToxicFrog" Kelly; see COPYING
-- load operations common to both unpack and pack, and set __index so that
-- requests for, say, unpack.seekto will succeed
local require,error,setmetatable,string,print
= require,error,setmetatable,string,print
module((...))
local struct = require (_PACKAGE:sub(1,-2))
local common = require (_PACKAGE.."common")
local fp = require (_PACKAGE.."fp")
local unpack = setmetatable({}, { __index = common })
-- boolean
-- true if any bit is 1, false otherwise
function unpack.b(fd, w)
return unpack.u(fd, w) ~= 0
end
-- counted string
-- a string immediately prefaced with its length as a uint
function unpack.c(fd, w)
w = unpack.u(fd, w)
return unpack.s(fd, w)
end
-- float
-- this is callout to the floating-point read/write module, if installed
function unpack.f(fd, w)
if not fp.r[w] then
error("struct.unpack: illegal floating point width")
end
return fp.r[w](unpack.s(fd,w))
end
-- utility functions for the i, m and u formats
local function directions(w)
if unpack.is_bigendian then
return 1,w,1
else
return w,1,-1
end
end
local function pve_unpack(buf, w)
local i,sof,eof,dir = 0,directions(w)
for c=sof,eof,dir do
i = i * 2^8 + buf:byte(c)
end
return i
end
local function nve_unpack(buf, w)
local i,sof,eof,dir = 0,directions(w)
if buf:byte(sof) < 128 then
return pve_unpack(buf, w)
end
for c=sof,eof,dir do
i = i * 2^8 - (255 - buf:byte(c))
end
return i-1
end
-- signed int of w bytes
function unpack.i(fd, w)
local buf = unpack.s(fd, w)
return nve_unpack(buf, w)
end
-- bitmask of w bytes
-- we need to read and unpack it as a string, not an unsigned, because otherwise
-- we're limited to 52 bits
function unpack.m(fd, w)
local buf = unpack.s(fd, w)
local mask = {}
local sof,eof,dir = directions(w)
-- reverse it here because directions() returns numbers for MSB first,
-- and we want LSB first
for i=eof,sof,-dir do
local byte = buf:byte(i)
local bits = struct.explode(byte)
for j=1,8 do
mask[#mask+1] = bits[j] or false
end
end
return mask
end
-- fixed point bit aligned
-- w is in the form d.f, where d is the number of bits in the integer part
-- and f the number of bits in the fractional part
function unpack.P(fd, dp, fp)
if (dp+fp) % 8 ~= 0 then
error "total width of fixed point value must be byte multiple"
end
return unpack.i(fd, (dp+fp)/8)/(2^fp)
end
-- fixed point byte aligned
function unpack.p(fd, dp, fp)
return unpack.P(fd, dp*8, fp*8)
end
-- string
-- reads exactly w bytes of data and returns them verbatim
function unpack.s(fd, w)
if w == 0 then return "" end
local buf,err = fd:read(w or "*a")
if not buf then
error(function() return "read error: "..(err or "(unknown error)") end)
elseif #buf < w then
error(function() return "short read: wanted "..w.." bytes, got "..#buf end)
end
return buf
end
-- unsigned int
function unpack.u(fd, w)
local buf,err = unpack.s(fd, w)
return pve_unpack(buf, w)
end
-- skip/pad
-- reads w bytes and discards them
function unpack.x(fd, w)
fd:read(w)
return true
end
-- null-terminated string
-- if w is omitted, reads up to and including the first nul, and returns everything
-- except that nul
-- otherwise, reads exactly w bytes and returns everything up to the first nul
function unpack.z(fd, w)
if w then
return unpack.s(fd, w):match('^%Z*')
end
local buf = ""
local c = unpack.s(fd, 1)
while #c > 0 and c ~= string.char(0) do
buf = buf..c
c = unpack.s(fd, 1)
end
return buf
end
return unpack

View File

@ -0,0 +1,54 @@
local lexis = {}
local function lexeme(name)
return function(pattern)
lexis[#lexis+1] = { name=name, pattern="^"..pattern }
end
end
lexeme (false) "%s+" -- whitespace
lexeme "table" "(%b{})"
lexeme "group" "(%b())"
lexeme "name_atom" "([%a_][%w_]*)%:(%a)([%d.]*)"
lexeme "name_table" "([%a_][%w_]*)%:(%b{})"
lexeme "prerepeat" "(%d+)%s*%*"
lexeme "postrepeat" "%*%s*(%d+)"
lexeme "control" "([-+@<>=ax])([%d.]*)"
lexeme "atom" "(%a)([%d.]*)"
return function(source)
local orig = source
local index = 1
local function iter()
if #source == 0 then return nil end
for _,lexeme in ipairs(lexis) do
if source:match(lexeme.pattern) then
local result = { source:find(lexeme.pattern) }
local eof = table.remove(result, 2)
table.remove(result, 1)
source = source:sub(eof+1, -1)
index = index+eof
if lexeme.name then
result.type = lexeme.name
coroutine.yield(result)
end
return iter()
end
end
error (function() return "Error lexing format string [["
..(orig)
.."]] at char "
..index
.." ("
..(source:sub(1,1))
..")"
end)
end
return coroutine.wrap(iter)
end

View File

@ -0,0 +1,35 @@
-- parser for format strings
-- you give it a format string, a table of code generators,
-- and a flag indicating whether to apply the preamble/postable
-- it gives you lua source
local require,concat = require,table.concat
local print = print
module((...))
local lex = require(_PACKAGE.."lexer")
return function(source, codegen, prepost)
local asl = {}
local get = lex(source)
for token in get do
-- seperate statements because codegen may change #asl
local code = codegen[token.type](token, get, asl)
asl[#asl+1] = code
end
local source = concat(asl, "\n")
if prepost then
source = codegen.preamble
.. source
.. codegen.postamble
end
return source
end

View File

@ -0,0 +1,218 @@
-- OBJECT.lua
-- object oriented livecoding library
_internal_object_table = {}
-- hump for classing
local Class = require "LICK/lib/hump/.class"
local hlpr = require "LICK/lib/hlpr"
require "LICK/lib/loveosc"
--[[
OBJECT
--]]
-- @Object: base class
Object = Class(function(self)
-- TODO: Object base code
table.insert(_internal_object_table, self)
end)
function Object:update(dt)
-- TODO: insert typical update
-- print("updated")
end
--[[
SCOBJECT
--]]
-- @SCObject: bass class for supercollider communication
SCObject = Class(function(self)
Object.construct(self)
end)
SCObject:inherit(Object)
--[[
SCSYNTH
--]]
-- @SCSynth: supercollider synthesizer class
SCSynth = Class(function(self, nodename, freq)
SCObject.construct(self)
self.nodename = nodename or "default"
self.freq = freq or 440
self.nodeid = 1000 + math.random(1000)
end)
SCSynth:inherit(SCObject)
-- #set a control, TODO: variable lenght of argument-pairs
function SCSynth:set(control, val)
local var = {
"#bundle",
os.time(),
{
"/n_set",
"i",
self.nodeid,
"s",
control,
"f",
val
}
}
osc.client:send(var)
--print("OUTGOING OSC MESSAGE")
end
--#sends an OSC message to the supercollider to start the synth
function SCSynth:play()
local var = {
"#bundle",
os.time(),
{
"/s_new",
"s",
self.nodename,
"i",
self.nodeid,
"i",
0,
"i",
0,
"s",
"freq",
"f",
self.freq
}
}
osc.client:send(var)
--print("OUTGOING OSC MESSAGE")
end
--#frees the node on the supercollider server
function SCSynth:free()
local var = {
"#bundle",
os.time()+0.8,
{
"/n_free",
"i",
self.nodeid,
"i",
0,
}
}
osc.client:send(var)
--print("OUTGOING OSC MESSAGE")
end
--[[
DRAWABLE
--]]
-- @Drawable: base class for all drawable stuff
Drawable = Class(function(self, x, y, color)
self.color = color or hlpr.color("white",255)
-- call constructor of Object class
Object.construct(self)
self.position = Vector(x,y)
self.pos = self.position
self.x = self.position.x
self.y = self.position.y
end)
Drawable:inherit(Object)
-- #can be called via wrapX(max) or wrapX(min,max)
function Drawable:wrapX(min, max)
if min and max then
self:wrap("x", min, max)
elseif min and not max then
self:wrap("x", 0, min)
end
end
-- #can be called via wrapY(max) or wrapY(min,max)
function Drawable:wrapY(min, max)
if min and max then
self:wrap("y", min, max)
elseif min and not max then
self:wrap("y", 0, min)
end
end
-- #internal wrapper
function Drawable:wrap(str, min, max)
if str == "x" then
self.position.x = hlpr.wrap(self.position.x, min, max)
elseif str == "y" then
self.position.y = hlpr.wrap(self.position.y, min, max)
end
end
-- #supercollider style 'set'
function Drawable:set(str, val)
if str == "x" then
self.position.x = val or self.position.x
elseif str == "y" then
self.position.y = val or self.position.y
end
-- TODO: add lots and lots and lots
end
-- #not yet implemented
function Drawable:draw()
-- TODO: abstract draw code...
end
--[[
CIRCLE
--]]
-- @Circle: drawable circle
Circle = Class(function(self, x, y, r, s, color)
self.r = r or 10
self.s = s or 16
-- call constructor of Drawable
Drawable.construct(self,x,y,color)
end)
Circle:inherit(Drawable)
-- #draw the circle
function Circle:draw(style)
if style ~= "fill" and style ~= "line" then
style = "line"
end
love.graphics.setColor(unpack(self.color))
love.graphics.circle(style, self.position.x, self.position.y, self.r, self.s)
end
--[[
LINE
--]]
-- @Line: draw a line
Line = Class(function(self, x, y, tx, ty)
self.tx = tx or 0
self.ty = ty or 0
-- call constructor of Drawable
Drawable.construct()
end)
Line:inherit(Object)
-- EXAMPLE:
-- (put in love.load):
-- coco = Circle(300,300)
-- (put in love.update):
-- coco:set("x", 30)
-- (put in love.draw):
-- coco:draw("fill")

View File

@ -0,0 +1,127 @@
-- lick.lua
--
-- simple LIVECODING environment with löve, overwrites love.run, suppressing errors to the terminal/console
lick = {}
lick.file = "main.lua"
lick.debug = false
lick.reset = false
lick.clearFlag = false
function handle(err)
return "ERROR: " .. err
end
function lick.setFile(str)
live.file = str or "lick.lua"
end
-- Initialization
function lick.load()
last_modified = 0
end
-- load the lickcoding file and execute the contained update function
function lick.update(dt)
if love.filesystem.exists(lick.file) and last_modified < love.filesystem.getLastModified(lick.file) then
last_modified = love.filesystem.getLastModified(lick.file)
success, chunk = pcall(love.filesystem.load, lick.file)
if not success then
print(tostring(chunk))
lick.debugoutput = chunk .. "\n"
end
ok,err = xpcall(chunk, handle)
if not ok then
print(tostring(err))
if lick.debugoutput then
lick.debugoutput = (lick.debugoutput .."ERROR: ".. err .. "\n" )
else lick.debugoutput = err .. "\n" end
end
if ok then
print("CHUNK LOADED\n")
lick.debugoutput = nil
end
if lick.reset then
loadok, err = xpcall(love.load, handle)
if not loadok and not loadok_old then
print("ERROR: "..tostring(err))
if lick.debugoutput then
lick.debugoutput = (lick.debugoutput .."ERROR: ".. err .. "\n" )
else lick.debugoutput = err .. "\n" end
loadok_old = not loadok
end
end
end
updateok, err = pcall(love.update,dt)
if not updateok and not updateok_old then
print("ERROR: "..tostring(err))
if lick.debugoutput then
lick.debugoutput = (lick.debugoutput .."ERROR: ".. err .. "\n" )
else lick.debugoutput = err .. "\n" end
end
updateok_old = not updateok
end
function lick.draw()
drawok, err = xpcall(love.draw, handle)
if not drawok and not drawok_old then
print(tostring(err))
if lick.debugoutput then
lick.debugoutput = (lick.debugoutput .. err .. "\n" )
else lick.debugoutput = err .. "\n" end
end
if lick.debug and lick.debugoutput then
love.graphics.setColor(255,255,255,120)
love.graphics.print(lick.debugoutput, 0, 0)
end
drawok_old = not drawok
end
function love.run()
if love.load then love.load(arg) end
lick.load()
local dt = 0
-- Main loop time.
while true do
if love.timer then
love.timer.step()
dt = love.timer.getDelta()
end
-- if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled
lick.update(dt)
if love.graphics then
if not lick.clearFlag then love.graphics.clear() end
-- if love.draw then love.draw() end
lick.draw()
end
-- Process events.
if love.event then
for e,a,b,c in love.event.poll() do
if e == "q" then
if not love.quit or not love.quit() then
if love.audio then
love.audio.stop()
end
return
end
end
love.handlers[e](a,b,c)
end
end
if love.timer then love.timer.sleep(1) end
if love.graphics then love.graphics.present() end
end
end

View File

@ -0,0 +1,21 @@
function love.conf(t)
t.modules.joystick = true -- Enable the joystick module (boolean)
t.modules.audio = true -- Enable the audio module (boolean)
t.modules.keyboard = true -- Enable the keyboard module (boolean)
t.modules.event = true -- Enable the event module (boolean)
t.modules.image = true -- Enable the image module (boolean)
t.modules.graphics = true -- Enable the graphics module (boolean)
t.modules.timer = true -- Enable the timer module (boolean)
t.modules.mouse = true -- Enable the mouse module (boolean)
t.modules.sound = true -- Enable the sound module (boolean)
t.modules.physics = true -- Enable the physics module (boolean)
t.console = false -- Attach a console (boolean, Windows only)
t.title = "live_testproject" -- The title of the window the game is in (string)
t.author = "Tilmann Hars" -- The author of the game (string)
t.screen.fullscreen = false -- Enable fullscreen (boolean)
t.screen.vsync = true -- Enable vertical sync (boolean)
t.screen.fsaa = 0 -- The number of FSAA-buffers (number)
t.screen.height = 600 -- The window height (number)
t.screen.width = 800 -- The window width (number)
t.version = 0 -- The LÖVE version this game was made for (number)
end

View File

@ -0,0 +1,12 @@
require "LICK"
require "LICK/lib"
ez = require "LICK/lib/hlpr"
function love.load()
end
function love.update(dt)
end
function love.draw()
end

View File

@ -0,0 +1,3 @@
require "LICK/lick"

View File

@ -0,0 +1,742 @@
x11_color_table = {
-- taken from the SuperCollider Color documentation:
["alice blue"]={240, 248, 255},
["AliceBlue"]={240, 248, 255},
["antique white"]={250, 235, 215},
["AntiqueWhite"]={250, 235, 215},
["AntiqueWhite1"]={255, 239, 219},
["AntiqueWhite2"]={238, 223, 204},
["AntiqueWhite3"]={205, 192, 176},
["AntiqueWhite4"]={139, 131, 120},
["aquamarine"]={127, 255, 212},
["aquamarine1"]={127, 255, 212},
["aquamarine2"]={118, 238, 198},
["aquamarine3"]={102, 205, 170},
["aquamarine4"]={69, 139, 116},
["azure"]={240, 255, 255},
["azure1"]={240, 255, 255},
["azure2"]={224, 238, 238},
["azure3"]={193, 205, 205},
["azure4"]={131, 139, 139},
["beige"]={245, 245, 220},
["bisque"]={255, 228, 196},
["bisque1"]={255, 228, 196},
["bisque2"]={238, 213, 183},
["bisque3"]={205, 183, 158},
["bisque4"]={139, 125, 107},
["black"]={0, 0, 0},
["blanched almond"]={255, 235, 205},
["BlanchedAlmond"]={255, 235, 205},
["blue"]={0, 0, 255},
["blue violet"]={138, 43, 226},
["blue1"]={0, 0, 255},
["blue2"]={0, 0, 238},
["blue3"]={0, 0, 205},
["blue4"]={0, 0, 139},
["BlueViolet"]={138, 43, 226},
["brown"]={165, 42, 42},
["brown1"]={255, 64, 64},
["brown2"]={238, 59, 59},
["brown3"]={205, 51, 51},
["brown4"]={139, 35, 35},
["burlywood"]={222, 184, 135},
["burlywood1"]={255, 211, 155},
["burlywood2"]={238, 197, 145},
["burlywood3"]={205, 170, 125},
["burlywood4"]={139, 115, 85},
["cadet blue"]={95, 158, 160},
["CadetBlue"]={95, 158, 160},
["CadetBlue1"]={152, 245, 255},
["CadetBlue2"]={142, 229, 238},
["CadetBlue3"]={122, 197, 205},
["CadetBlue4"]={83, 134, 139},
["chartreuse"]={127, 255, 0},
["chartreuse1"]={127, 255, 0},
["chartreuse2"]={118, 238, 0},
["chartreuse3"]={102, 205, 0},
["chartreuse4"]={69, 139, 0},
["chocolate"]={210, 105, 30},
["chocolate1"]={255, 127, 36},
["chocolate2"]={238, 118, 33},
["chocolate3"]={205, 102, 29},
["chocolate4"]={139, 69, 19},
["coral"]={255, 127, 80},
["coral1"]={255, 114, 86},
["coral2"]={238, 106, 80},
["coral3"]={205, 91, 69},
["coral4"]={139, 62, 47},
["cornflower blue"]={100, 149, 237},
["CornflowerBlue"]={100, 149, 237},
["cornsilk"]={255, 248, 220},
["cornsilk1"]={255, 248, 220},
["cornsilk2"]={238, 232, 205},
["cornsilk3"]={205, 200, 177},
["cornsilk4"]={139, 136, 120},
["cyan"]={0, 255, 255},
["cyan1"]={0, 255, 255},
["cyan2"]={0, 238, 238},
["cyan3"]={0, 205, 205},
["cyan4"]={0, 139, 139},
["dark goldenrod"]={184, 134, 11},
["dark green"]={0, 100, 0},
["dark khaki"]={189, 183, 107},
["dark olive green"]={85, 107, 47},
["dark orange"]={255, 140, 0},
["dark orchid"]={153, 50, 204},
["dark salmon"]={233, 150, 122},
["dark sea green"]={143, 188, 143},
["dark slate blue"]={72, 61, 139},
["dark slate gray"]={47, 79, 79},
["dark slate grey"]={47, 79, 79},
["dark turquoise"]={0, 206, 209},
["dark violet"]={148, 0, 211},
["DarkGoldenrod"]={184, 134, 11},
["DarkGoldenrod1"]={255, 185, 15},
["DarkGoldenrod2"]={238, 173, 14},
["DarkGoldenrod3"]={205, 149, 12},
["DarkGoldenrod4"]={139, 101, 8},
["DarkGreen"]={0, 100, 0},
["DarkKhaki"]={189, 183, 107},
["DarkOliveGreen"]={85, 107, 47},
["DarkOliveGreen1"]={202, 255, 112},
["DarkOliveGreen2"]={188, 238, 104},
["DarkOliveGreen3"]={162, 205, 90},
["DarkOliveGreen4"]={110, 139, 61},
["DarkOrange"]={255, 140, 0},
["DarkOrange1"]={255, 127, 0},
["DarkOrange2"]={238, 118, 0},
["DarkOrange3"]={205, 102, 0},
["DarkOrange4"]={139, 69, 0},
["DarkOrchid"]={153, 50, 204},
["DarkOrchid1"]={191, 62, 255},
["DarkOrchid2"]={178, 58, 238},
["DarkOrchid3"]={154, 50, 205},
["DarkOrchid4"]={104, 34, 139},
["DarkSalmon"]={233, 150, 122},
["DarkSeaGreen"]={143, 188, 143},
["DarkSeaGreen1"]={193, 255, 193},
["DarkSeaGreen2"]={180, 238, 180},
["DarkSeaGreen3"]={155, 205, 155},
["DarkSeaGreen4"]={105, 139, 105},
["DarkSlateBlue"]={72, 61, 139},
["DarkSlateGray"]={47, 79, 79},
["DarkSlateGray1"]={151, 255, 255},
["DarkSlateGray2"]={141, 238, 238},
["DarkSlateGray3"]={121, 205, 205},
["DarkSlateGray4"]={82, 139, 139},
["DarkSlateGrey"]={47, 79, 79},
["DarkTurquoise"]={0, 206, 209},
["DarkViolet"]={148, 0, 211},
["deep pink"]={255, 20, 147},
["deep sky blue"]={0, 191, 255},
["DeepPink"]={255, 20, 147},
["DeepPink1"]={255, 20, 147},
["DeepPink2"]={238, 18, 137},
["DeepPink3"]={205, 16, 118},
["DeepPink4"]={139, 10, 80},
["DeepSkyBlue"]={0, 191, 255},
["DeepSkyBlue1"]={0, 191, 255},
["DeepSkyBlue2"]={0, 178, 238},
["DeepSkyBlue3"]={0, 154, 205},
["DeepSkyBlue4"]={0, 104, 139},
["dim gray"]={105, 105, 105},
["dim grey"]={105, 105, 105},
["DimGray"]={105, 105, 105},
["DimGrey"]={105, 105, 105},
["dodger blue"]={30, 144, 255},
["DodgerBlue"]={30, 144, 255},
["DodgerBlue1"]={30, 144, 255},
["DodgerBlue2"]={28, 134, 238},
["DodgerBlue3"]={24, 116, 205},
["DodgerBlue4"]={16, 78, 139},
["firebrick"]={178, 34, 34},
["firebrick1"]={255, 48, 48},
["firebrick2"]={238, 44, 44},
["firebrick3"]={205, 38, 38},
["firebrick4"]={139, 26, 26},
["floral white"]={255, 250, 240},
["FloralWhite"]={255, 250, 240},
["forest green"]={34, 139, 34},
["ForestGreen"]={34, 139, 34},
["gainsboro"]={220, 220, 220},
["ghost white"]={248, 248, 255},
["GhostWhite"]={248, 248, 255},
["gold"]={255, 215, 0},
["gold1"]={255, 215, 0},
["gold2"]={238, 201, 0},
["gold3"]={205, 173, 0},
["gold4"]={139, 117, 0},
["goldenrod"]={218, 165, 32},
["goldenrod1"]={255, 193, 37},
["goldenrod2"]={238, 180, 34},
["goldenrod3"]={205, 155, 29},
["goldenrod4"]={139, 105, 20},
["gray"]={190, 190, 190},
["gray0"]={0, 0, 0},
["gray1"]={3, 3, 3},
["gray10"]={26, 26, 26},
["gray100"]={255, 255, 255},
["gray11"]={28, 28, 28},
["gray12"]={31, 31, 31},
["gray13"]={33, 33, 33},
["gray14"]={36, 36, 36},
["gray15"]={38, 38, 38},
["gray16"]={41, 41, 41},
["gray17"]={43, 43, 43},
["gray18"]={46, 46, 46},
["gray19"]={48, 48, 48},
["gray2"]={5, 5, 5},
["gray20"]={51, 51, 51},
["gray21"]={54, 54, 54},
["gray22"]={56, 56, 56},
["gray23"]={59, 59, 59},
["gray24"]={61, 61, 61},
["gray25"]={64, 64, 64},
["gray26"]={66, 66, 66},
["gray27"]={69, 69, 69},
["gray28"]={71, 71, 71},
["gray29"]={74, 74, 74},
["gray3"]={8, 8, 8},
["gray30"]={77, 77, 77},
["gray31"]={79, 79, 79},
["gray32"]={82, 82, 82},
["gray33"]={84, 84, 84},
["gray34"]={87, 87, 87},
["gray35"]={89, 89, 89},
["gray36"]={92, 92, 92},
["gray37"]={94, 94, 94},
["gray38"]={97, 97, 97},
["gray39"]={99, 99, 99},
["gray4"]={10, 10, 10},
["gray40"]={102, 102, 102},
["gray41"]={105, 105, 105},
["gray42"]={107, 107, 107},
["gray43"]={110, 110, 110},
["gray44"]={112, 112, 112},
["gray45"]={115, 115, 115},
["gray46"]={117, 117, 117},
["gray47"]={120, 120, 120},
["gray48"]={122, 122, 122},
["gray49"]={125, 125, 125},
["gray5"]={13, 13, 13},
["gray50"]={127, 127, 127},
["gray51"]={130, 130, 130},
["gray52"]={133, 133, 133},
["gray53"]={135, 135, 135},
["gray54"]={138, 138, 138},
["gray55"]={140, 140, 140},
["gray56"]={143, 143, 143},
["gray57"]={145, 145, 145},
["gray58"]={148, 148, 148},
["gray59"]={150, 150, 150},
["gray6"]={15, 15, 15},
["gray60"]={153, 153, 153},
["gray61"]={156, 156, 156},
["gray62"]={158, 158, 158},
["gray63"]={161, 161, 161},
["gray64"]={163, 163, 163},
["gray65"]={166, 166, 166},
["gray66"]={168, 168, 168},
["gray67"]={171, 171, 171},
["gray68"]={173, 173, 173},
["gray69"]={176, 176, 176},
["gray7"]={18, 18, 18},
["gray70"]={179, 179, 179},
["gray71"]={181, 181, 181},
["gray72"]={184, 184, 184},
["gray73"]={186, 186, 186},
["gray74"]={189, 189, 189},
["gray75"]={191, 191, 191},
["gray76"]={194, 194, 194},
["gray77"]={196, 196, 196},
["gray78"]={199, 199, 199},
["gray79"]={201, 201, 201},
["gray8"]={20, 20, 20},
["gray80"]={204, 204, 204},
["gray81"]={207, 207, 207},
["gray82"]={209, 209, 209},
["gray83"]={212, 212, 212},
["gray84"]={214, 214, 214},
["gray85"]={217, 217, 217},
["gray86"]={219, 219, 219},
["gray87"]={222, 222, 222},
["gray88"]={224, 224, 224},
["gray89"]={227, 227, 227},
["gray9"]={23, 23, 23},
["gray90"]={229, 229, 229},
["gray91"]={232, 232, 232},
["gray92"]={235, 235, 235},
["gray93"]={237, 237, 237},
["gray94"]={240, 240, 240},
["gray95"]={242, 242, 242},
["gray96"]={245, 245, 245},
["gray97"]={247, 247, 247},
["gray98"]={250, 250, 250},
["gray99"]={252, 252, 252},
["green"]={0, 255, 0},
["green yellow"]={173, 255, 47},
["green1"]={0, 255, 0},
["green2"]={0, 238, 0},
["green3"]={0, 205, 0},
["green4"]={0, 139, 0},
["GreenYellow"]={173, 255, 47},
["grey"]={190, 190, 190},
["grey0"]={0, 0, 0},
["grey1"]={3, 3, 3},
["grey10"]={26, 26, 26},
["grey100"]={255, 255, 255},
["grey11"]={28, 28, 28},
["grey12"]={31, 31, 31},
["grey13"]={33, 33, 33},
["grey14"]={36, 36, 36},
["grey15"]={38, 38, 38},
["grey16"]={41, 41, 41},
["grey17"]={43, 43, 43},
["grey18"]={46, 46, 46},
["grey19"]={48, 48, 48},
["grey2"]={5, 5, 5},
["grey20"]={51, 51, 51},
["grey21"]={54, 54, 54},
["grey22"]={56, 56, 56},
["grey23"]={59, 59, 59},
["grey24"]={61, 61, 61},
["grey25"]={64, 64, 64},
["grey26"]={66, 66, 66},
["grey27"]={69, 69, 69},
["grey28"]={71, 71, 71},
["grey29"]={74, 74, 74},
["grey3"]={8, 8, 8},
["grey30"]={77, 77, 77},
["grey31"]={79, 79, 79},
["grey32"]={82, 82, 82},
["grey33"]={84, 84, 84},
["grey34"]={87, 87, 87},
["grey35"]={89, 89, 89},
["grey36"]={92, 92, 92},
["grey37"]={94, 94, 94},
["grey38"]={97, 97, 97},
["grey39"]={99, 99, 99},
["grey4"]={10, 10, 10},
["grey40"]={102, 102, 102},
["grey41"]={105, 105, 105},
["grey42"]={107, 107, 107},
["grey43"]={110, 110, 110},
["grey44"]={112, 112, 112},
["grey45"]={115, 115, 115},
["grey46"]={117, 117, 117},
["grey47"]={120, 120, 120},
["grey48"]={122, 122, 122},
["grey49"]={125, 125, 125},
["grey5"]={13, 13, 13},
["grey50"]={127, 127, 127},
["grey51"]={130, 130, 130},
["grey52"]={133, 133, 133},
["grey53"]={135, 135, 135},
["grey54"]={138, 138, 138},
["grey55"]={140, 140, 140},
["grey56"]={143, 143, 143},
["grey57"]={145, 145, 145},
["grey58"]={148, 148, 148},
["grey59"]={150, 150, 150},
["grey6"]={15, 15, 15},
["grey60"]={153, 153, 153},
["grey61"]={156, 156, 156},
["grey62"]={158, 158, 158},
["grey63"]={161, 161, 161},
["grey64"]={163, 163, 163},
["grey65"]={166, 166, 166},
["grey66"]={168, 168, 168},
["grey67"]={171, 171, 171},
["grey68"]={173, 173, 173},
["grey69"]={176, 176, 176},
["grey7"]={18, 18, 18},
["grey70"]={179, 179, 179},
["grey71"]={181, 181, 181},
["grey72"]={184, 184, 184},
["grey73"]={186, 186, 186},
["grey74"]={189, 189, 189},
["grey75"]={191, 191, 191},
["grey76"]={194, 194, 194},
["grey77"]={196, 196, 196},
["grey78"]={199, 199, 199},
["grey79"]={201, 201, 201},
["grey8"]={20, 20, 20},
["grey80"]={204, 204, 204},
["grey81"]={207, 207, 207},
["grey82"]={209, 209, 209},
["grey83"]={212, 212, 212},
["grey84"]={214, 214, 214},
["grey85"]={217, 217, 217},
["grey86"]={219, 219, 219},
["grey87"]={222, 222, 222},
["grey88"]={224, 224, 224},
["grey89"]={227, 227, 227},
["grey9"]={23, 23, 23},
["grey90"]={229, 229, 229},
["grey91"]={232, 232, 232},
["grey92"]={235, 235, 235},
["grey93"]={237, 237, 237},
["grey94"]={240, 240, 240},
["grey95"]={242, 242, 242},
["grey96"]={245, 245, 245},
["grey97"]={247, 247, 247},
["grey98"]={250, 250, 250},
["grey99"]={252, 252, 252},
["honeydew"]={240, 255, 240},
["honeydew1"]={240, 255, 240},
["honeydew2"]={224, 238, 224},
["honeydew3"]={193, 205, 193},
["honeydew4"]={131, 139, 131},
["hot pink"]={255, 105, 180},
["HotPink"]={255, 105, 180},
["HotPink1"]={255, 110, 180},
["HotPink2"]={238, 106, 167},
["HotPink3"]={205, 96, 144},
["HotPink4"]={139, 58, 98},
["indian red"]={205, 92, 92},
["IndianRed"]={205, 92, 92},
["IndianRed1"]={255, 106, 106},
["IndianRed2"]={238, 99, 99},
["IndianRed3"]={205, 85, 85},
["IndianRed4"]={139, 58, 58},
["ivory"]={255, 255, 240},
["ivory1"]={255, 255, 240},
["ivory2"]={238, 238, 224},
["ivory3"]={205, 205, 193},
["ivory4"]={139, 139, 131},
["khaki"]={240, 230, 140},
["khaki1"]={255, 246, 143},
["khaki2"]={238, 230, 133},
["khaki3"]={205, 198, 115},
["khaki4"]={139, 134, 78},
["lavender"]={230, 230, 250},
["lavender blush"]={255, 240, 245},
["LavenderBlush"]={255, 240, 245},
["LavenderBlush1"]={255, 240, 245},
["LavenderBlush2"]={238, 224, 229},
["LavenderBlush3"]={205, 193, 197},
["LavenderBlush4"]={139, 131, 134},
["lawn green"]={124, 252, 0},
["LawnGreen"]={124, 252, 0},
["lemon chiffon"]={255, 250, 205},
["LemonChiffon"]={255, 250, 205},
["LemonChiffon1"]={255, 250, 205},
["LemonChiffon2"]={238, 233, 191},
["LemonChiffon3"]={205, 201, 165},
["LemonChiffon4"]={139, 137, 112},
["light blue"]={173, 216, 230},
["light coral"]={240, 128, 128},
["light cyan"]={224, 255, 255},
["light goldenrod"]={238, 221, 130},
["light goldenrod yellow"]={250, 250, 210},
["light gray"]={211, 211, 211},
["light grey"]={211, 211, 211},
["light pink"]={255, 182, 193},
["light salmon"]={255, 160, 122},
["light sea green"]={32, 178, 170},
["light sky blue"]={135, 206, 250},
["light slate blue"]={132, 112, 255},
["light slate gray"]={119, 136, 153},
["light slate grey"]={119, 136, 153},
["light steel blue"]={176, 196, 222},
["light yellow"]={255, 255, 224},
["LightBlue"]={173, 216, 230},
["LightBlue1"]={191, 239, 255},
["LightBlue2"]={178, 223, 238},
["LightBlue3"]={154, 192, 205},
["LightBlue4"]={104, 131, 139},
["LightCoral"]={240, 128, 128},
["LightCyan"]={224, 255, 255},
["LightCyan1"]={224, 255, 255},
["LightCyan2"]={209, 238, 238},
["LightCyan3"]={180, 205, 205},
["LightCyan4"]={122, 139, 139},
["LightGoldenrod"]={238, 221, 130},
["LightGoldenrod1"]={255, 236, 139},
["LightGoldenrod2"]={238, 220, 130},
["LightGoldenrod3"]={205, 190, 112},
["LightGoldenrod4"]={139, 129, 76},
["LightGoldenrodYellow"]={250, 250, 210},
["LightGray"]={211, 211, 211},
["LightGrey"]={211, 211, 211},
["LightPink"]={255, 182, 193},
["LightPink1"]={255, 174, 185},
["LightPink2"]={238, 162, 173},
["LightPink3"]={205, 140, 149},
["LightPink4"]={139, 95, 101},
["LightSalmon"]={255, 160, 122},
["LightSalmon1"]={255, 160, 122},
["LightSalmon2"]={238, 149, 114},
["LightSalmon3"]={205, 129, 98},
["LightSalmon4"]={139, 87, 66},
["LightSeaGreen"]={32, 178, 170},
["LightSkyBlue"]={135, 206, 250},
["LightSkyBlue1"]={176, 226, 255},
["LightSkyBlue2"]={164, 211, 238},
["LightSkyBlue3"]={141, 182, 205},
["LightSkyBlue4"]={96, 123, 139},
["LightSlateBlue"]={132, 112, 255},
["LightSlateGray"]={119, 136, 153},
["LightSlateGrey"]={119, 136, 153},
["LightSteelBlue"]={176, 196, 222},
["LightSteelBlue1"]={202, 225, 255},
["LightSteelBlue2"]={188, 210, 238},
["LightSteelBlue3"]={162, 181, 205},
["LightSteelBlue4"]={110, 123, 139},
["LightYellow"]={255, 255, 224},
["LightYellow1"]={255, 255, 224},
["LightYellow2"]={238, 238, 209},
["LightYellow3"]={205, 205, 180},
["LightYellow4"]={139, 139, 122},
["lime green"]={50, 205, 50},
["LimeGreen"]={50, 205, 50},
["linen"]={250, 240, 230},
["magenta"]={255, 0, 255},
["magenta1"]={255, 0, 255},
["magenta2"]={238, 0, 238},
["magenta3"]={205, 0, 205},
["magenta4"]={139, 0, 139},
["maroon"]={176, 48, 96},
["maroon1"]={255, 52, 179},
["maroon2"]={238, 48, 167},
["maroon3"]={205, 41, 144},
["maroon4"]={139, 28, 98},
["medium aquamarine"]={102, 205, 170},
["medium blue"]={0, 0, 205},
["medium orchid"]={186, 85, 211},
["medium purple"]={147, 112, 219},
["medium sea green"]={60, 179, 113},
["medium slate blue"]={123, 104, 238},
["medium spring green"]={0, 250, 154},
["medium turquoise"]={72, 209, 204},
["medium violet red"]={199, 21, 133},
["MediumAquamarine"]={102, 205, 170},
["MediumBlue"]={0, 0, 205},
["MediumOrchid"]={186, 85, 211},
["MediumOrchid1"]={224, 102, 255},
["MediumOrchid2"]={209, 95, 238},
["MediumOrchid3"]={180, 82, 205},
["MediumOrchid4"]={122, 55, 139},
["MediumPurple"]={147, 112, 219},
["MediumPurple1"]={171, 130, 255},
["MediumPurple2"]={159, 121, 238},
["MediumPurple3"]={137, 104, 205},
["MediumPurple4"]={93, 71, 139},
["MediumSeaGreen"]={60, 179, 113},
["MediumSlateBlue"]={123, 104, 238},
["MediumSpringGreen"]={0, 250, 154},
["MediumTurquoise"]={72, 209, 204},
["MediumVioletRed"]={199, 21, 133},
["midnight blue"]={25, 25, 112},
["MidnightBlue"]={25, 25, 112},
["mint cream"]={245, 255, 250},
["MintCream"]={245, 255, 250},
["misty rose"]={255, 228, 225},
["MistyRose"]={255, 228, 225},
["MistyRose1"]={255, 228, 225},
["MistyRose2"]={238, 213, 210},
["MistyRose3"]={205, 183, 181},
["MistyRose4"]={139, 125, 123},
["moccasin"]={255, 228, 181},
["navajo white"]={255, 222, 173},
["NavajoWhite"]={255, 222, 173},
["NavajoWhite1"]={255, 222, 173},
["NavajoWhite2"]={238, 207, 161},
["NavajoWhite3"]={205, 179, 139},
["NavajoWhite4"]={139, 121, 94},
["navy"]={0, 0, 128},
["navy blue"]={0, 0, 128},
["NavyBlue"]={0, 0, 128},
["old lace"]={253, 245, 230},
["OldLace"]={253, 245, 230},
["olive drab"]={107, 142, 35},
["OliveDrab"]={107, 142, 35},
["OliveDrab1"]={192, 255, 62},
["OliveDrab2"]={179, 238, 58},
["OliveDrab3"]={154, 205, 50},
["OliveDrab4"]={105, 139, 34},
["orange"]={255, 165, 0},
["orange red"]={255, 69, 0},
["orange1"]={255, 165, 0},
["orange2"]={238, 154, 0},
["orange3"]={205, 133, 0},
["orange4"]={139, 90, 0},
["OrangeRed"]={255, 69, 0},
["OrangeRed1"]={255, 69, 0},
["OrangeRed2"]={238, 64, 0},
["OrangeRed3"]={205, 55, 0},
["OrangeRed4"]={139, 37, 0},
["orchid"]={218, 112, 214},
["orchid1"]={255, 131, 250},
["orchid2"]={238, 122, 233},
["orchid3"]={205, 105, 201},
["orchid4"]={139, 71, 137},
["pale goldenrod"]={238, 232, 170},
["pale green"]={152, 251, 152},
["pale turquoise"]={175, 238, 238},
["pale violet red"]={219, 112, 147},
["PaleGoldenrod"]={238, 232, 170},
["PaleGreen"]={152, 251, 152},
["PaleGreen1"]={154, 255, 154},
["PaleGreen2"]={144, 238, 144},
["PaleGreen3"]={124, 205, 124},
["PaleGreen4"]={84, 139, 84},
["PaleTurquoise"]={175, 238, 238},
["PaleTurquoise1"]={187, 255, 255},
["PaleTurquoise2"]={174, 238, 238},
["PaleTurquoise3"]={150, 205, 205},
["PaleTurquoise4"]={102, 139, 139},
["PaleVioletRed"]={219, 112, 147},
["PaleVioletRed1"]={255, 130, 171},
["PaleVioletRed2"]={238, 121, 159},
["PaleVioletRed3"]={205, 104, 137},
["PaleVioletRed4"]={139, 71, 93},
["papaya whip"]={255, 239, 213},
["PapayaWhip"]={255, 239, 213},
["peach puff"]={255, 218, 185},
["PeachPuff"]={255, 218, 185},
["PeachPuff1"]={255, 218, 185},
["PeachPuff2"]={238, 203, 173},
["PeachPuff3"]={205, 175, 149},
["PeachPuff4"]={139, 119, 101},
["peru"]={205, 133, 63},
["pink"]={255, 192, 203},
["pink1"]={255, 181, 197},
["pink2"]={238, 169, 184},
["pink3"]={205, 145, 158},
["pink4"]={139, 99, 108},
["plum"]={221, 160, 221},
["plum1"]={255, 187, 255},
["plum2"]={238, 174, 238},
["plum3"]={205, 150, 205},
["plum4"]={139, 102, 139},
["powder blue"]={176, 224, 230},
["PowderBlue"]={176, 224, 230},
["purple"]={160, 32, 240},
["purple1"]={155, 48, 255},
["purple2"]={145, 44, 238},
["purple3"]={125, 38, 205},
["purple4"]={85, 26, 139},
["red"]={255, 0, 0},
["red1"]={255, 0, 0},
["red2"]={238, 0, 0},
["red3"]={205, 0, 0},
["red4"]={139, 0, 0},
["rosy brown"]={188, 143, 143},
["RosyBrown"]={188, 143, 143},
["RosyBrown1"]={255, 193, 193},
["RosyBrown2"]={238, 180, 180},
["RosyBrown3"]={205, 155, 155},
["RosyBrown4"]={139, 105, 105},
["royal blue"]={65, 105, 225},
["RoyalBlue"]={65, 105, 225},
["RoyalBlue1"]={72, 118, 255},
["RoyalBlue2"]={67, 110, 238},
["RoyalBlue3"]={58, 95, 205},
["RoyalBlue4"]={39, 64, 139},
["saddle brown"]={139, 69, 19},
["SaddleBrown"]={139, 69, 19},
["salmon"]={250, 128, 114},
["salmon1"]={255, 140, 105},
["salmon2"]={238, 130, 98},
["salmon3"]={205, 112, 84},
["salmon4"]={139, 76, 57},
["sandy brown"]={244, 164, 96},
["SandyBrown"]={244, 164, 96},
["sea green"]={46, 139, 87},
["SeaGreen"]={46, 139, 87},
["SeaGreen1"]={84, 255, 159},
["SeaGreen2"]={78, 238, 148},
["SeaGreen3"]={67, 205, 128},
["SeaGreen4"]={46, 139, 87},
["seashell"]={255, 245, 238},
["seashell1"]={255, 245, 238},
["seashell2"]={238, 229, 222},
["seashell3"]={205, 197, 191},
["seashell4"]={139, 134, 130},
["sienna"]={160, 82, 45},
["sienna1"]={255, 130, 71},
["sienna2"]={238, 121, 66},
["sienna3"]={205, 104, 57},
["sienna4"]={139, 71, 38},
["sky blue"]={135, 206, 235},
["SkyBlue"]={135, 206, 235},
["SkyBlue1"]={135, 206, 255},
["SkyBlue2"]={126, 192, 238},
["SkyBlue3"]={108, 166, 205},
["SkyBlue4"]={74, 112, 139},
["slate blue"]={106, 90, 205},
["slate gray"]={112, 128, 144},
["slate grey"]={112, 128, 144},
["SlateBlue"]={106, 90, 205},
["SlateBlue1"]={131, 111, 255},
["SlateBlue2"]={122, 103, 238},
["SlateBlue3"]={105, 89, 205},
["SlateBlue4"]={71, 60, 139},
["SlateGray"]={112, 128, 144},
["SlateGray1"]={198, 226, 255},
["SlateGray2"]={185, 211, 238},
["SlateGray3"]={159, 182, 205},
["SlateGray4"]={108, 123, 139},
["SlateGrey"]={112, 128, 144},
["snow"]={255, 250, 250},
["snow1"]={255, 250, 250},
["snow2"]={238, 233, 233},
["snow3"]={205, 201, 201},
["snow4"]={139, 137, 137},
["spring green"]={0, 255, 127},
["SpringGreen"]={0, 255, 127},
["SpringGreen1"]={0, 255, 127},
["SpringGreen2"]={0, 238, 118},
["SpringGreen3"]={0, 205, 102},
["SpringGreen4"]={0, 139, 69},
["steel blue"]={70, 130, 180},
["SteelBlue"]={70, 130, 180},
["SteelBlue1"]={99, 184, 255},
["SteelBlue2"]={92, 172, 238},
["SteelBlue3"]={79, 148, 205},
["SteelBlue4"]={54, 100, 139},
["tan"]={210, 180, 140},
["tan1"]={255, 165, 79},
["tan2"]={238, 154, 73},
["tan3"]={205, 133, 63},
["tan4"]={139, 90, 43},
["thistle"]={216, 191, 216},
["thistle1"]={255, 225, 255},
["thistle2"]={238, 210, 238},
["thistle3"]={205, 181, 205},
["thistle4"]={139, 123, 139},
["tomato"]={255, 99, 71},
["tomato1"]={255, 99, 71},
["tomato2"]={238, 92, 66},
["tomato3"]={205, 79, 57},
["tomato4"]={139, 54, 38},
["turquoise"]={64, 224, 208},
["turquoise1"]={0, 245, 255},
["turquoise2"]={0, 229, 238},
["turquoise3"]={0, 197, 205},
["turquoise4"]={0, 134, 139},
["violet"]={238, 130, 238},
["violet red"]={208, 32, 144},
["VioletRed"]={208, 32, 144},
["VioletRed1"]={255, 62, 150},
["VioletRed2"]={238, 58, 140},
["VioletRed3"]={205, 50, 120},
["VioletRed4"]={139, 34, 82},
["wheat"]={245, 222, 179},
["wheat1"]={255, 231, 186},
["wheat2"]={238, 216, 174},
["wheat3"]={205, 186, 150},
["wheat4"]={139, 126, 102},
["white"]={255, 255, 255},
["white smoke"]={245, 245, 245},
["WhiteSmoke"]={245, 245, 245},
["yellow"]={255, 255, 0},
["yellow green"]={154, 205, 50},
["yellow1"]={255, 255, 0},
["yellow2"]={238, 238, 0},
["yellow3"]={205, 205, 0},
["yellow4"]={139, 139, 0},
["YellowGreen"]={154, 205, 50}
}

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>Circle</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>Circle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; drawable circle</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self, x, y, r, s, color)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw(style)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw the circle<br></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>Drawable</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>Drawable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; base class for all drawable stuff</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self, x, y, color)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wrapX(min, max)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;can be called via wrapX(max) or wrapX(min,max)<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wrapY(min, max)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;can be called via wrapY(max) or wrapY(min,max)<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wrap(str, min, max)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal wrapper<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set(str, val)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;supercollider style 'set'<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw()</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;not yet implemented<br></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>Line</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>Line&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; draw a line</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self, x, y, tx, ty)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>Object</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>Object&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; base class</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>SCObject</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>SCObject&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bass class for supercollider communication</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i></BODY></HTML>

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>SCSynth</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>SCSynth&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; supercollider synthesizer class</h3><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(self, nodename, freq)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> Constructor</i><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set(control, val)</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set a control, TODO: variable lenght of argument-pairs<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.time(),</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bundle",<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;play()</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sends an OSC message to the supercollider to start the synth<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.time(),</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bundle",<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free()</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frees the node on the supercollider server<br><h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.time()+0.8,</h4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bundle",<br></BODY></HTML>

View File

@ -0,0 +1,70 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="1038.35">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1"><b>Guidelines for new live_libs classes</b></p>
<p class="p2"><br></p>
<p class="p3"><b>1. Howto write a new class</b></p>
<p class="p2"><br></p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span>&lt;class name&gt; =<span class="Apple-converted-space">  </span>Class(&lt;constructor&gt;)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>creates a class with function in constructor</p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-tab-span"> </span>&lt;class name&gt;:inherit(&lt;other class name&gt;)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>if you want to inherit from any class.Everything should inherit directly or indirectly from object, because here the instance is added to the _internal_object_table</p>
<p class="p2"><br></p>
<p class="p3">If you want to call the constructor of the superclass write the following in the constructor of the current class:</p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span>&lt;super class name&gt;.&lt;construct&gt;(self, &lt;arguments&gt;)</p>
<p class="p2"><br></p>
<p class="p3">More on Classes and HUMP: http://vrld.github.com/hump/</p>
<p class="p2"><br></p>
<p class="p3"><b>2. Commenting</b></p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span>In order to work the comment parser needs the following comment 'marks':</p>
<p class="p2"><br></p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-tab-span"> </span>-- @ &lt;class name&gt;:&lt;short description&gt;</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>This marks a new class. The following line should be the class definition</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Note: only one line comments are working</p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-tab-span"> </span>-- # &lt;description&gt;</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>This marks a new method.</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Note: the limitations of class comments apply</p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-tab-span"> </span>any '--' without marks will not be included in the helpfile</p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span><b>Example</b>:</p>
<p class="p3"><i><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>-- @Drawable: base class for all drawable stuff</i></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Drawable = Class(function(self, x, y, color)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>self.color = color or hlpr.color("white",255)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>-- call constructor of Object class</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Object.construct(self)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>self.position = Vector(x or 0,y or 0)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>end)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>Drawable:inherit(Object)</p>
<p class="p2"><br></p>
<p class="p3"><i><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>-- #can be called via wrapX(max) or wrapX(min,max)</i></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>function Drawable:wrapX(min, max)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>if min and max then</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>self:wrap("x", min, max)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>elseif min and not max then<span class="Apple-converted-space"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>self:wrap("x", 0, min)</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>end</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>end</p>
<p class="p2"><br></p>
<p class="p2"><br></p>
</body>
</html>

View File

@ -0,0 +1,51 @@
Guidelines for new live_libs classes
1. Howto write a new class
<class name> = Class(<constructor>)
creates a class with function in constructor
<class name>:inherit(<other class name>)
if you want to inherit from any class. Everything should inherit directly or indirectly from object, because here the instance is added to the _internal_object_table
If you want to call the constructor of the superclass write the following in the constructor of the current class:
<super class name>.<construct>(self, <arguments>)
More on Classes and HUMP: http://vrld.github.com/hump/
2. Commenting
In order to work the comment parser needs the following comment 'marks':
-- @ <class name>:<short description>
This marks a new class.
Note: only oneliners are working
-- # <description>
This marks a new method.
Note: limitation of class comments apply
any '--' without marks will not be included in the helpfile
Example:
-- @Drawable: base class for all drawable stuff
Drawable = Class(function(self, x, y, color)
self.color = color or hlpr.color("white",255)
-- call constructor of Object class
Object.construct(self)
self.position = Vector(x or 0,y or 0)
end)
Drawable:inherit(Object)
-- #can be called via wrapX(max) or wrapX(min,max)
function Drawable:wrapX(min, max)
if min and max then
self:wrap("x", min, max)
elseif min and not max then
self:wrap("x", 0, min)
end
end

View File

@ -0,0 +1 @@
<HTML><HEAD><TITLE>live_libs_doc</TITLE><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style></HEAD><BODY><h3>live_libs documentation</h3><a href="guidelines.html">Guidelines for new classes and commenting</a><h4>Classes:</h4><a href="classes/Object.html">Object</a> <br><a href="classes/SCObject.html">SCObject</a> <br><a href="classes/SCSynth.html">SCSynth</a> <br><a href="classes/Drawable.html">Drawable</a> <br><a href="classes/Circle.html">Circle</a> <br><a href="classes/Line.html">Line</a> <br></BODY></HTML>

View File

@ -0,0 +1,109 @@
-- parse the classes to readable html
module(..., package.seeall)
filename = "LICK/lib/object.lua"
help_filename = "LICK/lib/docs/"
-- some styles
local style = "<style type=\"text/css\">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}span.s1 {font: 18.0px Helvetica}span.s2 {color: #0026b4}span.Apple-tab-span {white-space:pre}</style>"
local header1 = "<HTML><HEAD><TITLE>"
local header2 = "</TITLE>"..style.."</HEAD><BODY>"
local footer = "</BODY></HTML>"
local _newclasstitle = "<h3>"
local newclasstitle_ = "</h3>"
local tab = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
-- generates the html file
function generate()
class_file = love.filesystem.newFile( filename )
class_file:open('r')
local output = ""
output = header1.."test"..header2
local found_methods = 0
local found_classes = 0
local classes = {}
for line in class_file:lines() do
local b,e = string.find(line,"@")
local b1,e1 = string.find(line,"Class")
if b and e then
if found_classes > 0 then
output = output..footer
writeClassFile(name, output)
local output = ""
end
dp,ep = string.find(line, ":")
name = line:sub(e+1, dp-1 or 0)
print(name)
table.insert(classes,name)
output = header1..name..header2
output = output .._newclasstitle .. name..tab..tab..line:sub(dp+1) ..newclasstitle_
found_methods = 0
found_classes = found_classes + 1
elseif b1 and e1 and not string.find(line,"require") then
output = output .."<h4>"..tab..line:sub(e1+2).."</h4>"..tab..tab.."<i> Constructor</i>"
end
local b,e = string.find(line,"#")
if method then
local dp,ep = string.find(line, ":")
ep = ep or 1
if found == 0 then
output = output .."<h3>Methods</h3>"
found_methods = found_methods + 1
end
output = output.."<h4>".. tab ..line:sub(ep+1).."</h4>"..tab..tab..method
method = nil
end
if b and e then
method = line:sub(e+1).."<br>"
--output = output..line:sub(e+1).."<br>"
end
end
output = output..footer
writeClassFile(name, output)
-- generate index.html
index = header1.."live_libs_doc"..header2
index = index.."<h3>live_libs documentation</h3>"
index = index .. "<a href=\"guidelines.html\">Guidelines for new classes and commenting</a>"
index = index.. "<h4>Classes:</h4>"
for i,v in ipairs(classes) do
index = index.."<a href=\"classes/"..v..".html".."\">"..v.."</a> <br>"
end
index = index..footer
writeFile("index", index)
end
function writeClassFile(name, output)
dir = love.filesystem.getWorkingDirectory( )
--print("touch "..dir.."/"..help_filename)
local path = dir.."/live_testproject/"..help_filename.."classes/"..name..".html"
os.execute("touch "..path)
local helpfile = io.open(path, "w" )
helpfile:write(output)
helpfile:close()
end
function writeFile(name, output)
dir = love.filesystem.getWorkingDirectory( )
--print("touch "..dir.."/"..help_filename)
local path = dir.."/live_testproject/"..help_filename..name..".html"
os.execute("touch "..path)
local helpfile = io.open(path, "w" )
helpfile:write(output)
helpfile:close()
end

View File

@ -0,0 +1,281 @@
-- hlpr libary: it's not about nice coding, ist about fast and easy coding
-- by Rukano and Headchant, 2011
pi = math.pi
setColor = love.graphics.setColor
rectangle = love.graphics.rectangle
getWidth = love.graphics.getWidth
getHeight = love.graphics.getHeight
push = love.graphics.push
pop = love.graphics.pop
translate = love.graphics.translate
rotate = love.graphics.rotate
scale = love.graphics.scale
circle = love.graphics.circle
sin = math.sin
deg = math.deg
rad = math.rad
require "LICK/lib/color"
module(...,package.seeall)
function color(r, g,b,a)
local color={}
local alpha=a or 255
local name=r or "azure"
if type(r) == "string" then
alpha = g or alpha
color = x11_color_table[name]
else
color[1]=r
color[2]=g
color[3]=b
end
color[4]=alpha
return color
end
-- clip withing range (by redlock)
function clip(n,min,max)
return math.min(math.max(n, min or -math.huge), max or math.huge)
end
-- wrap within range, updated version
function wrap(n, min, max)
local min = min or 0
return ((n - min) % ((max or 0) - min)) + min
end
-- setColor white
function white()
love.graphics.setColor(255,255,255,255)
end
-- setColor black
function black()
love.graphics.setColor(0,0,0,255)
end
-- shorter setColor white
function w()
white()
end
-- shorter setColor black
function b()
black()
end
-- fill the screen with translucent black
function clear(alpha)
love.graphics.setColor(0,0,0,alpha)
love.graphics.rectangle("fill", 0,0,800,600)
end
-- shorter clear
function cls(alpha)
clear(alpha)
end
-- one time clear
function cls_once()
love.graphics.setColor(0,0,0,255)
love.graphics.rectangle("fill", 0,0,800,600)
end
-- returns random values from -1 to 1, g sets the equidistance
function norm_random()
return 2 * math.random() - 1
end
-- shorte norm_random
function n_rnd()
return norm_random()
end
-- drunk, brownnoise/drunk walk: x = x +/- random(width)
function drunk(x, width, g)
x = x or 0
width = width or 1
g = g or 100
return (x + width*norm_random())
end
-- drnk, shorter version of drunk, start is only used the first time
-- this makes some sense whatsoever...
function drnk(width)
local last = 0
return function()
last = last + width * norm_random()
return last
end
end
-- scaling functions:
function linlin(n,inMin,inMax,outMin,outMax,clip)
-- ported and adapted from:
-- SuperCollider SimpleNumber:linlin
local n=n or 0 -- to avoid giving back nil
local clip=clip or "minmax" -- default:clip minmax
if (inMin == nil) or (inMax == nil) or (outMin == nil) or (outMax == nil) then
-- just in case you forgot the parameters...
return n
end
if clip == "minmax" then
if n <= inMin then
return minoutMin
elseif n >= inMax then
return outMax
end
elseif clip == "min" then
if n <= inMin then
return outMin
end
elseif clip == "max" then
if n >= inMax then
return outMax
end
end
-- here is the magic!
n = (((n-inMin)/(inMax-inMin)) * (outMax-outMin)) + outMin
return n
end
function linexp(n,inMin,inMax,outMin,outMax,clip)
-- ported and adapted from:
-- SuperCollider SimpleNumber:linexp
local n=n or 0.00001 -- to avoid giving back nil
local clip=clip or "minmax" -- default:clip minmax
if (inMin == nil) or (inMax == nil) or (outMin == nil) or (outMax == nil) then
-- just in case...
return n
end
if clip == "minmax" then
if n <= inMin then
return outMin
elseif n >= inMax then
return outMax
end
elseif clip == "min" then
if n <= inMin then
return outMin
end
elseif clip == "max" then
if n >= inMax then
return outMax
end
end
-- here is the magic!
n = math.pow(outMax/outMin, (n-inMin)/(inMax-inMin)) * outMin
return n
end
function explin(n,inMin,inMax,outMin,outMax,clip)
-- ported and adapted from:
-- SuperCollider SimpleNumber:explin
local n=n or 0.00001 -- to avoid giving back nil
local clip=clip or "minmax" -- default:clip minmax
if (inMin == nil) or (inMax == nil) or (outMin == nil) or (outMax == nil) then
-- just in case...
return n
end
if clip == "minmax" then
if n <= inMin then
return outMin
elseif n >= inMax then
return outMax
end
elseif clip == "min" then
if n <= inMin then
return outMin
end
elseif clip == "max" then
if n >= inMax then
return outMax
end
end
-- here is the magic!
n = (((math.log(n/inMin)) / (math.log(inMax/inMin))) * (outMax-outMin)) + outMin
return n
end
function expexp(n,inMin,inMax,outMin,outMax,clip)
-- ported and adapted from:
-- SuperCollider SimpleNumber:expexp
local n=n or 0.00001 -- to avoid giving back nil
local clip=clip or "minmax" -- default:clip minmax
if (inMin == nil) or (inMax == nil) or (outMin == nil) or (outMax == nil) then
-- just in case...
return n
end
if clip == "minmax" then
if n <= inMin then
return outMin
elseif n >= inMax then
return outMax
end
elseif clip == "min" then
if n <= inMin then
return outMin
end
elseif clip == "max" then
if n >= inMax then
return outMax
end
end
-- here is the magic!
n = math.pow(outMax/outMin, math.log(n/inMin) / math.log(inMax/inMin)) * outMin
return n
end
-- returns easy sine oscillator
function sin()
local x = 0
return function(dt)
x = x + (dt or 0)
if x > 2 * pi then x = x - 2*pi end
return math.sin(x)
end
end
-- updates all objects in the _object table
function update_objects()
for i,v in ipairs(_internal_object_table) do
v:update(dt)
end
end
-- rotate around center
function rotateCenter(angle)
local angle=angle or 0
local w, h = getWidth(), getHeight()
translate(w/2, h/2)
rotate(angle)
translate(-w/2, -h/2)
end
-- return a random table entry
function choose(table)
return table[math.random(#table)]
end

View File

@ -0,0 +1,48 @@
HUMP - Helper Utilities for Massive Progression
===============================================
__HUMP__ is a small collection of tools for developing games with L&Ouml;VE.
Contents:
------------
* *vector.lua*: powerful vector class (pure lua)
* *class.lua*: "class" system supporting function inheritance (pure lua)
* *camera.lua*: translate-, zoom- and rotatable camera
* *gamestate.lua*: class to handle gamestates
* *ringbuffer.lua*: a circular container
* *sequence.lua*: utility to handle ingame cutscenes and such
Documentation
=============
You can find the documentation here: [http://vrld.github.com/hump/](http://vrld.github.com/hump/ "project page")
License
=======
Yay, *free software*:
> Copyright (c) 2010 Matthias Richter
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> Except as contained in this notice, the name(s) of the above copyright holders
> shall not be used in advertising or otherwise to promote the sale, use or
> other dealings in this Software without prior written authorization.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.

View File

@ -0,0 +1,90 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local setmetatable, require, love = setmetatable, require, love
module(...)
local vector = require(_PACKAGE..'vector')
local camera = {}
camera.__index = camera
function new(pos, zoom, rot)
local pos = pos or vector(love.graphics.getWidth(), love.graphics.getHeight()) / 2
local zoom = zoom or 1
local rot = rot or 0
return setmetatable({pos = pos, zoom = zoom, rot = rot}, camera)
end
function camera:rotate(phi)
self.rot = self.rot + phi
end
function camera:translate(t)
self.pos = self.pos + t
end
camera.move = camera.translate
function camera:predraw()
local center = vector(love.graphics.getWidth(), love.graphics.getHeight()) / (self.zoom * 2)
love.graphics.push()
love.graphics.scale(self.zoom)
love.graphics.translate(center:unpack())
love.graphics.rotate(self.rot)
love.graphics.translate((-self.pos):unpack())
end
function camera:postdraw()
love.graphics.pop()
end
function camera:draw(func)
self:predraw()
func()
self:postdraw()
end
function camera:toCameraCoords(p)
local w,h = love.graphics.getWidth(), love.graphics.getHeight()
local p = (p - self.pos):rotate_inplace(self.rot)
return vector(p.x * self.zoom + w/2, p.y * self.zoom + h/2)
end
function camera:toWorldCoords(p)
local w,h = love.graphics.getWidth(), love.graphics.getHeight()
local p = vector((p.x-w/2) / self.zoom, (p.y-h/2) / self.zoom):rotate_inplace(-self.rot)
return p + self.pos
end
function camera:mousepos()
return self:toWorldCoords(vector(love.mouse.getPosition()))
end
-- camera() as a shortcut to new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

View File

@ -0,0 +1,82 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local setmetatable, getmetatable = setmetatable, getmetatable
local type, assert, pairs = type, assert, pairs
local tostring, string_format = tostring, string.format
module(...)
local function __NULL__() end
function new(constructor)
-- check name and constructor
local name = '<unnamed class>'
if type(constructor) == "table" then
if constructor.name then name = constructor.name end
constructor = constructor[1]
end
assert(not constructor or type(constructor) == "function",
string_format('%s: constructor has to be nil or a function', name))
-- build class
local c = {}
c.__index = c
c.__tostring = function() return string_format("<instance of %s>", name) end
c.construct = constructor or __NULL__
c.Construct = constructor or __NULL__
c.inherit = inherit
c.Inherit = inherit
local meta = {
__call = function(self, ...)
local obj = {}
self.construct(obj, ...)
return setmetatable(obj, self)
end,
__tostring = function() return tostring(name) end
}
return setmetatable(c, meta)
end
function inherit(class, interface, ...)
if not interface then return end
-- __index and construct are not overwritten as for them class[name] is defined
for name, func in pairs(interface) do
if not class[name] and type(func) == "function" then
class[name] = func
end
end
inherit(class, ...)
end
-- class() as shortcut to class.new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

View File

@ -0,0 +1,154 @@
--[[
Copyright (c) 2010-2011 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local error, assert, love = error, assert, love
module(...)
local function __NULL__() end
-- default gamestate produces error on every callback
local function __ERROR__() error("Gamestate not initialized. Use Gamestate.switch()") end
current = {
enter = __ERROR__,
leave = __NULL__,
update = __ERROR__,
draw = __ERROR__,
focus = __ERROR__,
keyreleased = __ERROR__,
keypressed = __ERROR__,
mousepressed = __ERROR__,
mousereleased = __ERROR__,
joystickpressed = __ERROR__,
joystickreleased = __ERROR__,
quit = __ERROR__,
}
function new()
return {
enter = __NULL__,
leave = __NULL__,
update = __NULL__,
draw = __NULL__,
focus = __NULL__,
keyreleased = __NULL__,
keypressed = __NULL__,
mousepressed = __NULL__,
mousereleased = __NULL__,
joystickpressed = __NULL__,
joystickreleased = __NULL__,
quit = __NULL__,
}
end
function switch(to, ...)
assert(to, "Missing argument: Gamestate to switch to")
current:leave()
local pre = current
current = to
return current:enter(pre, ...)
end
local _update
function update(...)
if _update then _update(...) end
return current:update(...)
end
local _draw
function draw(...)
if _draw then _draw(...) end
return current:draw(...)
end
local _focus
function focus(...)
if _focus then _focus(...) end
return current:focus(...)
end
local _keypressed
function keypressed(...)
if _keypressed then _keypressed(...) end
return current:keypressed(...)
end
local _keyreleased
function keyreleased(...)
if _keyreleased then _keyreleased(...) end
return current:keyreleased(...)
end
local _mousepressed
function mousepressed(...)
if _mousereleased then _mousepressed(...) end
return current:mousepressed(...)
end
local _mousereleased
function mousereleased(...)
if _mousereleased then _mousereleased(...) end
return current:mousereleased(...)
end
local _joystickpressed
function joystickpressed(...)
if _joystickpressed then _joystickpressed(...) end
return current:joystickpressed(...)
end
local _joystickreleased
function joystickreleased(...)
if _joystickreleased then _joystickreleased(...) end
return current:joystickreleased(...)
end
local _quit
function quit(...)
if _quit then _quit(...) end
return current:quit(...)
end
function registerEvents()
_update = love.update
love.update = update
_draw = love.draw
love.draw = draw
_focus = love.focus
love.focus = focus
_keypressed = love.keypressed
love.keypressed = keypressed
_keyreleased = love.keyreleased
love.keyreleased = keyreleased
_mousepressed = love.mousepressed
love.mousepressed = mousepressed
_mousereleased = love.mousereleased
love.mousereleased = mousereleased
_joystickpressed = love.joystickpressed
love.joystickpressed = joystickpressed
_joystickreleased = love.joystickreleased
love.joystickreleased = joystickreleased
_quit = love.quit
love.quit = quit
end

View File

@ -0,0 +1,99 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local setmetatable, getmetatable, table = setmetatable, getmetatable, table
module(...)
local ringbuffer = {}
ringbuffer.__index = ringbuffer
function new(...)
local rb = {}
rb.items = {...}
rb.current = 1
return setmetatable(rb, ringbuffer)
end
function ringbuffer:insert(item, ...)
if not item then return end
-- insert rest before self so order is restored, e.g.:
-- {1,<2>,3}:insert(4,5) -> {1,<2>,3}:insert(5) -> {1,<2>,5,3} -> {1,<2>,4,5,3}
self:insert(...)
table.insert(self.items, self.current+1, item)
end
function ringbuffer:append(item, ...)
if not item then return end
self.items[#self.items+1] = item
return self:append(...)
end
function ringbuffer:removeAt(k)
-- wrap position
local pos = (self.current + k) % #self.items
while pos < 1 do pos = pos + #self.items end
-- remove item
local item = table.remove(self.items, pos)
-- possibly adjust current pointer
if pos < self.current then self.current = self.current - 1 end
if self.current > #self.items then self.current = 1 end
-- return item
return item
end
function ringbuffer:remove()
return table.remove(self.items, self.current)
end
function ringbuffer:get()
return self.items[self.current]
end
function ringbuffer:size()
return #self.items
end
function ringbuffer:next()
self.current = (self.current % #self.items) + 1
return self:get()
end
function ringbuffer:prev()
self.current = self.current - 1
if self.current < 1 then
self.current = #self.items
end
return self:get()
end
-- Ringbuffer() as a shortcut to Ringbuffer.new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

View File

@ -0,0 +1,83 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local assert, type = assert, type
local pairs, ipairs = pairs, ipairs
local min = math.min
module(...)
functions = {}
function update(dt)
local to_remove = {}
for func, delay in pairs(functions) do
delay = delay - dt
if delay <= 0 then
to_remove[#to_remove+1] = func
else
functions[func] = delay
end
end
for _,func in ipairs(to_remove) do
functions[func] = nil
func(func)
end
end
function add(delay, func)
assert(type(func) == "function", "second argument needs to be a function")
functions[func] = delay
end
function addPeriodic(delay, func, count)
assert(type(func) == "function", "second argument needs to be a function")
if count then
return add(delay, function(f) func(func) count = count - 1 if count > 0 then add(delay, f) end end)
end
return add(delay, function(f) func(func) add(delay, f) end)
end
function clear()
functions = {}
end
function Interpolator(length, func)
assert(type(func) == "function", "second argument needs to be a function")
local t = 0
return function(dt, ...)
t = t + dt
return t <= length and func((t-dt)/length, ...) or nil
end
end
function Oscillator(length, func)
assert(type(func) == "function", "second argument needs to be a function")
local t = 0
return function(dt, ...)
t = t + dt
while t > length do t = t - length end
return func(t/length, ...)
end
end

View File

@ -0,0 +1,156 @@
--[[
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local setmetatable, getmetatable = setmetatable, getmetatable
local assert, type, tonumber = assert, type, tonumber
local sqrt, cos, sin = math.sqrt, math.cos, math.sin
module(...)
local vector = {}
vector.__index = vector
function new(x,y)
local v = {x = x or 0, y = y or 0}
setmetatable(v, vector)
return v
end
function isvector(v)
return getmetatable(v) == vector
end
function vector:clone()
return new(self.x, self.y)
end
function vector:unpack()
return self.x, self.y
end
function vector:__tostring()
return "("..tonumber(self.x)..","..tonumber(self.y)..")"
end
function vector.__unm(a)
return new(-a.x, -a.y)
end
function vector.__add(a,b)
assert(isvector(a) and isvector(b), "Add: wrong argument types (<vector> expected)")
return new(a.x+b.x, a.y+b.y)
end
function vector.__sub(a,b)
assert(isvector(a) and isvector(b), "Sub: wrong argument types (<vector> expected)")
return new(a.x-b.x, a.y-b.y)
end
function vector.__mul(a,b)
if type(a) == "number" then
return new(a*b.x, a*b.y)
elseif type(b) == "number" then
return new(b*a.x, b*a.y)
else
assert(isvector(a) and isvector(b), "Mul: wrong argument types (<vector> or <number> expected)")
return a.x*b.x + a.y*b.y
end
end
function vector.__div(a,b)
assert(isvector(a) and type(b) == "number", "wrong argument types (expected <vector> / <number>)")
return new(a.x / b, a.y / b)
end
function vector.__eq(a,b)
return a.x == b.x and a.y == b.y
end
function vector.__lt(a,b)
return a.x < b.x or (a.x == b.x and a.y < b.y)
end
function vector.__le(a,b)
return a.x <= b.x and a.y <= b.y
end
function vector.permul(a,b)
assert(isvector(a) and isvector(b), "permul: wrong argument types (<vector> expected)")
return new(a.x*b.x, a.y*b.y)
end
function vector:len2()
return self * self
end
function vector:len()
return sqrt(self*self)
end
function vector.dist(a, b)
assert(isvector(a) and isvector(b), "dist: wrong argument types (<vector> expected)")
return (b-a):len()
end
function vector:normalize_inplace()
local l = self:len()
self.x, self.y = self.x / l, self.y / l
return self
end
function vector:normalized()
return self / self:len()
end
function vector:rotate_inplace(phi)
local c, s = cos(phi), sin(phi)
self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y
return self
end
function vector:rotated(phi)
return self:clone():rotate_inplace(phi)
end
function vector:perpendicular()
return new(-self.y, self.x)
end
function vector:projectOn(v)
assert(isvector(v), "invalid argument: cannot project onto anything other than a new.")
return (self * v) * v / v:len2()
end
function vector:cross(other)
assert(isvector(other), "cross: wrong argument types (<vector> expected)")
return self.x * other.y - self.y * other.x
end
-- vector() as shortcut to vector.new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1,4 @@
-- init live_libs
Vector = require "LICK/lib/hump/vector"
require "LICK/lib/object"
require "LICK/lib/loveosc"

View File

@ -0,0 +1,8 @@
loveOSC is a fork of luaOSC(http://luaforge.net/projects/luaosc/) which implements the Open Sound Control Protocol (http://opensoundcontrol.org/) but substitutes the LPACK dependency with VSTRUCT for greater portability
The testproject sends a OSC message to a server on port 57110, which is Supercolliders OSC port. It also receives OSC messages on port 7771.
Features:
- Client, sending/encoding OSC messages/bundles
- Server, receiving/decoding/handle OSC messages

View File

@ -0,0 +1,340 @@
--[[
-- luaosc Copyright (C) 2009 Jost Tobias Springenberg <k-gee@wrfl.de> --
This file is part of luaosc.
luaosc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
luaosc 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
--]]
-- This is a luaOSC Fork from Jost Tobias Springenberg, additional code and modifications by Tilmann Hars, Headchant.com, Copyright 2010
local socket = require "socket"
local base = _G
local string = require("string")
local vstruct = require "LICK/lib/loveosc/vstruct"
local pack = vstruct.pack
local upack = vstruct.unpack
--------------------------------
-- some constants
--------------------------------
osc.client = {}
osc.client.host = "localhost"
osc.client.port = 57110
osc.client.timeout = 0
PROTOCOL = "OSC/1.0"
ADJUSTMENT_FACTOR = 2208988800
IMMEDIATE = string.rep('0', 31) .. '1'
function osc.client:send( data )
local ip, port = assert(socket.dns.toip(osc.client.host)), osc.client.port
-- create a new UDP object
local udp = assert(socket.udp())
udp:settimeout(0)
--print(encode(data))
assert(udp:sendto(encode(data), ip, port), "could not send data")
--assert(udp:sendto(data, ip, port), "could not send data")
-- retrieve the answer and print results, warning: crashes love
--print(udp:receive() or "")
end
--------------------------------
-- interface functions:
-- decode(string)
-- and encode(table)
--------------------------------
function decode(data)
if #data == 0 then
return nil
end
if string.match(data, "^#bundle") then
return decode_bundle(data)
else
return decode_message(data)
end
end
function encode(data)
local msg = ""
local idx = 1
if data == nil then
return nil
end
if data[1] == "#bundle" then
msg = msg .. encode_string(data[1])
--print("1 "..msg.."\n")
msg = msg .. encode_timetag(data[2])
--print("2 "..msg.."\n")
idx = 3
while idx <= #data do
local submsg = encode(data[idx])
msg = msg .. encode_int(#submsg) .. submsg
--print(idx.." "..submsg.."\n")
idx = idx + 1
end
return msg
else
local typestring = ","
local encodings = ""
idx = idx + 1
msg = msg .. encode_string(data[1])
for t, d in iter_pairwise(data, idx) do
typestring = typestring .. t
encodings = encodings .. collect_encoding_for_message(t, d)
end
--print("else "..msg..encode_string(typestring) .. encodings.."\n")
return msg .. encode_string(typestring) .. encodings
end
end
--------------------------------
-- auxilliary functions
--------------------------------
digits = {}
for i=0,9 do digits[i] = string.char(string.byte('0')+i) end
for i=10,36 do digits[i] = string.char(string.byte('A')+i-10) end
function numberstring(number, bas)
local s = ""
repeat
local remainder = base.math.mod(number,bas)
s = digits[remainder]..s
number = (number-remainder)/bas
until number==0
return s
end
function next_string(astring)
-- this is a workaraound because the lua pttern matching is
-- not as powerful as pcre and I did not want to include another
-- dependecy to an external re lib
local pos = 0
local num_nzero = 0
local num_zero = 0
local result = ""
if astring == nil then
-- ensure that string is not empty
base.error("error: string is empty - probably malformated message")
end
-- we match every character with the help of gmatch
for m in string.gmatch(astring, ".") do
pos = pos + 1
-- and then check if it is correctly padded with '\0's
if m ~= '\0' and num_zero == 0 then
num_nzero = (num_nzero + 1) % 4
result = result .. m
elseif num_zero ~= 0 and (num_zero + num_nzero) % 4 == 0 then
return result, pos
elseif m == '\0' then
num_zero = num_zero + 1
result = result .. m
else
return nil
end
end
end
function iter_pairwise(atable, startvalue)
local index = startvalue - 2
return function()
index = index + 2
return atable[index], atable[index+1]
end
end
function collect_encoding_for_message(t, data)
if t == 'i' then
return encode_int(data)
elseif t == 'f' then
return encode_float(data)
elseif t == 's' then
return encode_string(data)
elseif t == 'b' then
return encode_blob(data)
end
end
function collect_decoding_from_message(t, data, message)
table.insert(message, t)
if t == 'i' then
table.insert(message, decode_int(data))
return string.sub(data, 5)
elseif t == 'f' then
table.insert(message, decode_float(data))
return string.sub(data, 5)
elseif t == 's' then
local match, last = next_string(data)
table.insert(message, match)
return string.sub(data, last)
elseif t == 'b' then
local length = decode_int(data)
table.insert(message, string.sub(data, 4, length))
return string.sub(data, 4 + length + 1)
end
end
function get_addr_from_data(data)
local addr_raw_string,last = next_string(data)
local result = ""
if addr_raw_string == nil then
-- if we could not find an addr something went wrong
base.error("error: could not extract address from OSC message")
end
-- delete possible trailing zeros
for t in string.gmatch(addr_raw_string, "[^%z]") do
result = result .. t
end
return result, string.sub(data, last)
end
function get_types_from_data(data)
local typestring, last = next_string(data)
local result = {}
if typestring == nil then
return {}
end
-- split typestring into an iterable table
for t in string.gmatch(typestring, "[^,%z]") do
table.insert(result, t)
end
return result, string.sub(data, last)
end
--------------------------------
-- decoding functions
--------------------------------
function decode_message(data)
local types, addr, tmp_data = nil
local message = {}
addr, tmp_data = get_addr_from_data(data)
types, tmp_data = get_types_from_data(tmp_data)
-- ensure that we at least found something
if addr == nil or types == nil then
return nil
end
for _,t in base.ipairs(types) do
tmp_data = collect_decoding_from_message(t, tmp_data, message)
end
return message
end
function decode_bundle(data)
local match, last = next_string(data)
local tmp_data = nil
local msg = {}
local sec, frac
-- skip first string data since it will only contian #bundle
tmp_data = string.sub(data, 9)
-- check that there is a part of the message left
if not tmp_data then
return nil
end
table.insert(msg, "#bundle")
_, sec, frac = upack("> u4 > u4", {string.sub(tmp_data, 1, 8)})
-- note this is an awful way of decoding to a bin string and
-- then decoding the frac again TODO: make this nicer
frac = numberstring(frac, 2)
if sec == 0 and frac == IMMEDIATE then
table.insert(msg, 0)
else
table.insert(msg, sec - ADJUSTMENT_FACTOR + decode_frac(frac) )
end
tmp_data = string.sub(tmp_data, 9)
while #tmp_data > 0 do
local length = decode_int(string.sub(tmp_data,1,4))
table.insert(msg, decode(string.sub(tmp_data, 5, 4 + length)))
tmp_data = string.sub(tmp_data, 9 + length)
end
return msg
end
function decode_frac(bin)
local frac = 0
for i=#bin,1 do
frac = (frac + string.sub(bin, i-1, i)) / 2
end
return frac
end
function decode_float(bin)
local pos, res = upack("> f4", {bin})
return res
end
function decode_int(bin)
local pos, res = upack("> i4", {bin} )
return res
end
--------------------------------
-- encoding
--------------------------------
function encode_string(astring)
local fillbits = (4 - #astring % 4)
return astring .. string.rep('\0', fillbits)
end
function encode_int(num)
return pack("> i4",{ num })
end
function encode_blob(blob)
return encode_int(#blob) .. encode_string(#blob)
end
function encode_timetag(tpoint)
if tpoint == 0 then
return IMMEDIATE
else
local sec = math.floor(tpoint)
local frac = tpoint - sec
return pack("> u4 > u4", {sec + ADJUSTMENT_FACTOR , encode_frac(frac)})
end
end
function encode_frac(num)
local bin = ""
local frac = num
while #bin < 32 do
bin = bin .. base.math.floor(frac * 2)
frac = (frac * 2) - base.math.floor(frac * 2)
end
return bin
end
function encode_float(num)
return pack("> f4", {num})
end

View File

@ -0,0 +1,3 @@
osc = {}
require "LICK/lib/loveosc/client"
require "LICK/lib/loveosc/server"

View File

@ -0,0 +1,81 @@
--[[
-- luaosc Copyright (C) 2009 Jost Tobias Springenberg <k-gee@wrfl.de> --
This file is part of luaosc.
luaosc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
luaosc 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
--]]
-- This is a luaOSC Fork from Jost Tobias Springenberg, additional code and modifications by Tilmann Hars, Headchant.com, Copyright 2010
require "socket"
osc.server = {}
osc.server.host = "localhost"
osc.server.port = 7771
osc.server.socket = socket.udp() or error('error could not create lua socket object')
osc.server.socket:setsockname(osc.server.host, osc.server.port)
osc.server.socket:settimeout(0)
-- call this in LÖVE update
function osc.server:update(dt)
local message, from = osc.server.socket:receive(1024)
-- invoke handler function
if message ~= nil then
local success, result = pcall(decode, message)
if not success then
print("Error in decoding: \n" .. result)
else
success, result = pcall(handle, from, result)
if not success then
print("Error in your handler function: \n" .. result)
end
end
end
if message == "exit" then
return
end
end
-- use this to start the server in lua only (not with LÖVE!)
function osc.server:start()
local length = 1024
while 1 do
local message, from = self.socket:receivefrom(1024)
-- invoke handler function
if message ~= nil then
local success, result = base.pcall(osc.decode, message)
if not success then
base.io.stderr:write("Error in decoding: \n" .. result)
else
success, result = base.pcall(self.handle, from, result)
if not success then
base.io.stderr:write("Error in your handler function: \n" .. result)
end
end
end
if message == "exit" then
return
end
end
end
function osc.server:setHandler(hdle)
handle = hdle
end

View File

@ -0,0 +1,30 @@
1.0
---
Bugfixes to read error handling
Ability to return unpacked values rather than tables
1.0 beta 4
----------
Added the ability to say 's' with no width to read until EOF.
Modified struct.unpack and struct.pack to return the number of bytes
read/written as a second value. Note that this is not the same as the r/w
pointer delta if seeks are involved.
1.0 beta 3
----------
Lots of bugfixing and general cleanup
Improved error reporting
API name changes
1.0 beta 2
----------
Added the counted string format "c".
Added float and double support, courtesy of Peter "Corsix" Cawley.
Updated the test framework.
Fixed a bug in format m that could result in data loss when manipulating fields
of 7 bytes or more width.
1.0 beta 1
----------
Released to the world.

View File

@ -0,0 +1,19 @@
Copyright © 2008 Ben "ToxicFrog" Kelly
FP module copyright © 2008 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,290 @@
Contents
========
1. Overview
2. API
3. Warning!
4. The Format String
Naming
Grouping
Repetition
5. Format Specifiers
6. Credits
1. Overview
===========
VStruct is a library for Lua 5.1. It provides functions for manipulating binary
data, in particular for unpacking binary files or byte buffers into Lua values
and for packing Lua values back into files or buffers. Supported data types
include:
- signed and unsigned integers of arbitrary byte width
- booleans and bitmasks
- plain and null-terminated strings
- fixed and floating point reals (the latter requires C module support)
In addition, the library supports seeking, alignment, and byte order controls,
repetition, grouping of data into tables, and naming of values within tables.
2. API
======
exports:
vstruct.pack(fmt, [fd], data)
vstruct.unpack(fmt, <fd or string>, [unpacked])
vstruct.explode(int)
vstruct.implode(table)
vstruct.cursor(string)
vstruct.compile.read(format)
vstruct.compile.write(format)
pack takes a format string and a table of data and packs the contents into a
buffer. If the fd argument is present, it will write the data directly to it
using standard file io methods (write and seek), and return the fd; otherwise
it will construct and return a string. In either case it also returns (as a
second value) the number of bytes written - note that if the format involved
seeks, this is not the same as the amount by which the write pointer moved
or the size of the packed string.
unpack takes a format string and a buffer or file to unpack from, and returns
the unpacked data as a table. It also returns (as a second value) the number of
bytes read - note that if the format string involved seeks, this is not the same
as the difference between read pointer positions. If the _unpacked_ argument is
true, it will return the unpacked data as a series of values rather than as a
table, equivalent to using the standard Lua function unpack() on the return
value. Note that this means it will not return the number of bytes read as an
additional value.
explode converts a bitmask into a list of booleans, and implode does the
converse. In such lists, list[1] is the least significant bit, and list[n] the
most significant.
cursor wraps a string in something that looks, at first glance, like a file.
This permits strings to be wrapped and passed to the vstruct IO functions. The
wrapped string supports :seek, and has limited support for :read (the only
supported calling mode is :read(num_bytes)) and :write (as :write(buffer)).
compile.read takes a format string and returns a function, which can later be
passed a file (or file-like object - see vstruct.cursor) to perform a read
operation. In effect, the following code:
f = vstruct.compile.read(fmt)
d = f(fd)
Is equivalent to:
d = vstruct.unpack(fd, fmt)
f can of course be called repeatedly, with different or the same fds each time.
compile.write is the converse of compile.read. The emitted function expects a
file and a table of data elements, so that:
f = vstruct.compile.write(fmt)
f(fd, data)
Is equivalent to:
vstruct.pack(fd, fmt, data)
As with compile.read, the emitted function is fully re-usable.
3. Warning!
===========
When reading and writing numeric formats, vstruct is inherently limited by lua's
number format, which is by default the IEEE 754 double. What this means in
practice is that formats cipPu may be subject to data loss when read in widths
of 7 bytes or more, if they contain more than 52 significant bits. (The same is
true of numeric constants declared in Lua itself, of course, and other libraries
which store values in lua numbers).
Formats bfmsxz are unaffected by this, as they either do not use lua numbers or
are guaranteed to fit inside them.
4. The Format String
====================
The format string contains any number of endianness controls, seek controls,
format specifiers, and grouping/naming sequences, seperated by whitespace,
commas, or semicolons (or any mix thereof, although you are encouraged to choose
one and stick to it for the sake of consistency). Each of these is detailed
below.
In the documentation below, the convention is that A represents an address and W
a width in bytes. At present only base-10 numerals are supported.
Naming
------
Under normal operation, when unpacking, the library simply stores unpacked
values sequentially into a list, which is returned. Similarly, when packing, it
expects a list of values which will be packed in order. However, values can be
named, in which case the unpacked value will be stored in a field with that
name, and when packing, it will use the value stored with that key. This is done
by prefixing the format specifier with the name (which can be any sequence of
letters, numbers, and _, provided it does not start with a number) followed by a
':'. For example, the following format would generate a table with three keys,
'x', 'y', and 'z':
"x:u4 y:u4 z:u4"
And, when packing, would expect a table with those three keys and store their
corresponding values.
If the same name is specified multiple times, or is combined with repetition
(see below), only the last read value is stored there.
Named and anonymous values can be freely mixed; the named values will be
assigned to their given fields and the anonymous ones to sequential indices.
Grouping
--------
Rather than generating or expecting a flat table, the library can be instructed to
create or read from a table containing subtables. This is done by surrounding the
group of values you wish to be packed with '{' and '}' in the format string. For example,
the following format string:
"{ u4 i4 } { s32 u4 }"
Would, rather than generating a list of four values, generate a list containing two
lists of two values each.
Similarly, when packing, it would expect not a flat list, but a list of sublists, from
which the values to be packed will be drawn.
Groups can be named, so formats like:
"flags:m1 coords:{ x:u4 y:u4 z:u4 }"
Are permitted and meaningful.
Repetition
----------
A {} group can be repeated by prefixing or suffixing it with a count, seperated
from the group by a '*'. For example:
"4 * { u4 }"
"{ u4 } * 4"
"{ u4 } { u4 } { u4 } { u4 }"
Are all equivalent. Note that the whitespace in the above examples is optional.
In cases where you want to repeat format specifiers without implying a grouping,
you can use (). For example:
"4 * (u4 b1)"
Is equivalent to:
"u4 b1 u4 b1 u4 b1 u4"
Like grouping, these can be nested.
5. Format Specifiers
====================
Endianness Controls
-------------------
The formats i, m, and u are affected by the endianness setting, which controls
the order in which bytes are read and written within a field. The following
characters in a format string adjust the endianness setting:
<
Sets the endianness to little-endian (eg, Intel processors)
>
Sets the endianness to big-endian (eg, PPC and Motorola processors)
=
Sets the endianness to the native endianness.
Seek Controls
-------------
These characters are used to seek to specific locations in the input or output.
Note that they only work on buffers or file-like objects that support the seek()
method; for streams which cannot be sought on, use the 'x' (skip/null-pad)
data format instead.
@A
Seek to absolute address A.
+A
Seek forward A bytes.
-A
Seek backwards A bytes.
aW
Align to word width W (ie, seek to the next address which is a multiple of W)
Data Format Specifiers
----------------------
bW Boolean.
Read: as uW, but returns true if the result is non-zero and false otherwise.
Write: as uW with input 1 if true and 0 otherwise.
cW Counted string.
Read: uW to determine the length of the string W', followed by sW'.
Write: the length of the string as uW, followed by the string itself.
The counted string is a common idiom where a string is immediately prefixed
with its length, as in:
size_t len;
char[] str;
The counted string format can be used to easily read and write these. The
width provided is the width of the len field, which is treated as an
unsigned int. Only the string itself is returned (when unpacking) or
required (when packing).
The len field is affected by endianness, as in format u.
fW IEEE 754 floating point.
Valid widths are 4 (float) and 8 (double). No quads yet, sorry!
Affected by endianness.
iW Signed integer.
Read: a signed integer of width W bytes.
Write: a signed integer of width W bytes.
Floating point values will be truncated.
Affected by endianness.
mW Bitmask.
Read: as uW, but explodes the result into a list of booleans, one per bit.
Write: implodes the input value, then writes it as uW.
Affected by endianness.
See also: vstruct.implode, vstruct.explode.
pW Signed fixed point rational.
Width is in the format "I.F"; the value before the dot is the number of
bytes in the integer part, and the value after, in the fractional part.
Read: a fixed point rational of I+F bytes.
Write: a fixed point rational of I+F bytes. Values which cannot be exactly
represented in the specified width are truncated.
Affected by endianness.
PW Signed fixed point rational with bit-aligned subfields
Equivalent to pW, except that the decimal point does not need to be byte
aligned; for example, formats such as P20.12 are possible.
Note that underlying reads must still occur in byte multiples. Using a W
such that I+F is not a multiple of 8 is an error.
sW String.
Read: reads exactly W bytes and returns them as a string. If W is omitted,
reads until EOF.
Write:
If W is omitted, uses the string length.
If W is shorter than the string length, truncates the string.
If W is greater than the string length, null pads the string.
uW Unsigned integer.
Read: an unsigned integer of width W bytes.
Write: an unsigned integer of width W bytes.
Floating point values will be truncated.
Negative values will be taken absolute.
Affected by endianness.
xW Skip/pad.
Read: read and discard the next W bytes.
Write: write W zero bytes.
zW Null terminated string.
Read: reads exactly W bytes. Returns everything up to the first zero byte.
If W is omitted, reads up to the next zero byte.
Write: writes exactly W bytes.
If the input is shorter than W, zero pads the output.
If as long or longer, truncates to W-1 and writes a zero byte at the end.
If W is omitted, uses the string length plus one (ie, writes the string
out entire and then null terminates it).
6. Credits
==========
While most of the library code was written by me (Ben Kelly), the existence
of this library owes itself to many others:
The floating point code was contributed by Peter Cawley on lua-l.
The original inspiration came from Roberto Ierusalimschy's "struct" library
and Luiz Henrique de Figueiredo's "lpack" library, as well as the "struct"
available in Python.
sanooj, from #lua, has done so much testing and bug reporting that at this
point he's practically a co-author.
The overall library design and interface are the result of much discussion
with rici, sanooj, Keffo, snogglethorpe, Spark, kozure, Vornicus, McMartin, and
probably several others I've forgotten about on IRC (#lua on freenode and #code
on nightstar).
Finally, without Looking Glass Studios to make System Shock, and Team TSSHP
(in particular Jim "hairyjim" Cameron) to reverse engineer it, I wouldn't have
had a reason to write this library in the first place.

View File

@ -0,0 +1,48 @@
-- shared formats - seeking, endianness
-- these should all return nil so that they do not mutate the data list
-- Copyright © 2008 Ben "ToxicFrog" Kelly; see COPYING
local common = {}
-- determine if the host system is big-endian or not, by dumping an empty
-- function and looking at the endianness flag
-- this is kind of hackish
local function bigendian()
return string.byte(string.dump(function() end)) == string.char(0x00)
end
common.is_bigendian = bigendian()
-- seek controls
function common.seekto(fd, w)
fd:seek("set", w)
end
function common.seekforward(fd, w)
fd:seek("cur", w)
end
function common.seekback(fd, w)
fd:seek("cur", -w)
end
function common.a(fd,w)
local a = fd:seek()
if a % w ~= 0 then
fd:seek("cur", w - (a % w))
end
end
-- endianness controls
function common.littleendian(fd, w)
common.is_bigendian = false
end
function common.bigendian(fd, w)
common.is_bigendian = true
end
function common.hostendian(fd, w)
common.is_bigendian = bigendian()
end
return common

View File

@ -0,0 +1,134 @@
-- functions for turning a format string into a callable function
-- they work by calling parse(), passing it the format string and
-- a table of code generators appropriate for whether we are reading
-- or writing.
-- The resulting code is then prefixed with some setup code and postfixed
-- with a return value and loadstring() is called on it to generate a function
-- Copyright <20> 2008 Ben "ToxicFrog" Kelly; see COPYING
local require,loadstring,setfenv,type,select,unpack,setmetatable
= require,loadstring,setfenv,type,select,unpack,setmetatable
local print,assert,error,xpcall,pairs,where
= print,assert,error,xpcall,pairs,debug.traceback
module((...))
local parse = require(_PACKAGE.."parser")
local function nulsafe_error(s)
return error(s:gsub('%z', '_'))
end
local function xpcall2(f, err, ...)
local args = {n=select('#', ...), ...}
return xpcall(function() return f(unpack(args, 1, args.n)) end, err)
end
local function err_generate(message, format, trace)
nulsafe_error([[
struct: internal error in code generator
This is an internal error in the struct library
Please report it as a bug and include the following information:
-- error message
]]..message.."\n\n"..[[
-- format string
]]..format.."\n\n"..[[
-- stack trace
]]..trace)
end
local function err_compile(message, format, source)
nulsafe_error([[
struct: syntax error in emitted lua source
This is an internal error in the struct library
Please report it as a bug and include the following information:
-- loadstring error
]]..message.."\n\n"..[[
-- format string
]]..format.."\n\n"..[[
-- emitted source
]]..source.."\n\n"..[[
-- stack trace
]])
end
local function err_execute(message, format, source, trace)
nulsafe_error([[
struct: runtime error in generated function
This is at some level an internal error in the struct library
It could be a genuine error in the emitted code (in which case this is a code
generation bug)
Alternately, it could be that you gave it a malformed format string, a bad
file descriptor, or data that does not match the given format (in which case
it is an argument validation bug and you should be getting an error anyways).
Please report this as a bug and include the following information:
-- execution error
]]..message.."\n\n"..[[
-- format string
]]..format.."\n\n"..[[
-- emitted source
]]..source.."\n\n"..[[
-- stack trace
]]..trace)
end
local function compile(format, gen, env)
local status,source = xpcall(function()
return parse(format, gen, true)
end,
function(message)
return { message, where("",2) }
end)
if not status then
if type(source[1]) == "function" then
error(source[1]()..source[2])
end
err_generate(source[1], format, source[2])
end
local fn,err = loadstring(source)
if not fn then
err_compile(err, format, source)
end
setfenv(fn, env)
local fn = function(...)
local status,ret,len = xpcall2(fn, function(message)
return { message, where("",2) }
end, ...)
-- call succeeded without errors
if status then return ret,len end
local message,where = ret[1],ret[2]
-- call generated a deliberate error; call the provided closure
-- it will either emit an error code or re-throw
if type(message) == "function" then return nil,message() end
-- call generated an internal error; re-throw with extra debug info
err_execute(message, format, source, where)
end
return fn
end
local gen_unpack = require(_PACKAGE.."gen_unpack")
local io_unpack = require(_PACKAGE.."io_unpack")
function _M.unpack(format)
return compile(format, gen_unpack, io_unpack)
end
local gen_pack = require(_PACKAGE.."gen_pack")
local io_pack = require(_PACKAGE.."io_pack")
function _M.pack(format)
return compile(format, gen_pack, io_pack)
end
return _M

View File

@ -0,0 +1,80 @@
-- cursor - a wrapper for strings that makes them look like files
-- exports: seek read write
-- read only supports numeric amounts
-- Copyright © 2008 Ben "ToxicFrog" Kelly; see COPYING
local cursor = {}
-- like fseek
-- seeking past the end of the string is permitted
-- reads will return EOF, writes will fill in the intermediate space with nuls
-- seeking past the start of the string is a soft error
function cursor:seek(whence, offset)
whence = whence or "cur"
offset = offset or 0
if whence == "set" then
self.pos = offset
elseif whence == "cur" then
self.pos = self.pos + offset
elseif whence == "end" then
self.pos = #self.str + offset
else
error "bad argument #1 to seek"
end
if self.pos < 0 then
self.pos = 0
return nil,"attempt to seek prior to start of file"
end
return self.pos
end
-- read n bytes from the current position
-- reads longer than the string can satisfy return as much as it can
-- reads while the position is at the end return nil,"eof"
function cursor:read(n)
if self.pos >= #self.str then
return nil,"eof"
end
if n == "*a" then
n = #self.str
end
local buf = self.str:sub(self.pos+1, self.pos + n)
self.pos = math.min(self.pos + n, #self.str)
return buf
end
-- write the contents of the buffer at the current position, overwriting
-- any data already present
-- if the write pointer is past the end of the string, also fill in the
-- intermediate space with nuls
function cursor:write(buf)
if self.pos > #self.str then
self.str = self.str .. string.char(0):rep(self.pos - #self.str)
end
self.str = self.str:sub(1, self.pos)
.. buf
.. self.str:sub(self.pos + #buf + 1, -1)
self.pos = self.pos + #buf
return self
end
function cursor:__call(source)
assert(type(source) == "string", "invalid first argument to cursor()")
return setmetatable(
{ str = source, pos = 0 },
cursor)
end
cursor.__index = cursor
setmetatable(cursor, cursor)
return cursor

View File

@ -0,0 +1,121 @@
-- floating point module
-- Copyright © 2008 Peter "Corsix" Cawley and Ben "ToxicFrog" Kelly; see COPYING
local fp = {}
local name = (...):gsub('%.[^%.]+$', '')
local struct = require (name)
local common = require (name..".common")
local function reader(data, size_exp, size_fraction)
local fraction, exponent, sign
local endian = common.is_bigendian and ">" or "<"
-- Split the unsigned integer into the 3 IEEE fields
local bits = struct.unpack(endian.."m"..#data, data, true)
local fraction = struct.implode({unpack(bits, 1, size_fraction)}, size_fraction)
local exponent = struct.implode({unpack(bits, size_fraction+1, size_fraction+size_exp)}, size_exp)
local sign = bits[#bits] and -1 or 1
-- special case: exponent is all 1s
if exponent == 2^size_exp-1 then
-- significand is 0? +- infinity
if fraction == 0 then
return sign * math.huge
-- otherwise it's NaN
else
return 0/0
end
end
-- restore the MSB of the significand, unless it's a subnormal number
if exponent ~= 0 then
fraction = fraction + (2 ^ size_fraction)
else
exponent = 1
end
-- remove the exponent bias
exponent = exponent - 2 ^ (size_exp - 1) + 1
-- Decrease the size of the exponent rather than make the fraction (0.5, 1]
exponent = exponent - size_fraction
return sign * math.ldexp(fraction, exponent)
end
local function writer(value, size_exp, size_fraction)
local fraction, exponent, sign
local width = (size_exp + size_fraction + 1)/8
local endian = common.is_bigendian and ">" or "<"
local bias = 2^(size_exp-1)-1
if value < 0
or 1/value == -math.huge then -- handle the case of -0
sign = true
value = -value
else
sign = false
end
-- special case: value is infinite
if value == math.huge then
exponent = bias+1
fraction = 0
-- special case: value is NaN
elseif value ~= value then
exponent = bias+1
fraction = 2^(size_fraction-1)
--special case: value is 0
elseif value == 0 then
exponent = -bias
fraction = 0
else
fraction,exponent = math.frexp(value)
-- subnormal number
if exponent+bias <= 1 then
fraction = fraction * 2^(size_fraction+(exponent+bias)-1)
exponent = -bias
else
-- remove the most significant bit from the fraction and adjust exponent
fraction = fraction - 0.5
exponent = exponent - 1
-- turn the fraction into an integer
fraction = fraction * 2^(size_fraction+1)
end
end
-- add the exponent bias
exponent = exponent + bias
local bits = struct.explode(fraction)
local bits_exp = struct.explode(exponent)
for i=1,size_exp do
bits[size_fraction+i] = bits_exp[i]
end
bits[size_fraction+size_exp+1] = sign
return struct.pack(endian.."m"..width, {bits})
end
-- Create readers and writers for the IEEE sizes
fp.sizes = {
[4] = {1, 8, 23},
[8] = {1, 11, 52},
}
fp.r = {}
fp.w = {}
for width, sizes in pairs(fp.sizes) do
fp.r[width] = function(uint) return reader(uint, sizes[2], sizes[3]) end
fp.w[width] = function(valu) return writer(valu, sizes[2], sizes[3]) end
end
return fp

View File

@ -0,0 +1,132 @@
local require,table
= require,table
module((...))
local parse = require(_PACKAGE.."parser")
local gen = {}
gen.preamble = [[
local fd,data = ...
local stack = {}
local index = 1
local start = fd:seek()
local len = 0
local function push(key)
if not key then
key = index
index = index + 1
end
stack[#stack+1] = { index, data }
data = data[key]
index = 1
end
local function pop(key)
local saved = stack[#stack]
stack[#stack] = nil
index = saved[1]
data = saved[2]
end
local function update_len()
len = len + fd:seek() - start
end
local function update_start()
start = fd:seek()
end
hostendian()
]]
gen.postamble = [[
update_len()
return fd,len
]]
-- control:
-- <<type>>(fd, <<args>>)
function gen.control(token)
local tr = {
["<"] = "littleendian";
[">"] = "bigendian";
["="] = "hostendian";
["+"] = "seekforward";
["-"] = "seekback";
["@"] = "seekto";
}
local fn = tr[token[1]] or token[1]
local args = token[2]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return "update_len(); "..fn.."(fd, "..args..")".."; update_start()"
end
-- atom:
-- <<type>>(fd, data[index], <<args>>)
-- ++index
function gen.atom(token)
local fn = token[1]
local args = token[2]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return fn.."(fd, data[index], "..args..")\nindex = index+1"
end
-- table:
-- push()
-- <<table contents>>
-- pop()
function gen.table(token)
return "push()\n"
..parse(token[1]:sub(2,-2), gen)
.."\npop()"
end
-- group:
-- <<group contents>>
function gen.group(token)
return parse(token[1]:sub(2,-2), gen)
end
-- named atom:
-- <<type>>(fd, data.<<name>>, <<args>>)
function gen.name_atom(token)
local fn = token[2]
local args = token[3]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return fn.."(fd, data."..token[1]..", "..args..")"
end
-- named table:
-- push(<<name>>)
-- <<table contents>>
-- pop()
function gen.name_table(token)
return "push('"..token[1].."')\n"
..parse(token[2]:sub(2,-2), gen)
.."\npop()"
end
function gen.prerepeat(token, get)
local next = get()
local src = gen[next.type](next, get)
return "for _idx=1,"..token[1].." do\n\n"..src.."\nend"
end
function gen.postrepeat(token, get, asl)
local src = table.remove(asl)
return "for _idx=1,"..token[1].." do\n\n"..src.."\nend"
end
return gen

View File

@ -0,0 +1,117 @@
local require,table
= require,table
module((...))
local parse = require(_PACKAGE.."parser")
local gen = {}
gen.preamble = [[
local fd = (...)
local stack = {}
local pack = {}
local start = fd:seek()
local len = 0
local function push()
stack[#stack+1],pack = pack,{}
end
local function pop(key)
local target = stack[#stack]
key = key or #target+1
target[key],pack = pack,target
stack[#stack] = nil
end
local function update_len()
len = len + fd:seek() - start
end
local function update_start()
start = fd:seek()
end
hostendian()
]]
gen.postamble = [[
update_len()
return pack,len
]]
-- control:
-- <<type>>(fd, <<args>>)
function gen.control(token)
local tr = {
["<"] = "littleendian";
[">"] = "bigendian";
["="] = "hostendian";
["+"] = "seekforward";
["-"] = "seekback";
["@"] = "seekto";
}
local fn = tr[token[1]] or token[1]
local args = token[2]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return "update_len(); "..fn.."(fd, "..args..")".."; update_start()"
end
-- atom:
-- pack[#pack+1] = <<type>>(fd, <<args>>)
function gen.atom(token)
local fn = token[1]
local args = token[2]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return "pack[#pack+1] = "..fn.."(fd, "..args..")"
end
-- table:
-- push()
-- <<table contents>>
-- pop()
function gen.table(token)
return "push()\n"
..parse(token[1]:sub(2,-2), gen)
.."\npop()"
end
-- group:
-- <<group contents>>
function gen.group(token)
return parse(token[1]:sub(2,-2), gen)
end
function gen.name_atom(token)
local fn = token[2]
local args = token[3]:gsub('%.', ', ')
if #args == 0 then args = "nil" end
return "pack."..token[1].." = "..fn.."(fd, "..args..")"
end
function gen.name_table(token)
return "push()\n"
..parse(token[2]:sub(2,-2), gen)
.."\npop('"..token[1].."')\n"
end
function gen.prerepeat(token, get)
local next = get()
local src = gen[next.type](next, get)
return "for _idx=1,"..token[1].." do\n\n"..src.."\nend"
end
function gen.postrepeat(token, get, asl)
local src = table.remove(asl)
return "for _idx=1,"..token[1].." do\n\n"..src.."\nend"
end
return gen

View File

@ -0,0 +1,94 @@
-- vstruct, the versatile struct library
-- Copyright <20> 2008 Ben "ToxicFrog" Kelly; see COPYING
local table,math,type,require,assert,_unpack = table,math,type,require,assert,unpack
local print = print
module((...))
cursor = require (_NAME..".cursor")
compile = require (_NAME..".compile")
function math.trunc(n)
if n < 0 then
return math.ceil(n)
else
return math.floor(n)
end
end
-- turn an int into a list of booleans
-- the length of the list will be the smallest number of bits needed to
-- represent the int
function explode(int, size)
assert(int, "struct.explode: missing argument")
size = size or 0
local mask = {}
while int ~= 0 or #mask < size do
table.insert(mask, int % 2 ~= 0)
int = math.trunc(int/2)
end
return mask
end
-- turn a list of booleans into an int
-- the converse of explode
function implode(mask, size)
size = size or #mask
local int = 0
for i=size,1,-1 do
int = int*2 + ((mask[i] and 1) or 0)
end
return int
end
-- given a source, which is either a string or a file handle,
-- unpack it into individual data based on the format string
function unpack(fmt, source, untable)
-- wrap it in a cursor so we can treat it like a file
if type(source) == 'string' then
source = cursor(source)
end
assert(fmt and source and type(fmt) == "string", "struct: invalid arguments to unpack")
-- the lexer will take our format string and generate code from it
-- it returns a function that when called with our source, will
-- unpack the data according to the format string and return all
-- values from said unpacking in a list
if untable then
--local t = compile.unpack(fmt)(source)
--print(t)
-- print(_unpack(t))
return _unpack((compile.unpack(fmt)(source)))
else
return compile.unpack(fmt)(source)
end
end
-- given a format string and a list of data, pack them
-- if 'fd' is omitted, pack them into and return a string
-- otherwise, write them directly to the given file
function pack(fmt, fd, data)
local str_fd
if not data then
data = fd
fd = ""
end
if type(fd) == 'string' then
fd = cursor("")
str_fd = true
end
assert(fmt and fd and data and type(fmt) == "string", "struct: invalid arguments to pack")
local fd,len = compile.pack(fmt)(fd, data)
return (str_fd and fd.str) or fd,len
end
return struct

View File

@ -0,0 +1,127 @@
-- write formats
-- return true if they have consumed a value from the input stream
-- return false/nil otherwise (ie, the next value will be preserved
-- for subsequent calls, eg skip/pad)
-- Copyright © 2008 Ben "ToxicFrog" Kelly; see COPYING
local require,error,setmetatable,string,print,math,unpack,io
= require,error,setmetatable,string,print,math,unpack,io
module((...))
local struct = require (_PACKAGE:sub(1,-2))
local common = require (_PACKAGE.."common")
local fp = require (_PACKAGE.."fp")
local pack = setmetatable({}, { __index = common })
-- boolean
function pack.b(fd, d, w)
return pack.u(fd, (d and 1) or 0, w)
end
-- counted string
-- a string immediately prefaced with its length as a uint
function pack.c(fd, d, w)
pack.u(fd, #d, w)
return pack.s(fd, d)
end
-- floating point
function pack.f(fd, d, w)
if not fp.w[w] then
error("struct.pack: illegal floating point width")
end
-- local f = fp.w[w](d)
-- print(f, type(f))
return pack.s(fd, fp.w[w](d), w)
end
-- signed int
function pack.i(fd, d, w)
if d < 0 then
d = 2^(w*8) + d
end
return pack.u(fd, d, w)
end
-- bitmask
-- we use a string here because using an unsigned will lose data on bitmasks
-- wider than lua's native number format
function pack.m(fd, d, w)
local buf = ""
for i=1,w*8,8 do
local bits = { unpack(d, i, i+7) }
local byte = string.char(struct.implode(bits, 8))
if pack.is_bigendian then
buf = byte..buf
else
buf = buf..byte
end
end
return pack.s(fd, buf, w)
end
-- fixed point bit aligned
function pack.P(fd, d, dp, fp)
if (dp+fp) % 8 ~= 0 then
error "total width of fixed point value must be byte multiple"
end
return pack.i(fd, d * 2^fp, (dp+fp)/8)
end
-- fixed point byte aligned
function pack.p(fd, d, dp, fp)
return pack.P(fd, d, dp*8, fp*8)
end
-- fixed length string
-- length 0 is write string as is
-- length >0 is write exactly w bytes, truncating or padding as needed
function pack.s(fd, d, w)
w = w or #d
if w == 0 then return end
if #d < w then
d = d..string.char(0):rep(w-#d)
end
return fd:write(d:sub(1,w))
end
-- unsigned int
function pack.u(fd, d, w)
local s = ""
for i=1,w do
if pack.is_bigendian then
s = string.char(d % 2^8) .. s
else
s = s .. string.char(d % 2^8)
end
d = math.trunc(d/2^8)
end
return pack.s(fd, s, w)
end
-- skip/pad
-- this is technically a control format, so it has a different signature
-- specifically, there is no "data" argument
function pack.x(fd, w)
return pack.s(fd, "", w)
end
-- null terminated string
-- w==nil is write string as is + termination
-- w>0 is write exactly w bytes, truncating/padding and terminating
function pack.z(fd, d, w)
w = w or #d+1
if #d >= w then
d = d:sub(1, w-1)
end
return pack.s(fd, d.."\0", w)
end
return pack

View File

@ -0,0 +1,165 @@
-- read formats
-- return a value if applicable, which will be packed
-- otherwise return nil
-- Copyright <20> 2008 Ben "ToxicFrog" Kelly; see COPYING
-- load operations common to both unpack and pack, and set __index so that
-- requests for, say, unpack.seekto will succeed
local require,error,setmetatable,string,print
= require,error,setmetatable,string,print
module((...))
local struct = require (_PACKAGE:sub(1,-2))
local common = require (_PACKAGE.."common")
local fp = require (_PACKAGE.."fp")
local unpack = setmetatable({}, { __index = common })
-- boolean
-- true if any bit is 1, false otherwise
function unpack.b(fd, w)
return unpack.u(fd, w) ~= 0
end
-- counted string
-- a string immediately prefaced with its length as a uint
function unpack.c(fd, w)
w = unpack.u(fd, w)
return unpack.s(fd, w)
end
-- float
-- this is callout to the floating-point read/write module, if installed
function unpack.f(fd, w)
if not fp.r[w] then
error("struct.unpack: illegal floating point width")
end
return fp.r[w](unpack.s(fd,w))
end
-- utility functions for the i, m and u formats
local function directions(w)
if unpack.is_bigendian then
return 1,w,1
else
return w,1,-1
end
end
local function pve_unpack(buf, w)
local i,sof,eof,dir = 0,directions(w)
for c=sof,eof,dir do
i = i * 2^8 + buf:byte(c)
end
return i
end
local function nve_unpack(buf, w)
local i,sof,eof,dir = 0,directions(w)
if buf:byte(sof) < 128 then
return pve_unpack(buf, w)
end
for c=sof,eof,dir do
i = i * 2^8 - (255 - buf:byte(c))
end
return i-1
end
-- signed int of w bytes
function unpack.i(fd, w)
local buf = unpack.s(fd, w)
return nve_unpack(buf, w)
end
-- bitmask of w bytes
-- we need to read and unpack it as a string, not an unsigned, because otherwise
-- we're limited to 52 bits
function unpack.m(fd, w)
local buf = unpack.s(fd, w)
local mask = {}
local sof,eof,dir = directions(w)
-- reverse it here because directions() returns numbers for MSB first,
-- and we want LSB first
for i=eof,sof,-dir do
local byte = buf:byte(i)
local bits = struct.explode(byte)
for j=1,8 do
mask[#mask+1] = bits[j] or false
end
end
return mask
end
-- fixed point bit aligned
-- w is in the form d.f, where d is the number of bits in the integer part
-- and f the number of bits in the fractional part
function unpack.P(fd, dp, fp)
if (dp+fp) % 8 ~= 0 then
error "total width of fixed point value must be byte multiple"
end
return unpack.i(fd, (dp+fp)/8)/(2^fp)
end
-- fixed point byte aligned
function unpack.p(fd, dp, fp)
return unpack.P(fd, dp*8, fp*8)
end
-- string
-- reads exactly w bytes of data and returns them verbatim
function unpack.s(fd, w)
if w == 0 then return "" end
local buf,err = fd:read(w or "*a")
if not buf then
error(function() return "read error: "..(err or "(unknown error)") end)
elseif #buf < w then
error(function() return "short read: wanted "..w.." bytes, got "..#buf end)
end
return buf
end
-- unsigned int
function unpack.u(fd, w)
local buf,err = unpack.s(fd, w)
return pve_unpack(buf, w)
end
-- skip/pad
-- reads w bytes and discards them
function unpack.x(fd, w)
fd:read(w)
return true
end
-- null-terminated string
-- if w is omitted, reads up to and including the first nul, and returns everything
-- except that nul
-- otherwise, reads exactly w bytes and returns everything up to the first nul
function unpack.z(fd, w)
if w then
return unpack.s(fd, w):match('^%Z*')
end
local buf = ""
local c = unpack.s(fd, 1)
while #c > 0 and c ~= string.char(0) do
buf = buf..c
c = unpack.s(fd, 1)
end
return buf
end
return unpack

Some files were not shown because too many files have changed in this diff Show More