From 753f60c7d4769fa72d3b910e491f37db6f130898 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 2 Aug 2013 17:19:21 -0500 Subject: dymaxion --- .../demo/360-player/360 button.psd | Bin 0 -> 38695 bytes .../demo/360-player/360-button-pause-light.gif | Bin 0 -> 333 bytes .../demo/360-player/360-button-pause-light.png | Bin 0 -> 445 bytes .../demo/360-player/360-button-pause.gif | Bin 0 -> 333 bytes .../demo/360-player/360-button-pause.png | Bin 0 -> 440 bytes .../demo/360-player/360-button-play-light.gif | Bin 0 -> 442 bytes .../demo/360-player/360-button-play-light.png | Bin 0 -> 501 bytes .../demo/360-player/360-button-play.gif | Bin 0 -> 442 bytes .../demo/360-player/360-button-play.png | Bin 0 -> 487 bytes .../demo/360-player/360player-visualization.css | 88 ++ .../demo/360-player/360player.css | 258 ++++ .../360-player/canvas-visualization-basic.html | 125 ++ .../demo/360-player/canvas-visualization.html | 328 +++++ .../demo/360-player/demo-slider-controls.css | 179 +++ .../demo/360-player/demo-slider-controls.js | 711 +++++++++++ .../demo/360-player/demo.css | 75 ++ .../demo/360-player/empty.gif | Bin 0 -> 43 bytes .../demo/360-player/icon_loading_dots.gif | Bin 0 -> 1456 bytes .../demo/360-player/icon_loading_spinner.gif | Bin 0 -> 530 bytes .../360-player/icon_loading_spinner_bigger.gif | Bin 0 -> 2545 bytes .../demo/360-player/index.html | 166 +++ .../demo/360-player/script/360player.js | 1270 ++++++++++++++++++++ .../demo/360-player/script/berniecode-animator.js | 674 +++++++++++ .../demo/360-player/script/excanvas.js | 17 + 24 files changed, 3891 insertions(+) create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360 button.psd create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause-light.gif create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause-light.png create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause.gif create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause.png create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play-light.gif create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play-light.png create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play.gif create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play.png create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360player-visualization.css create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360player.css create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/canvas-visualization-basic.html create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/canvas-visualization.html create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/demo-slider-controls.css create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/demo-slider-controls.js create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/demo.css create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/empty.gif create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/icon_loading_dots.gif create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/icon_loading_spinner.gif create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/icon_loading_spinner_bigger.gif create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/index.html create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/script/360player.js create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/script/berniecode-animator.js create mode 100755 docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/script/excanvas.js (limited to 'docs/dymaxion/soundmanagerv297a-20101010/demo/360-player') diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360 button.psd b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360 button.psd new file mode 100755 index 0000000..afd0498 Binary files /dev/null and b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360 button.psd differ diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause-light.gif b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause-light.gif new file mode 100755 index 0000000..cf9eab3 Binary files /dev/null and b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause-light.gif differ diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause-light.png b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause-light.png new file mode 100755 index 0000000..8f66539 Binary files /dev/null and b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause-light.png differ diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause.gif b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause.gif new file mode 100755 index 0000000..6e589ea Binary files /dev/null and b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause.gif differ diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause.png b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause.png new file mode 100755 index 0000000..dc84def Binary files /dev/null and b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-pause.png differ diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play-light.gif b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play-light.gif new file mode 100755 index 0000000..eb36483 Binary files /dev/null and b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play-light.gif differ diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play-light.png b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play-light.png new file mode 100755 index 0000000..a2f6557 Binary files /dev/null and b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play-light.png differ diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play.gif b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play.gif new file mode 100755 index 0000000..b97cd7f Binary files /dev/null and b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play.gif differ diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play.png b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play.png new file mode 100755 index 0000000..ce2d9a3 Binary files /dev/null and b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360-button-play.png differ diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360player-visualization.css b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360player-visualization.css new file mode 100755 index 0000000..96cc582 --- /dev/null +++ b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360player-visualization.css @@ -0,0 +1,88 @@ +/* larger canvas, spectrum + EQ visualization and other items */ + +.ui360, +.sm2-360ui { + /* size of the container for the circle, etc. */ + width:256px; + height:256px; +} + +.ui360 { + position:relative; + /* a little extra spacing */ + padding-top:1px; + padding-bottom:1px; + margin-bottom:-18px; /* approximate "line height" we want */ + padding-left:248px; + margin-left:0px; + background-position:22.6% 50%; /* (~109px) initial play button position */ +} + +.ui360 a { + font:14px "helvetica neue",helvetica,monaco,lucida,terminal,monospace; + white-space:nowrap; + line-height:256px; +} + +.sm2-360ui { + margin-left:-256px; +} + +.ui360 .sm2-timing { + line-height:256px; +} + +.ui360 .sm2-timing { + font:bold 24px "helvetica neue",helvetica,monaco,lucida,terminal,monospace; + color:#333; + text-align:center; + line-height:256px; + text-indent:0px; +} + +.sm2-inline-list .ui360, +.sm2-inline-list .sm2-360ui { + margin-left:0px; +} + +.sm2-inline-list .ui360 { + margin:8px 13px 7px 0px; + padding-left:0px; + background-position:50% 50%; /* initial play button position */ +} + +.sm2-inline-list .sm2-360ui { + border:1px solid #eee; +} + +.sm2-inline-list .ui360 a { + position:absolute; + left:0px; + bottom:0px; + margin-left:1px; + width:100%; /* 2px padding in box */ + height:auto; + font-size:x-small; + padding:2px 0px; + color:#999; + line-height:15px; + text-align:center; + display:inline; + -moz-border-radius:0px; + -khtml-border-radius:0px; + border-radius:0px; +} + +.sm2-inline-list .ui360 a:focus, +.sm2-inline-list .ui360 a:active { + background-color:transparent; +} + +/* Use a bigger loading image for this layout */ + +.ui360 .sm2-360ui.sm2_buffering .sm2-360btn, +.ui360 .sm2-360ui.sm2_buffering .sm2-360btn:hover { + background:transparent url(icon_loading_spinner_bigger.gif) no-repeat 50% 50%; + opacity:0.5; + visibility:visible; +} \ No newline at end of file diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360player.css b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360player.css new file mode 100755 index 0000000..a961dc5 --- /dev/null +++ b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/360player.css @@ -0,0 +1,258 @@ +/* General warning: Beta-ish. Code could be a bit cleaner. */ + +.ui360, +.ui360 * { + position:relative; +} + +.ui360, +.sm2-360ui { + /* size of the container for the circle, etc. */ + width:50px; + height:50px; +} + +.ui360 { + position:relative; + /* a little extra spacing */ + padding-top:1px; + padding-bottom:1px; + margin-bottom:-18px; /* approximate "line height" we want */ + padding-left:42px; /* 50px, with a few off - margin used for visualization UI */ +} + +.ui360 a { + line-height:50px; +} + +.sm2-360ui { + margin-left:-50px; +} + +.ui360 { + width:auto; +} + +.ui360, +.ui360 * { + vertical-align:middle; +} + +.sm2-360ui { + position:relative; + display:inline-block; /* firefox 3 et al */ + float:left; /* firefox 2 needs this, inline-block would work with fx3 and others */ + *float:left; /* IE 6+7 */ + *display:inline; + *clear:left; +} + +.sm2-360ui.sm2_playing, +.sm2-360ui.sm2_paused { + /* bump on top when active */ + z-index:10; +} + +.ui360 a.sm2_link { /* this class added to playable links by SM2 */ + position:relative; +} + +.ui360 a { + color:#000; + text-decoration:none; +} + +.ui360 a, +.ui360 a:hover, +.ui360 a:focus { + padding:2px; + margin-left:-2px; + margin-top:-2px; +} + +.ui360 a:hover, +.ui360 a:focus { + background:#eee; + -moz-border-radius:3px; + -webkit-border-radius:3px; + -khtml-border-radius:3px; + border-radius:3px; + outline:none; +} + +.ui360 .sm2-canvas { + position:absolute; + left:0px; + top:0px; +} + +.ui360 .sm2-timing { + position:absolute; + display:block; + left:0px; + top:0px; + width:100%; + height:100%; + margin:0px; + font:11px "helvetica neue",helvetica,monaco,lucida,terminal,monospace; + color:#666; + text-align:center; + line-height:50px; +} + +.ui360 .sm2-timing.alignTweak { + text-indent:1px; /* devious center-alignment tweak for Safari (might break things for others.) */ +} + +.ui360 .sm2-cover { + position:absolute; + left:0px; + top:0px; + z-index:2; + display:none; +} + +.ui360 .sm2-360btn { + position:absolute; + top:50%; + left:50%; + width:22px; + height:22px; + margin-left:-11px; + margin-top:-11px; + cursor:pointer; + z-index:3; +} + +.ui360 .sm2-360btn-default { +} + +.ui360 .sm2-360data { + display:inline-block; + font-family:helvetica; +} + +.ui360 .sm2-360ui.sm2_playing .sm2-cover, +.ui360 .sm2-360ui.sm2_paused .sm2-cover { + display:block; +} + +/* this could be optimized a fair bit. */ + +.ui360, +.ui360 .sm2-360btn-default { + background:transparent url(360-button-play.png) no-repeat 50% 50%; + _background:transparent url(360-button-play.gif) no-repeat 50% 50%; /* IE 6-only: special crap GIF */ + cursor:pointer; +} + +.ui360 { + /* + "fake" button shown before SM2 has started, non-JS/non-SM2 case etc. + background image will be removed via JS, in threeSixyPlayer.init() + */ + background-position:6px 50%; +} + +.ui360 .sm2-360ui.sm2_paused .sm2-360btn { + background:transparent url(360-button-play.png) no-repeat 50% 50%; + _background:transparent url(360-button-play.gif) no-repeat 50% 50%; + cursor:pointer; +} + +.ui360 .sm2-360btn-default:hover, +.ui360 .sm2-360ui.sm2_paused .sm2-360btn:hover { + background:transparent url(360-button-play-light.png) no-repeat 50% 50%; + _background:transparent url(360-button-play.gif) no-repeat 50% 50%; + cursor:pointer; +} + +.ui360 .sm2-360ui.sm2_playing .sm2-360btn:hover, +.ui360 .sm2-360btn-playing:hover { + background:transparent url(360-button-pause-light.png) no-repeat 50% 50%; + _background:transparent url(360-button-pause-light.gif) no-repeat 50% 50%; + cursor:pointer; +} + + +.ui360 .sm2-360ui.sm2_playing .sm2-timing { + visibility:visible; +} + +.ui360 .sm2-360ui.sm2_buffering .sm2-timing { + visibility:hidden; +} + +.ui360 .sm2-360ui .sm2-timing, +.ui360 .sm2-360ui .sm2-360btn:hover + .sm2-timing, +.ui360 .sm2-360ui.sm2_paused .sm2-timing { + visibility:hidden; +} + +.ui360 .sm2-360ui.sm2_dragging .sm2-timing, +.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover + .sm2-timing { + /* paused + dragging */ + visibility:visible; +} + +.ui360 .sm2-360ui.sm2_playing .sm2-360btn, +x.ui360 .sm2-360btn-playing, +.ui360 .sm2-360ui.sm2_dragging .sm2-360btn, +.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover, +.ui360 .sm2-360ui.sm2_dragging .sm2-360btn-playing:hover { + /* don't let pause button show on hover when dragging (or paused and dragging) */ + background:transparent; + cursor:auto; +} + +.ui360 .sm2-360ui.sm2_buffering .sm2-360btn, +.ui360 .sm2-360ui.sm2_buffering .sm2-360btn:hover { + background:transparent url(icon_loading_spinner.gif) no-repeat 50% 50%; + opacity:0.5; + visibility:visible; +} + +/* inline list style */ + +.sm2-inline-list .ui360, +.sm2-inline-block .ui360 { + position:relative; + display:inline-block; + float:left; + _display:inline; + margin-bottom:-15px; +} + +.sm2-inline-list .ui360 { + margin-bottom:0px; +} + +.sm2-inline-block .ui360 { + margin-right:8px; +} + +.sm2-inline-list .ui360 a { + display:none; +} + +/* annotations */ + +ul.ui360playlist { + list-style-type:none; +} + +ul.ui360playlist, +ul.ui360playlist li { + margin:0px; + padding:0px; +} + +div.ui360 div.metadata { + display:none; +} + +div.ui360 a span.metadata, +div.ui360 a span.metadata * { + /* name of track, note etc. */ + vertical-align:baseline; +} \ No newline at end of file diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/canvas-visualization-basic.html b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/canvas-visualization-basic.html new file mode 100755 index 0000000..789846b --- /dev/null +++ b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/canvas-visualization-basic.html @@ -0,0 +1,125 @@ + + + +360° MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization, basic example + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

360° Player Demo - Visualization Example, Basic Template

+ +

Canvas-based UI with visualization options. Note: No EQ/spectrum support for IE (too slow.) Data not available in HTML5.

+ +
+ +
+ +
+ + + +

Inline list

+ +
+ + + + + + +
+ +

Block list

+ +
+ + +
+ +
+ +

+ SoundManager 2 project page (not an MP3 link) +

+ + + + + diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/canvas-visualization.html b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/canvas-visualization.html new file mode 100755 index 0000000..cb8071f --- /dev/null +++ b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/canvas-visualization.html @@ -0,0 +1,328 @@ + + + +360° MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

SoundManager 2 / 360° Player Demo: JS + Canvas Visualization

+ +

Canvas-based UI with visualization options. Note: Spectrum/EQ visualizations disabled for IE (too slow.) Data is not currently available under HTML5.

+

You can also show FPS or customize the UI, or see the hi-fi version. Check the basic template for a minimal code example; also see the default 360° UI.

+ + + + + + + +
+ +
+ +

Inline list

+ + + +

"I Tried" and "People Asking" courtesy of SonReal, from the "Lightyear" Mixtape.

+ +

Block list

+ +
+ + +
+ + +
+ +

Variant: Annotations/meta-data

+ + + + +
+ +

+ SoundManager 2 project page (not an MP3 link) +

+ + + +
+ + + diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/demo-slider-controls.css b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/demo-slider-controls.css new file mode 100755 index 0000000..27281c0 --- /dev/null +++ b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/demo-slider-controls.css @@ -0,0 +1,179 @@ +#cp-container { position:relative;float:left;display:inline; margin-left:1em;padding: 6px; background-color: #f6f6f6; border:1px solid #eee; width: 320px; height:180px;z-index:2; } + +.yui-picker-controls li, +.yui-picker-controls input { + font-size:1em; + font-family:"helvetica neue",helvetica,arial,verdana; +} + +#controls { + position:relative; + margin-top:1.5em; + font-size:0.85em; +} + +#options { + float:left; + display:inline; + margin-bottom:0.5em; + margin-top:-1.2em; +} + +#controls .checkbox { + float:left; + display:inline; + width:21.2em; + margin-right:2.5em; +} + +#controls .checkbox div { + /* tab */ + width:auto; + padding:0.4em; + border:1px solid #ddd; + border-bottom:none; + background:#eee; +} + +#controls .checkbox div, +#controls .checkbox input { + font-family:arial,tahoma,verdana,"sans serif"; + font-size:1em; + vertical-align:middle; +} + +#controls dl { + width:21em; +} + +#controls dl.col { + position:relative; + float:left; + display:inline; + margin:0px; + margin-right:1em; + padding:0.75em; +/* + height:12.4em; +*/ + height:auto; + border:1px solid #ddd; + background:#f6f6f6; +} + +#controls .disabled { + color:#ccc; +} + +#controls .disabled dt, +#controls .disabled dd { + color:#999; + opacity:0.5; +} + +#controls dl dd p { + margin:0px; + padding:0px; +} + +#controls dt, +#controls dd { + margin:0px; + padding:0px; +} + +#controls dt { + border-bottom:none; +} + +#controls dt { + float:left; + display:inline; + background:transparent; + padding-right:0.7em; + margin-right:0.7em; + border-right:1px solid #ccc; + font-size:1.1em; + color:#333; + font-family:"helvetica neue",helvetica,verdana,arial,"sans serif"; +} + +#controls dd { + margin:0px; + padding:0px; + font-size:0.9em; + vertical-align:middle; + color:#666; +} + +#controls .title { + float:left; + display:inline; + margin-right:0.6em; + color:#333; +} + +/* those slider bits you might be wondering about */ + +#controls .control { + position:relative; + border-left:0px; + width:214px; + height:20px; +} + +#controls .control .bar { + position:absolute; + left:0px; + top:0px; + width:214px; + height:20px; + background:transparent url(../_image/slider-bar.gif) no-repeat 0px 9px; + cursor:pointer; + cursor:hand; +} + +#controls .control .slider { + position:absolute; + left:0px; + top:0px; + width:20px; + height:20px; + background:transparent url(../_image/slider.png) no-repeat 0px 0px; + *background:none; + filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider.png'); + cursor:pointer; + cursor:hand; +} + +#controls .control .slider:hover { + background:transparent url(../_image/slider-1.png) no-repeat 0px 0px; + *background:none; +} + +#controls .control .slider.hover { + filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-1.png'); +} + +#controls .disabled .control .slider { + background:transparent url(../_image/slider-disabled.png) no-repeat 0px 0px; + *background:none; + filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-disabled.png'); +} + +#controls .disabled .control .slider:hover { + background:transparent url(../_image/slider-disabled-1.png) no-repeat 0px 0px; + *background:none; +} + +#controls .disabled .control .slider.hover { + filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-disabled-1.png'); +} + +#controls input[type=text] { + width:5em; +} + +#options div { + margin-bottom:0.25em; +} \ No newline at end of file diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/demo-slider-controls.js b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/demo-slider-controls.js new file mode 100755 index 0000000..16a02dc --- /dev/null +++ b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/demo-slider-controls.js @@ -0,0 +1,711 @@ +/* + Ancient fireworks slider control code (2005) + http://schillmania.com/projects/fireworks/ + -------------------------------------------- + Not required for your use! +*/ + +function Animator2() { + var self = this; + this.tweens = []; + this.tweens['default'] = [1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1]; + this.tweens['blast'] = [12,12,11,10,10,9,8,7,6,5,4,3,2,1]; + this.tweens['fade'] = [10,10,10,10,10,10,10,10,10,10]; + this.queue = []; + this.queue.IDs = []; + this.active = false; + this.timer = null; + + this.createTween = function(start,end,type) { + // return array of tween coordinate data (start->end) + type = type||'default'; + var tween = [start]; + var tmp = start; + var diff = end-start; + var x = self.tweens[type].length; + for (var i=0; i= 0.4 && pos <= 0.6) { + pos = 0.5; + } + pos = parseInt(pos*100); + // writeDebug('getPanX('+x+'): '+pos+'%'); + return pos; + } + + this.isEmpty = function(o) { + // needs further hacking + return (typeof(o)=='undefined'||(o==null&&o!=0)||(o==''&&o!=0)||o=='null'); + } + + this.init = function() { +// self.oFW = document.getElementById('fw'); +// self.oFP = document.getElementById('fp'); +// if (typeof(enableDebugMode)!='undefined' && (self.DEBUG||window.location.toString().toLowerCase().indexOf('debug')>=0)) enableDebugMode(); + self.getWindowCoords(); + self.animator = new Animator2(); + } + + this.destructor = function() { +/* + for (var i=self.fireworks.length; i--;) { + self.fireworks[i] = null; + } + self.fireworks = null; + if (soundManager) { + soundManager.destructor(); + soundManager = null; + } +*/ + } + + if (this.isSafari || this.isOpera) this.getWindowCoords = this.getWindowCoordsAlt; + +} + + +function Controller(o) { + var self = this; + this.o = o; + this.controls = []; + this.cb = []; + this.options = []; + this.functionExample = document.getElementById('function-example'); + this.fbIE = null; + + this.randomize = function() { + for (var i=1; i,\n\ + playRingColor: '"+threeSixtyPlayer.config.playRingColor+"',\n\ + backgroundRingColor: '"+threeSixtyPlayer.config.backgroundRingColor+"',\n\ + circleDiameter: "+threeSixtyPlayer.config.circleDiameter+",\n\ + circleRadius: "+threeSixtyPlayer.config.circleRadius+",\n\ + imageRoot: '"+threeSixtyPlayer.config.imageRoot+"',\n\ + animDuration: "+threeSixtyPlayer.config.animDuration+",\n\ + animTransition: Animator.tx.bouncy,\n\ + showHMSTime: "+threeSixtyPlayer.config.showHMSTime+",\n\ +\n\ + useWaveformData: "+threeSixtyPlayer.config.useWaveformData+",\n\ + waveformDataColor: '"+threeSixtyPlayer.config.waveformDataColor+"',\n\ + waveformDataDownsample: "+threeSixtyPlayer.config.waveformDataDownsample+",\n\ + waveformDataOutside: "+threeSixtyPlayer.config.waveformDataOutside+",\n\ + waveformDataConstrain: false,\n\ + waveformDataLineRatio: "+threeSixtyPlayer.config.waveformDataLineRatio+",\n\ +\n\ + useEQData: "+threeSixtyPlayer.config.useEQData+",\n\ + eqDataColor: '"+threeSixtyPlayer.config.eqDataColor+"',\n\ + eqDataDownsample: "+threeSixtyPlayer.config.eqDataDownsample+",\n\ + eqDataOutside: "+threeSixtyPlayer.config.eqDataOutside+",\n\ + eqDataLineRatio: "+threeSixtyPlayer.config.eqDataLineRatio+",\n\ +\n\ + usePeakData: "+threeSixtyPlayer.config.usePeakData+",\n\ + peakDataColor: '"+threeSixtyPlayer.config.peakDataColor+"',\n\ + peakDataOutside: "+threeSixtyPlayer.config.peakDataOutside+",\n\ + peakDataLineRatio: "+threeSixtyPlayer.config.peakDataLineRatio+",\n\ +\n\ + useAmplifier: "+threeSixtyPlayer.config.useAmplifier+"\n\ +\n\ +}"; +document.getElementById('config-code').style.display = 'block'; // weird Fx fix + } + + this.createCustomFirework = function() { + } + + this.destructor = function() { + for (var i=self.controls.length; i--;) { + self.controls[i].destructor(); + } + for (i=self.cb.length; i--;) { + self.cb.onclick = null; + self.cb[i] = null; + } + for (i=self.options.length; i--;) { + self.options[i] = null; + } + if (navigator.userAgent.match(/msie/i)) { + self.fbIE.onmouseover = null; + self.fbIE.onmouseout = null; + self.fbIE = null; + } + self.cb = null; + self.options = null; + self.controls = null; + self.functionExample = null; + self.o = null; + } + + var items = parseInt(this.o.length/3); + for (var i=0; iself.xMax) { + x = self.xMax; + } else if (x=self.tween.length-1) { + self.active = false; + self.frame = 0; + if (self._oncomplete) self._oncomplete(); +// self.doUpdate(); + return false; + } + self.doUpdate(); + return true; + } + + this.doUpdate = function(t) { + // if (!self.timer) self.timer = setTimeout(self.update,t||20); + self.update(); + } + + this.update = function() { + self.timer = null; + self.value = 1+parseInt(self.x/self.xMax*(self.scale-1)); + if (self.value<1) self.value = 1; + // if (self.oV.innerHTML != self.value) self.oV.innerHTML = self.value; + // self.oV.innerHTML = self.value; + } + + this.setValue = function(x) { + self.slide(self.x,Math.min(self.xMax,x)); + } + + this.randomize = function() { + self.slide(self.x,parseInt(Math.random()*self.xMax)); + } + + this.destructor = function() { + self.o.onmouseover = null; + self.o.onmouseout = null; + self.o.onmousedown = null; + self.o = null; + self.oV = null; + self.oB.onclick = null; + self.oB = null; + } + + if (soundManager.isIE) { + // IE is lame, no :hover + this.o.onmouseover = this.over; + this.o.onmouseout = this.out; + } + + this.o.onmousedown = this.down; + this.oB.onclick = this.barClick; + self.update(); + +} + +var gOID = 0; + +function demoInit() { + controller = new Controller(document.getElementById('controls').getElementsByTagName('dd')); +} + +function demoDestuctor() { + controller.destructor(); + controller = null; +} + +var controller = null; + +var mc = new MainController(); +// create null objects if APIs not present + +function createCP(oInput,oHandler) { + var Event = YAHOO.util.Event; + + cpHandler = oHandler; + if (picker != null) { + // picker.showcontrols(true); + var c = oInput.value.substr(1); + picker.setValue(hex2decArray([c.substr(0,2),c.substr(2,2),c.substr(4,2)]),true); // be silent + return false; + } + + Event.onDOMReady(function() { + picker = new YAHOO.widget.ColorPicker("cp-container", { + showhsvcontrols: true, + showhexcontrols: true, + images: { + PICKER_THUMB: "../_image/picker_thumb.png", + HUE_THUMB: "../_image/hue_thumb.png" + } + }); + +// picker.showcontrols(false); + //a listener for logging RGB color changes; + //this will only be visible if logger is enabled: + var onRgbChange = function(o) { + /*o is an object + { newValue: (array of R, G, B values), + prevValue: (array of R, G, B values), + type: "rgbChange" + } + */ + cpHandler(o.newValue); + controller.updateExampleCode(); + } + + //subscribe to the rgbChange event; + picker.on("rgbChange", onRgbChange); + + //use setValue to reset the value to white: + Event.on("reset", "click", function(e) { + picker.setValue([255, 255, 255], false); //false here means that rgbChange + //wil fire; true would silence it + }); + + //use the "get" method to get the current value + //of one of the Color Picker's properties; in + //this case, we'll get the hex value and write it + //to the log: + Event.on("gethex", "click", function(e) { + console.log("Current hex value: " + picker.get("hex")); + }); + + }); +} + +var picker = null; + +cpHandler = function() { +} + + + // hex -> dec / dec -> hex + // http://www.southwest.com.au/~jfuller/binary/converter.htm + + function dec2hex(cval) { + if (cval > 255) cval = 255; + var hexascii = "0123456789ABCDEF"; + var cval0 = Math.floor(cval/16); + var cval1 = cval-(cval0*16); + var c1 = hexascii.charAt(cval0); + var c2 = hexascii.charAt(cval1); + return (c1+c2); + } + + function hex2dec(cval) { + cval = cval.toUpperCase(); + var tval = 0; + var hexascii = "0123456789ABCDEF"; + var mychar, ch; + for (var c=0; c + + +360° MP3 player UI demo (SoundManager 2) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

SoundManager 2 / 360° Player: JS + Canvas UI

+ +

Canvas-based UI. Load progress, seek, play/pause etc. Also see 360° UI visualization demo.

+ +
+ +
+ +
+ + + + +
+ +

Alternate style: inline

+ + + +
+ +
+ +
+ + +

How This Works

+ +

The script looks for a container element matching div.ui360, and then the first link inside of it.

+ +
+ +
<div class="ui360">
+ <a href="/path/to/an.mp3">
+</div>
+ +
+ +

When the link is clicked, the script adds a UI template to the block, prepending it in front of the MP3 link:

+ +
<div class="ui360">
+ <-- dynamically-inserted block -->
+ <div class="ui">
+  <canvas class="sm2-canvas"></canvas>
+  <img class="sm2-360btn" /> 
+  <div class="sm2-timing"></div>
+  <div class="sm2-cover"></div>
+ </div>
+ <-- /UI -->
+ <a href="/path/to/an.mp3">
+</div>
+ +

Customizing the UI

+ +

The player's default 50x50-pixel canvas is defined both within JavaScript and CSS. For an example with different values, see this larger version.

+ +
threeSixtyPlayer.config = {
+  playNext: false, // stop after one sound, or play through list until end
+  autoPlay: false, // start playing the first sound right away
+  loadRingColor: '#ccc', // amount of sound which has loaded
+  playRingColor: '#000', // amount of sound which has played
+  backgroundRingColor: '#eee', // "default" color shown underneath everything else
+  imageRoot: '', // path to prepend for empty.gif used for play/pause button
+  animDuration: 500,
+  animTransition: Animator.tx.bouncy // http://www.berniecode.com/writing/animator.html
+}
+ +

The CSS for the canvas UI block is a bit ugly, but JavaScript reads the width of the .sm2-360ui element in the DOM as set by CSS and uses that to later draw and update the canvas element while playing.

+ +
.ui360,
+.sm2-360ui {
+  /* size of the container for the circle, etc. */
+  width:50px;
+  height:50px;
+}
+
+ +

Third-party Components

+ +

This demo includes use of Bernie's Better Animation Class (Apache licensed) for some animation effects.

+

Also, some loader/spinner icons from ajaxload.info are used for showing loading/buffering states.

+ +
+ +

+ SoundManager 2 project page (not an MP3 link) +

+ + +
+ + + diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/script/360player.js b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/script/360player.js new file mode 100755 index 0000000..419559c --- /dev/null +++ b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/script/360player.js @@ -0,0 +1,1270 @@ +/* + + SoundManager 2 Demo: 360-degree / "donut player" + ------------------------------------------------ + http://schillmania.com/projects/soundmanager2/ + + An inline player with a circular UI. + Based on the original SM2 inline player. + Inspired by Apple's preview feature in the + iTunes music store (iPhone), among others. + + Requires SoundManager 2 Javascript API. + Also uses Bernie's Better Animation Class (BSD): + http://www.berniecode.com/writing/animator.html + +*/ + +function ThreeSixtyPlayer() { + var self = this; + var pl = this; + var sm = soundManager; // soundManager instance + var uA = navigator.userAgent; + var isIE = (uA.match(/msie/i)); + var isOpera = (uA.match(/opera/i)); + var isSafari = (uA.match(/safari/i)); + var isChrome = (uA.match(/chrome/i)); + var isFirefox = (uA.match(/firefox/i)); + var isTouchDevice = (uA.match(/ipad|iphone/i)); + this.excludeClass = 'threesixty-exclude'; // CSS class for ignoring MP3 links + + this.links = []; + this.sounds = []; + this.soundsByURL = []; + this.indexByURL = []; + this.lastSound = null; + this.soundCount = 0; + this.oUITemplate = null; + this.oUIImageMap = null; + this.vuMeter = null; + + this.config = { + + playNext: false, // stop after one sound, or play through list until end + autoPlay: false, // start playing the first sound right away + loadRingColor: '#ccc', // how much has loaded + playRingColor: '#000', // how much has played + backgroundRingColor: '#eee', // color shown underneath load + play ("not yet loaded" color) + + // optional segment/annotation (metadata) stuff.. + segmentRingColor: 'rgba(255,255,255,0.33)', // metadata/annotation (segment) colors + segmentRingColorAlt: 'rgba(0,0,0,0.1)', + loadRingColorMetadata: '#ddd', // "annotations" load color + playRingColorMetadata: 'rgba(96,160,224,0.99)', // how much has played when metadata is present + playRingColorMetadata: 'rgba(128,192,256,0.9)', // how much has played when metadata is present + + circleDiameter: null, // set dynamically according to values from CSS + circleRadius: null, + imageRoot: '', // image path to prepend for transparent .GIF - eg. /images/ + animDuration: 500, + animTransition: Animator.tx.bouncy, // http://www.berniecode.com/writing/animator.html + showHMSTime: false, // hours:minutes:seconds vs. seconds-only + scaleFont: false, // also set the font size (if possible) while animating the circle + + // optional: spectrum or EQ graph in canvas (not supported in IE, too slow via ExCanvas) + useWaveformData: false, + waveformDataColor: '#0099ff', + waveformDataDownsample: 3, // use only one in X (of a set of 256 values) - 1 means all 256 + waveformDataOutside: false, + waveformDataConstrain: false, // if true, +ve values only - keep within inside circle + waveformDataLineRatio: 0.64, + + // "spectrum frequency" option + useEQData: false, + eqDataColor: '#339933', + eqDataDownsample: 4, // use only one in X (of 256 values) + eqDataOutside: true, + eqDataLineRatio: 0.54, + + // enable "amplifier" (canvas pulses like a speaker) effect + usePeakData: true, + peakDataColor: '#ff33ff', + peakDataOutside: true, + peakDataLineRatio: 0.5, + + useAmplifier: true, // "pulse" like a speaker + + fontSizeMax: null, // set according to CSS + + useFavIcon: false // Experimental (also requires usePeakData: true).. Try to draw a "VU Meter" in the favicon area, if browser supports it (Firefox + Opera as of 2009) + + } + + this.css = { + // CSS class names appended to link during various states + sDefault: 'sm2_link', // default state + sBuffering: 'sm2_buffering', + sPlaying: 'sm2_playing', + sPaused: 'sm2_paused' + } + + this.addEventHandler = function(o,evtName,evtHandler) { + typeof(attachEvent)=='undefined'?o.addEventListener(evtName,evtHandler,false):o.attachEvent('on'+evtName,evtHandler); + } + + this.removeEventHandler = function(o,evtName,evtHandler) { + typeof(attachEvent)=='undefined'?o.removeEventListener(evtName,evtHandler,false):o.detachEvent('on'+evtName,evtHandler); + } + + this.hasClass = function(o,cStr) { + return (typeof(o.className)!='undefined'?o.className.match(new RegExp('(\\s|^)'+cStr+'(\\s|$)')):false); + } + + this.addClass = function(o,cStr) { + if (!o || !cStr || self.hasClass(o,cStr)) return false; + o.className = (o.className?o.className+' ':'')+cStr; + } + + this.removeClass = function(o,cStr) { + if (!o || !cStr || !self.hasClass(o,cStr)) return false; + o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),''); + } + + this.getElementsByClassName = function(className,tagNames,oParent) { + var doc = (oParent||document); + var matches = []; + var i,j; + var nodes = []; + if (typeof tagNames != 'undefined' && typeof tagNames != 'string') { + for (i=tagNames.length; i--;) { + if (!nodes || !nodes[tagNames[i]]) { + nodes[tagNames[i]] = doc.getElementsByTagName(tagNames[i]); + } + } + } else if (tagNames) { + nodes = doc.getElementsByTagName(tagNames); + } else { + nodes = doc.all||doc.getElementsByTagName('*'); + } + if (typeof(tagNames)!='string') { + for (i=tagNames.length; i--;) { + for (j=nodes[tagNames[i]].length; j--;) { + if (self.hasClass(nodes[tagNames[i]][j],className)) { + matches.push(nodes[tagNames[i]][j]); + } + } + } + } else { + for (i=0; i 1) { + // only catch left-clicks + return true; + } + var o = self.getTheDamnLink(e); + if (o.nodeName.toLowerCase() != 'a') { + o = self.isChildOfNode(o,'a'); + if (!o) return true; + } + if (!self.isChildOfClass(o,'ui360')) { + // not a link we're interested in + return true; + } + var sURL = o.getAttribute('href'); + if (!o.href || !sm.canPlayLink(o) || self.hasClass(o,self.excludeClass)) { + return true; // pass-thru for non-MP3/non-links + } + sm._writeDebug('handleClick()'); + var soundURL = (o.href); + var thisSound = self.getSoundByURL(soundURL); + if (thisSound) { + // already exists + if (thisSound == self.lastSound) { + // and was playing (or paused) + thisSound.togglePause(); + } else { + // different sound + thisSound.togglePause(); // start playing current + sm._writeDebug('sound different than last sound: '+self.lastSound.sID); + if (self.lastSound) { + self.stopSound(self.lastSound); + } + } + } else { + // append some dom shiz + + // create sound + thisSound = sm.createSound({ + id:'ui360Sound'+(self.soundCount++), + url:soundURL, + onplay:self.events.play, + onstop:self.events.stop, + onpause:self.events.pause, + onresume:self.events.resume, + onfinish:self.events.finish, + onbufferchange:self.events.bufferchange, + whileloading:self.events.whileloading, + whileplaying:self.events.whileplaying + }); + var oContainer = o.parentNode; + // tack on some custom data + + thisSound._360data = { + oUI360: self.getParentByClassName(o,'ui360'), // the (whole) entire container + oLink: o, // DOM node for reference within SM2 object event handlers + className: self.css.sPlaying, + oUIBox: self.getElementsByClassName('sm2-360ui','div',oContainer)[0], + oCanvas: self.getElementsByClassName('sm2-canvas','canvas',oContainer)[0], + oButton: self.getElementsByClassName('sm2-360btn','img',oContainer)[0], + oTiming: self.getElementsByClassName('sm2-timing','div',oContainer)[0], + oCover: self.getElementsByClassName('sm2-cover','div',oContainer)[0], + lastTime: null, + didFinish: null, + pauseCount:0, + radius:0, + amplifier: (self.config.usePeakData?0.9:1), // TODO: x1 if not being used, else use dynamic "how much to amplify by" value + radiusMax: self.config.circleDiameter*0.175, // circle radius + width:0, + widthMax: self.config.circleDiameter*0.4, // width of the outer ring + lastValues: { + bytesLoaded: 0, + bytesTotal: 0, + position: 0, + durationEstimate: 0 + }, // used to track "last good known" values before sound finish/reset for anim + animating: false, + oAnim: new Animator({ + duration: self.config.animDuration, + transition:self.config.animTransition, + onComplete: function() { + // var thisSound = this; + // thisSound._360data.didFinish = false; // reset full circle + } + }), + oAnimProgress: function(nProgress) { + var thisSound = this; + thisSound._360data.radius = parseInt(thisSound._360data.radiusMax*thisSound._360data.amplifier*nProgress); + thisSound._360data.width = parseInt(thisSound._360data.widthMax*thisSound._360data.amplifier*nProgress); + if (self.config.scaleFont && self.config.fontSizeMax != null) { + thisSound._360data.oTiming.style.fontSize = parseInt(Math.max(1,self.config.fontSizeMax*nProgress))+'px'; + thisSound._360data.oTiming.style.opacity = nProgress; + } + if (thisSound.paused || thisSound.playState == 0 || thisSound._360data.lastValues.bytesLoaded == 0 || thisSound._360data.lastValues.position == 0) { + self.updatePlaying.apply(thisSound); + } + }, + fps: 0 + }; + + // "Metadata" (annotations) + if (typeof self.Metadata != 'undefined' && self.getElementsByClassName('metadata','div',thisSound._360data.oUI360).length) { + thisSound._360data.metadata = new self.Metadata(thisSound,self); + } + + // set the cover width/height to match the canvas + thisSound._360data.oCover.style.width = self.config.circleDiameter+'px'; + thisSound._360data.oCover.style.height = self.config.circleDiameter+'px'; + + // minimize ze font + if (self.config.scaleFont && self.config.fontSizeMax != null) { + thisSound._360data.oTiming.style.fontSize = '1px'; + } + + // set up ze animation + thisSound._360data.oAnim.addSubject(thisSound._360data.oAnimProgress,thisSound); + + // animate the radius out nice + self.refreshCoords(thisSound); + + self.updatePlaying.apply(thisSound); + + self.soundsByURL[soundURL] = thisSound; + self.sounds.push(thisSound); + if (self.lastSound) { + self.stopSound(self.lastSound); + } + thisSound.play(); + } + + self.lastSound = thisSound; // reference for next call + + if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') { + e.preventDefault(); + } else if (typeof event != 'undefined') { + event.returnValue = false; + } + return false; + } + + this.fanOut = function(oSound) { + var thisSound = oSound; + if (thisSound._360data.animating == 1) { + return false; + } + thisSound._360data.animating = 0; + soundManager._writeDebug('fanOut: '+thisSound.sID+': '+thisSound._360data.oLink.href); + thisSound._360data.oAnim.seekTo(1); // play to end + window.setTimeout(function() { + // oncomplete hack + thisSound._360data.animating = 0; + },self.config.animDuration+20); + } + + this.fanIn = function(oSound) { + var thisSound = oSound; + if (thisSound._360data.animating == -1) { + return false; + } + thisSound._360data.animating = -1; + soundManager._writeDebug('fanIn: '+thisSound.sID+': '+thisSound._360data.oLink.href); + // massive hack + thisSound._360data.oAnim.seekTo(0); // play to end + window.setTimeout(function() { + // reset full 360 fill after animation has completed (oncomplete hack) + thisSound._360data.didFinish = false; + thisSound._360data.animating = 0; + self.resetLastValues(thisSound); + },self.config.animDuration+20); + + } + + this.resetLastValues = function(oSound) { + var oData = oSound._360data; + oData.lastValues.position = 0; + // oData.lastValues.bytesLoaded = 0; // will likely be cached, if file is small + // oData.lastValues.bytesTotal = 0; + // oData.lastValues.durationEstimate = 0; + } + + this.refreshCoords = function(thisSound) { + thisSound._360data.canvasXY = self.findXY(thisSound._360data.oCanvas); + // thisSound._360data.canvasMid = [Math.floor(thisSound._360data.oCanvas.offsetWidth/2), Math.floor(thisSound._360data.oCanvas.offsetHeight/2)]; // doesn't work in IE, w/h are wrong + thisSound._360data.canvasMid = [self.config.circleRadius,self.config.circleRadius]; + thisSound._360data.canvasMidXY = [thisSound._360data.canvasXY[0]+thisSound._360data.canvasMid[0], thisSound._360data.canvasXY[1]+thisSound._360data.canvasMid[1]]; + } + + this.stopSound = function(oSound) { + soundManager._writeDebug('stopSound: '+oSound.sID); + soundManager.stop(oSound.sID); + soundManager.unload(oSound.sID); + } + + this.buttonClick = function(e) { + var o = e?(e.target?e.target:e.srcElement):event.srcElement; + self.handleClick({target:self.getParentByClassName(o,'sm2-360ui').nextSibling}); // link next to the nodes we inserted + return false; + } + + this.buttonMouseDown = function(e) { + // user might decide to drag from here + // watch for mouse move + if (!isTouchDevice) { + document.onmousemove = function(e) { + // should be boundary-checked, really (eg. move 3px first?) + self.mouseDown(e); + } + } else { + self.addEventHandler(document,'touchmove',self.mouseDown); + } + self.stopEvent(e); + return false; + } + + this.mouseDown = function(e) { + if (!self.lastSound) { + self.stopEvent(e); + return false; + } + var thisSound = self.lastSound; + // just in case, update coordinates (maybe the element moved since last time.) + self.refreshCoords(thisSound); + var oData = self.lastSound._360data; + self.addClass(oData.oUIBox,'sm2_dragging'); + oData.pauseCount = (self.lastSound.paused?1:0); + // self.lastSound.pause(); + self.mmh(e?e:event); + if (isTouchDevice) { + self.removeEventHandler(document,'touchmove',self.mouseDown); + self.addEventHandler(document,'touchmove',self.mmh); + self.addEventHandler(document,'touchend',self.mouseUp); + } else { + document.onmousemove = self.mmh; + document.onmouseup = self.mouseUp; + } + self.stopEvent(e); + return false; + } + + this.mouseUp = function(e) { + var oData = self.lastSound._360data; + self.removeClass(oData.oUIBox,'sm2_dragging'); + if (oData.pauseCount == 0) { + self.lastSound.resume(); + } + if (!isTouchDevice) { + document.onmousemove = null; + document.onmouseup = null; + } else { + self.removeEventHandler(document,'touchmove',self.mmh); + self.removeEventHandler(document,'touchend',self.mouseUP); + } + } + + var fullCircle = 360; + + this.mmh = function(e) { + if (typeof e == 'undefined') { + var e = event; + } + var oSound = self.lastSound; + var coords = self.getMouseXY(e); + var x = coords[0]; + var y = coords[1]; + var deltaX = x-oSound._360data.canvasMidXY[0]; + var deltaY = y-oSound._360data.canvasMidXY[1]; + var angle = Math.floor(fullCircle-(self.rad2deg(Math.atan2(deltaX,deltaY))+180)); + oSound.setPosition(oSound.durationEstimate*(angle/fullCircle)); + self.stopEvent(e); + return false; + } + + // assignMouseDown(); + + this.drawSolidArc = function(oCanvas, color, radius, width, radians, startAngle, noClear) { + + // thank you, http://www.snipersystems.co.nz/community/polarclock/tutorial.html + + var x = radius; + var y = radius; + + var canvas = oCanvas; + + if (canvas.getContext){ + // use getContext to use the canvas for drawing + var ctx = canvas.getContext('2d'); + } + + // var startAngle = 0; + var oCanvas = ctx; + + if (!noClear) { + self.clearCanvas(canvas); + } + // ctx.restore(); + + if (color) { + ctx.fillStyle = color; + } else { + // ctx.fillStyle = 'black'; + } + + oCanvas.beginPath(); + + if (isNaN(radians)) { + radians = 0; + } + + var innerRadius = radius-width; + var doesntLikeZero = (isOpera || isSafari); // safari 4 doesn't actually seem to mind. + + if (!doesntLikeZero || (doesntLikeZero && radius > 0)) { + oCanvas.arc(0, 0, radius, startAngle, radians, false); + var endPoint = self.getArcEndpointCoords(innerRadius, radians); + oCanvas.lineTo(endPoint.x, endPoint.y); + oCanvas.arc(0, 0, innerRadius, radians, startAngle, true); + oCanvas.closePath(); + oCanvas.fill(); + } + + } + + this.getArcEndpointCoords = function(radius, radians) { + return { + x: radius * Math.cos(radians), + y: radius * Math.sin(radians) + }; + } + + +this.deg2rad = function(nDeg) { + return (nDeg * Math.PI/180); +} + +this.rad2deg = function(nRad) { + return (nRad * 180/Math.PI); +} + +this.getTime = function(nMSec,bAsString) { + // convert milliseconds to mm:ss, return as object literal or string + var nSec = Math.floor(nMSec/1000); + var min = Math.floor(nSec/60); + var sec = nSec-(min*60); + // if (min == 0 && sec == 0) return null; // return 0:00 as null + return (bAsString?(min+':'+(sec<10?'0'+sec:sec)):{'min':min,'sec':sec}); +} + +this.clearCanvas = function(oCanvas) { + var canvas = oCanvas; + var ctx = null; + if (canvas.getContext){ + // use getContext to use the canvas for drawing + ctx = canvas.getContext('2d'); + } + var width = canvas.offsetWidth; + var height = canvas.offsetHeight; + ctx.clearRect(-(width/2), -(height/2), width, height); +} + + +var fullCircle = (isOpera||isChrome?359.9:360); // I dunno what Opera doesn't like about this. + +this.updatePlaying = function() { + if (this.bytesLoaded) { + this._360data.lastValues.bytesLoaded = this.bytesLoaded; + this._360data.lastValues.bytesTotal = this.bytesTotal; + } + if (this.position) { + this._360data.lastValues.position = this.position; + } + if (this.durationEstimate) { + this._360data.lastValues.durationEstimate = this.durationEstimate; + } + + self.drawSolidArc(this._360data.oCanvas,self.config.backgroundRingColor,this._360data.width,this._360data.radius,self.deg2rad(fullCircle),false); + + self.drawSolidArc(this._360data.oCanvas,(this._360data.metadata?self.config.loadRingColorMetadata:self.config.loadRingColor),this._360data.width,this._360data.radius,self.deg2rad(fullCircle*(this._360data.lastValues.bytesLoaded/this._360data.lastValues.bytesTotal)),0,true); + + if (this._360data.lastValues.position != 0) { + // don't draw if 0 (full black circle in Opera) + self.drawSolidArc(this._360data.oCanvas,(this._360data.metadata?self.config.playRingColorMetadata:self.config.playRingColor),this._360data.width,this._360data.radius,self.deg2rad((this._360data.didFinish==1?fullCircle:fullCircle*(this._360data.lastValues.position/this._360data.lastValues.durationEstimate))),0,true); + } + + // metadata goes here + if (this._360data.metadata) { + this._360data.metadata.events.whileplaying(); + } + + var timeNow = (self.config.showHMSTime?self.getTime(this.position,true):parseInt(this.position/1000)); + + if (timeNow != this._360data.lastTime) { + this._360data.lastTime = timeNow; + this._360data.oTiming.innerHTML = timeNow; + } + + // draw spectrum, if applicable + if (!isIE) { // IE can render maybe 3 or 4 FPS when including the wave/EQ, so don't bother. + self.updateWaveform(this); + // self.updateWaveformOld(this); + } + + if (self.config.useFavIcon && self.vuMeter) { + self.vuMeter.updateVU(this); + } + +} + + this.updateWaveform = function(oSound) { + + if ((!self.config.useWaveformData && !self.config.useEQData) || (!sm.features.waveformData && !sm.features.eqData)) { + // feature not enabled.. + return false; + } + + if (!oSound.waveformData.left.length && !oSound.eqData.length && !oSound.peakData.left) { + // no data (or errored out/paused/unavailable?) + return false; + } + + /* use for testing the data */ + /* + for (i=0; i<256; i++) { + oSound.eqData[i] = 1-(i/256); + } + */ + + var oCanvas = oSound._360data.oCanvas.getContext('2d'); + var offX = 0; + var offY = parseInt(self.config.circleDiameter/2); + var scale = offY/2; // Y axis (+/- this distance from 0) + var lineWidth = Math.floor(self.config.circleDiameter-(self.config.circleDiameter*0.175)/(self.config.circleDiameter/255)); // width for each line + lineWidth = 1; + var lineHeight = 1; + var thisY = 0; + var offset = offY; + + if (self.config.useWaveformData) { + // raw waveform + var downSample = self.config.waveformDataDownsample; // only sample X in 256 (greater number = less sample points) + downSample = Math.max(1,downSample); // make sure it's at least 1 + var dataLength = 256; + var sampleCount = (dataLength/downSample); + var startAngle = 0; + var endAngle = 0; + var waveData = null; + var innerRadius = (self.config.waveformDataOutside?1:(self.config.waveformDataConstrain?0.5:0.565)); + var scale = (self.config.waveformDataOutside?0.7:0.75); + var perItemAngle = self.deg2rad((360/sampleCount)*self.config.waveformDataLineRatio); // 0.85 = clean pixel lines at 150? // self.deg2rad(360*(Math.max(1,downSample-1))/sampleCount); + for (var i=0; i16500 Hz), most stuff won't actually use it. + var sampleCount = (eqSamples/downSample); + var innerRadius = (self.config.eqDataOutside?1:0.565); + var direction = (self.config.eqDataOutside?-1:1); + var scale = (self.config.eqDataOutside?0.5:0.75); + var startAngle = 0; + var endAngle = 0; + var perItemAngle = self.deg2rad((360/sampleCount)*self.config.eqDataLineRatio); // self.deg2rad(360/(sampleCount+1)); + var playedAngle = self.deg2rad((oSound._360data.didFinish==1?360:360*(oSound._360data.lastValues.position/oSound._360data.lastValues.durationEstimate))); + var j=0; + var iAvg = 0; + for (var i=0; iplayedAngle?self.config.eqDataColor:self.config.playRingColor),oSound._360data.width*innerRadius,oSound._360data.radius*scale*(oSound.eqData.left[i]*direction),endAngle,startAngle,true); + } + } + + if (self.config.usePeakData) { + if (!oSound._360data.animating) { + var nPeak = (oSound.peakData.left||oSound.peakData.right); + // GIANT HACK: use EQ spectrum data for bass frequencies + var eqSamples = 3; + for (var i=0; i', + ' ', // note use of imageMap, edit or remove if you use a different-size image. + '
', // + Ever-so-slight Safari horizontal alignment tweak + '
' + ]; + } + + this.init = function() { + sm._writeDebug('threeSixtyPlayer.init()'); + var oItems = self.getElementsByClassName('ui360','div'); + var oLinks = []; + + for (var i=0,j=oItems.length; i0) { + self.addEventHandler(document,'click',self.handleClick); + if (self.config.autoPlay) { + self.handleClick({target:self.links[0],preventDefault:function(){}}); + } + } + sm._writeDebug('threeSixtyPlayer.init(): Found '+foundItems+' relevant items.'); + + if (self.config.useFavIcon && typeof this.VUMeter != 'undefined') { + this.vuMeter = new this.VUMeter(this); + } + + } + +} + +// Optional: VU Meter component + +ThreeSixtyPlayer.prototype.VUMeter = function(oParent) { + + var self = oParent; + var me = this; + this.vuMeterData = []; + this.vuDataCanvas = null; + var _head = document.getElementsByTagName('head')[0]; + var isOpera = (navigator.userAgent.match(/opera/i)); + var isFirefox = (navigator.userAgent.match(/firefox/i)); + + this.setPageIcon = function(sDataURL) { + + if (!self.config.useFavIcon || !self.config.usePeakData || !sDataURL) { + return false; + } + + var link = document.getElementById('sm2-favicon'); + if (link) { + _head.removeChild(link); + link = null; + } + if (!link) { + link = document.createElement('link'); + link.id = 'sm2-favicon'; + link.rel = 'shortcut icon'; + link.type = 'image/png'; + link.href = sDataURL; + document.getElementsByTagName('head')[0].appendChild(link); + } + } + + this.resetPageIcon = function() { + if (!self.config.useFavIcon) { + return false; + } + var link = document.getElementById('favicon'); + if (link) { + link.href = '/favicon.ico'; + } + } + + this.updateVU = function(oSound) { + if (soundManager.flashVersion >= 9 && self.config.useFavIcon && self.config.usePeakData) { + me.setPageIcon(me.vuMeterData[parseInt(16*oSound.peakData.left)][parseInt(16*oSound.peakData.right)]); + } + } + + this.createVUData = function() { + var i=0; + var j=0; + var canvas = me.vuDataCanvas.getContext('2d'); + var vuGrad = canvas.createLinearGradient(0, 16, 0, 0); + vuGrad.addColorStop(0,'rgb(0,192,0)'); + vuGrad.addColorStop(0.30,'rgb(0,255,0)'); + vuGrad.addColorStop(0.625,'rgb(255,255,0)'); + vuGrad.addColorStop(0.85,'rgb(255,0,0)'); + var bgGrad = canvas.createLinearGradient(0, 16, 0, 0); + var outline = 'rgba(0,0,0,0.2)'; + bgGrad.addColorStop(0,outline); + bgGrad.addColorStop(1,'rgba(0,0,0,0.5)'); + for (i=0; i<16; i++) { + me.vuMeterData[i] = []; + } + for (var i=0; i<16; i++) { + for (j=0; j<16; j++) { + // reset/erase canvas + me.vuDataCanvas.setAttribute('width',16); + me.vuDataCanvas.setAttribute('height',16); + // draw new stuffs + canvas.fillStyle = bgGrad; + canvas.fillRect(0,0,7,15); + canvas.fillRect(8,0,7,15); + /* + // shadow + canvas.fillStyle = 'rgba(0,0,0,0.1)'; + canvas.fillRect(1,15-i,7,17-(17-i)); + canvas.fillRect(9,15-j,7,17-(17-j)); + */ + canvas.fillStyle = vuGrad; + canvas.fillRect(0,15-i,7,16-(16-i)); + canvas.fillRect(8,15-j,7,16-(16-j)); + // and now, clear out some bits. + canvas.clearRect(0,3,16,1); + canvas.clearRect(0,7,16,1); + canvas.clearRect(0,11,16,1); + me.vuMeterData[i][j] = me.vuDataCanvas.toDataURL('image/png'); + // for debugging VU images + /* + var o = document.createElement('img'); + o.style.marginRight = '5px'; + o.src = vuMeterData[i][j]; + document.documentElement.appendChild(o); + */ + } + } + }; + + this.testCanvas = function(noOpaque) { + // canvas + toDataURL(); + var c = document.createElement('canvas'); + var ctx = null; + if (!c || typeof c.getContext == 'undefined') { + return null; + } + ctx = c.getContext('2d'); + if (!ctx || typeof c.toDataURL != 'function') { + return null; + } + // just in case.. + try { + var ok = c.toDataURL('image/png'); + } catch(e) { + // no canvas or no toDataURL() + return null; + } + // assume we're all good. + return c; + } + + this.init = function() { + if (self.config.useFavIcon) { + me.vuDataCanvas = me.testCanvas(true); + if (me.vuDataCanvas && (isFirefox || isOpera)) { + // these browsers support dynamically-updating the favicon + me.createVUData(); + } else { + // browser doesn't support doing this + self.config.useFavIcon = false; + } + } + } + + this.init(); + +} + +// completely optional: Metadata/annotations/segments code + +ThreeSixtyPlayer.prototype.Metadata = function(oSound, oParent) { + soundManager._wD('Metadata()'); + var me = this; + var oBox = oSound._360data.oUI360; + var o = oBox.getElementsByTagName('ul')[0]; + var oItems = o.getElementsByTagName('li'); + var isFirefox = (navigator.userAgent.match(/firefox/i)); + this.lastWPExec = 0; + this.refreshInterval = 250; + + var isAlt = false; + + this.events = { + whileplaying: function() { + var width = oSound._360data.width; + var radius = oSound._360data.radius; + var fullDuration = (oSound.durationEstimate||(me.totalTime*1000)); + var isAlt = null; + for (var i=0,j=me.data.length; ime.refreshInterval) { + me.refresh(); + me.lastWPExec = d; + } + } + } + + this.refresh = function() { + // Display info as appropriate + var index = null; + var now = oSound.position; + var metadata = oSound._360data.metadata.data; + for (var i=0, j=metadata.length; i= metadata[i].startTimeMS && now <= metadata[i].endTimeMS) { + index = i; + break; + } + } + if (index != metadata.currentItem && index < metadata.length) { + // update + oSound._360data.oLink.innerHTML = metadata.mainTitle+' '; + // self.setPageTitle(metadata[index].title+' | '+metadata.mainTitle); + metadata.currentItem = index; + } + } + + this.totalTime = 0; + + this.strToTime = function(sTime) { + var segments = sTime.split(':'); + var seconds = 0; + for (var i=segments.length; i--;) { + seconds += parseInt(segments[i])*Math.pow(60,segments.length-1-i,10); // hours, minutes + } + return seconds; + } + + this.data = []; + this.data.givenDuration = null; + this.data.currentItem = null; + this.data.mainTitle = oSound._360data.oLink.innerHTML; + for (var i=0; i= Math.abs(this.state - this.target)) { + this.state = this.target; + } else { + this.state += movement; + } + + try { + this.propagate(); + } finally { + this.options.onStep.call(this); + if (this.target == this.state) { + window.clearInterval(this.intervalId); + this.intervalId = null; + this.options.onComplete.call(this); + } + } + }, + // shortcuts + play: function() {this.seekFromTo(0, 1)}, + reverse: function() {this.seekFromTo(1, 0)}, + // return a string describing this Animator, for debugging + inspect: function() { + var str = "# 20) return; + } + }, + getStyle: function(state) { + state = this.from + ((this.to - this.from) * state); + if (this.property == 'filter') return "alpha(opacity=" + Math.round(state*100) + ")"; + if (this.property == 'opacity') return state; + return Math.round(state) + this.units; + }, + inspect: function() { + return "\t" + this.property + "(" + this.from + this.units + " to " + this.to + this.units + ")\n"; + } +} + +// animates a colour based style property between two hex values +function ColorStyleSubject(els, property, from, to) { + this.els = Animator.makeArray(els); + this.property = Animator.camelize(property); + this.to = this.expandColor(to); + this.from = this.expandColor(from); + this.origFrom = from; + this.origTo = to; +} + +ColorStyleSubject.prototype = { + // parse "#FFFF00" to [256, 256, 0] + expandColor: function(color) { + var hexColor, red, green, blue; + hexColor = ColorStyleSubject.parseColor(color); + if (hexColor) { + red = parseInt(hexColor.slice(1, 3), 16); + green = parseInt(hexColor.slice(3, 5), 16); + blue = parseInt(hexColor.slice(5, 7), 16); + return [red,green,blue] + } + if (window.DEBUG) { + alert("Invalid colour: '" + color + "'"); + } + }, + getValueForState: function(color, state) { + return Math.round(this.from[color] + ((this.to[color] - this.from[color]) * state)); + }, + setState: function(state) { + var color = '#' + + ColorStyleSubject.toColorPart(this.getValueForState(0, state)) + + ColorStyleSubject.toColorPart(this.getValueForState(1, state)) + + ColorStyleSubject.toColorPart(this.getValueForState(2, state)); + for (var i=0; i 255) number = 255; + var digits = number.toString(16); + if (number < 16) return '0' + digits; + return digits; +} +ColorStyleSubject.parseColor.rgbRe = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i; +ColorStyleSubject.parseColor.hexRe = /^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; + +// Animates discrete styles, i.e. ones that do not scale but have discrete values +// that can't be interpolated +function DiscreteStyleSubject(els, property, from, to, threshold) { + this.els = Animator.makeArray(els); + this.property = Animator.camelize(property); + this.from = from; + this.to = to; + this.threshold = threshold || 0.5; +} + +DiscreteStyleSubject.prototype = { + setState: function(state) { + var j=0; + for (var i=0; i section ? 1 : 0); + } + if (this.options.rememberance) { + document.location.hash = this.rememberanceTexts[section]; + } + } +} diff --git a/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/script/excanvas.js b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/script/excanvas.js new file mode 100755 index 0000000..d748873 --- /dev/null +++ b/docs/dymaxion/soundmanagerv297a-20101010/demo/360-player/script/excanvas.js @@ -0,0 +1,17 @@ +// Excanvas (Explorer Canvas) R43 +// http://excanvas.sourceforge.net/ +// Copyright 2006 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +if(!document.createElement("canvas").getContext){(function(){var u=Math;var v=u.round;var r=u.sin;var C=u.cos;var l=u.abs;var B=u.sqrt;var a=10;var n=a/2;function g(){return this.context_||(this.context_=new p(this))}var t=Array.prototype.slice;function D(j,m,E){var i=t.call(arguments,2);return function(){return j.apply(m,i.concat(t.call(arguments)))}}var h={init:function(i){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var j=i||document;j.createElement("canvas");j.attachEvent("onreadystatechange",D(this.init_,this,j))}},init_:function(F){if(!F.namespaces.g_vml_){F.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML")}if(!F.namespaces.g_o_){F.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML")}if(!F.styleSheets.ex_canvas_){var E=F.createStyleSheet();E.owningElement.id="ex_canvas_";E.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}g_o_\\:*{behavior:url(#default#VML)}"}var m=F.getElementsByTagName("canvas");for(var j=0;j','","");this.element_.insertAdjacentHTML("BeforeEnd",Y.join(""))};k.stroke=function(ae){var J=[];var K=false;var ap=c(ae?this.fillStyle:this.strokeStyle);var aa=ap.color;var ak=ap.alpha*this.globalAlpha;var F=10;var M=10;J.push("V.x){V.x=ai.x}if(ao.y==null||ai.yV.y){V.y=ai.y}}}J.push(' ">');if(!ae){var U=this.lineScale_*this.lineWidth;if(U<1){ak*=U}J.push("')}else{if(typeof this.fillStyle=="object"){var N=this.fillStyle;var S=0;var ah={x:0,y:0};var ab=0;var Q=1;if(N.type_=="gradient"){var P=N.x0_/this.arcScaleX_;var m=N.y0_/this.arcScaleY_;var O=N.x1_/this.arcScaleX_;var aq=N.y1_/this.arcScaleY_;var am=this.getCoords_(P,m);var al=this.getCoords_(O,aq);var I=al.x-am.x;var G=al.y-am.y;S=Math.atan2(I,G)*180/Math.PI;if(S<0){S+=360}if(S<0.000001){S=0}}else{var am=this.getCoords_(N.x0_,N.y0_);var j=V.x-ao.x;var E=V.y-ao.y;ah={x:(am.x-ao.x)/j,y:(am.y-ao.y)/E};j/=this.arcScaleX_*a;E/=this.arcScaleY_*a;var ag=u.max(j,E);ab=2*N.r0_/ag;Q=2*N.r1_/ag-ab}var Z=N.colors_;Z.sort(function(H,i){return H.offset-i.offset});var T=Z.length;var Y=Z[0].color;var X=Z[T-1].color;var ad=Z[0].alpha*this.globalAlpha;var ac=Z[T-1].alpha*this.globalAlpha;var af=[];for(var aj=0;aj')}else{J.push('')}}J.push("");this.element_.insertAdjacentHTML("beforeEnd",J.join(""))};k.fill=function(){this.stroke(true)};k.closePath=function(){this.currentPath_.push({type:"close"})};k.getCoords_=function(E,j){var i=this.m_;return{x:a*(E*i[0][0]+j*i[1][0]+i[2][0])-n,y:a*(E*i[0][1]+j*i[1][1]+i[2][1])-n}};k.save=function(){var i={};w(this,i);this.aStack_.push(i);this.mStack_.push(this.m_);this.m_=d(q(),this.m_)};k.restore=function(){w(this.aStack_.pop(),this);this.m_=this.mStack_.pop()};k.translate=function(m,j){var i=[[1,0,0],[0,1,0],[m,j,1]];this.m_=d(i,this.m_)};k.rotate=function(j){var E=C(j);var m=r(j);var i=[[E,m,0],[-m,E,0],[0,0,1]];this.m_=d(i,this.m_)};k.scale=function(G,F){this.arcScaleX_*=G;this.arcScaleY_*=F;var j=[[G,0,0],[0,F,0],[0,0,1]];var i=this.m_=d(j,this.m_);var E=i[0][0]*i[1][1]-i[0][1]*i[1][0];this.lineScale_=B(l(E))};k.clip=function(){};k.arcTo=function(){};k.createPattern=function(){return new f};function z(i){this.type_=i;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}z.prototype.addColorStop=function(j,i){i=c(i);this.colors_.push({offset:j,color:i.color,alpha:i.alpha})};function f(){}G_vmlCanvasManager=h;CanvasRenderingContext2D=p;CanvasGradient=z;CanvasPattern=f})()}; \ No newline at end of file -- cgit v1.2.3-70-g09d2