From 028382a751ae6d07da6e3b832cc86f39b170b70b Mon Sep 17 00:00:00 2001
From: Timer91 <marais.jeremie@gmail.com>
Date: Thu, 14 Jan 2016 01:26:25 +0100
Subject: [PATCH 1/2] tempo

---
 api/video.js              |  8 ++++++++
 dom.js                    |  2 ++
 index.html                |  2 ++
 player/events/rotation.js | 38 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 50 insertions(+)
 create mode 100644 player/events/rotation.js

diff --git a/api/video.js b/api/video.js
index 95cb65f..72ce434 100644
--- a/api/video.js
+++ b/api/video.js
@@ -149,6 +149,14 @@ api.video = that = {
 			jqVideo.trigger( "opacitychange" );
 		}
 		return that;
+	},
+
+	// Getter: width/height
+	width: function() {
+		return video.videoWidth;
+	},
+	height: function() {
+		return video.videoHeight;
 	}
 };
 
diff --git a/dom.js b/dom.js
index 1a3baf4..302e97d 100644
--- a/dom.js
+++ b/dom.js
@@ -34,6 +34,8 @@ window.dom = {
 		// Opacity
 		jqPlayerOpacityIcon: $( "#ctrl .opacity .fa" ),
 		jqPlayerOpacitySlider: $( "#ctrl .opacity .cuteslider" ),
+		// Rotation
+		jqPlayerRotationIcon: $( "#ctrl .rotation" ),
 		// CurrentTime
 		jqPlayerSliderCurrentTime: $( "#ctrl .cuteslider.position" ),
 			// Thumbnail
diff --git a/index.html b/index.html
index 5676441..ecfb8d5 100644
--- a/index.html
+++ b/index.html
@@ -103,6 +103,7 @@ <h1 class="title">
 						</span>
 					</div
 					><div class="right"
+						><i class="btn rotation fa fa-repeat"></i
 						><span class="btn opacity"
 							><i class="fa fa-fw"></i
 							><div
@@ -200,6 +201,7 @@ <h1 class="title">
 <script src="player/events/controls.js"></script>
 <script src="player/events/subtitles.js"></script>
 <script src="player/events/thumbnail.js"></script>
+<script src="player/events/rotation.js"></script>
 <script src="player/events/position.js"></script>
 <script src="player/events/playpausestop.js"></script>
 <script src="player/events/volume.js"></script>
diff --git a/player/events/rotation.js b/player/events/rotation.js
new file mode 100644
index 0000000..bd05faa
--- /dev/null
+++ b/player/events/rotation.js
@@ -0,0 +1,38 @@
+(function(){
+
+var
+	jqVideo = dom.jqPlayerVideo,
+	jqRotation = dom.jqPlayerRotationIcon
+;
+
+function getRotationDegrees( obj ) {
+	var matrix = obj.css( "transform" );
+
+	if( matrix !== 'none' ) {
+		var
+			values =
+				matrix
+					.split( '(' )[ 1 ]
+					.split( ')' )[ 0 ]
+					.split( ',' )
+			,
+			a = values[ 0 ],
+			b = values[ 1 ],
+			angle = Math.round( Math.atan2( b, a ) * ( 180 / Math.PI ) )
+		;
+	} else { var angle = 0; }
+	//return (angle < 0) ? angle + 360 : angle;
+	return angle;
+}
+
+function rotate( degree ) {
+	var rotation = getRotationDegrees( jqVideo );
+
+	jqVideo.css( { transform: "rotate(" + ( rotation + degree ) + "deg)" } );
+}
+
+
+
+jqRotation.click( function() { rotate( 45 ); } );
+
+})();

From d464ee755722647bf33fa44aeadd4dac8dc36cb7 Mon Sep 17 00:00:00 2001
From: Timer91 <marais.jeremie@gmail.com>
Date: Thu, 14 Jan 2016 04:48:13 +0100
Subject: [PATCH 2/2] Controls+Rotation: New menu for rotation with a
 cuteslider

---
 api/video.js              | 12 ++++++++++++
 dom.js                    |  4 +++-
 index.html                | 21 ++++++++++++++++++++-
 init.js                   |  1 +
 player/css/controls.css   |  8 +++++++-
 player/data-binding.js    |  4 ++++
 player/events/rotation.js | 37 +++----------------------------------
 player/player-ui.js       |  9 +++++++++
 tools/utils.js            |  1 +
 9 files changed, 60 insertions(+), 37 deletions(-)

diff --git a/api/video.js b/api/video.js
index adb776f..a342690 100644
--- a/api/video.js
+++ b/api/video.js
@@ -4,6 +4,7 @@ var
 	that,
 	oldSource,
 	opacity,
+	rotation,
 	isStopped = true,
 	isLoaded = false,
 	video = dom.jqPlayerVideo[ 0 ],
@@ -155,12 +156,23 @@ api.video = that = {
 		return that;
 	},
 
+	// Rotation (degrees)
+	rotation: function( deg ) {
+		if ( arguments.length === 0 ) {
+			return rotation;
+		}
+		rotation = utils.range( 0, deg, 360, rotation );
+		jqVideo.trigger( "rotationchange" );
+		return that;
+	},
+
 	// Getter: width/height
 	width: function() {
 		return video.videoWidth;
 	},
 	height: function() {
 		return video.videoHeight;
+	},
 
 	opacityToggle: function( b ) {
 		if ( typeof b !== "boolean" ) {
diff --git a/dom.js b/dom.js
index d7fd196..b683892 100644
--- a/dom.js
+++ b/dom.js
@@ -45,7 +45,9 @@ window.dom = {
 		jqPlayerOpacitySlider: $( "#ctrl .opacity .cuteslider" ),
 		jqPlayerOpacityValue: $( "#ctrl .opacity .val" ),
 		// Rotation
-		jqPlayerRotationIcon: $( "#ctrl .rotation" ),
+		jqPlayerRotationIcon: $( "#ctrl .rotation .fa" ),
+		jqPlayerRotationSlider: $( "#ctrl .rotation .cuteslider" ),
+		jqPlayerRotationValue: $( "#ctrl .rotation .val" ),
 		// CurrentTime
 		jqPlayerSliderCurrentTime: $( "#ctrl .cuteslider.position" ),
 			// Thumbnail
diff --git a/index.html b/index.html
index 992f08a..d3bee25 100644
--- a/index.html
+++ b/index.html
@@ -102,7 +102,26 @@ <h1 class="title">
 						</span>
 					</div
 					><div class="right"
-						><i class="btn rotation fa fa-repeat"></i
+						><span class="btn rotation"
+							><i class="fa fa-repeat"></i
+							><div
+								class="menu"
+								><div class="content"
+									><div class="header"
+										><span class="title">Rotation : </span
+										><b class="val"></b
+									></div
+									><ul
+										><li
+											><input
+												type="range"
+												data-jquery-element="cuteslider"
+												min="0" max="360" value="0" step="1"
+										/></li
+									></ul
+								></div
+							></div
+						></span
 						><span class="btn visu"
 							><i class="fa fa-fw fa-align-center fa-rotate-270"></i
 							><div
diff --git a/init.js b/init.js
index c439df9..f6fdb94 100644
--- a/init.js
+++ b/init.js
@@ -5,6 +5,7 @@ playerUI.textsShowing = false;
 api.video
 	.resizeUpdate()
 	.opacity( 1 )
+	.rotation( 0 )
 	// Force the volumechange event
 	.volume( 0 )
 	.volume( 1 )
diff --git a/player/css/controls.css b/player/css/controls.css
index e6d1a2e..500f21e 100644
--- a/player/css/controls.css
+++ b/player/css/controls.css
@@ -115,7 +115,8 @@
 	right: -62px;
 }
 
-#ctrl .opacity .menu .cuteslider {
+#ctrl .opacity .menu .cuteslider,
+#ctrl .rotation .menu .cuteslider {
 	width: 90px;
 	height: 14px;
 	margin: 0 .9em 0 .7em;
@@ -131,3 +132,8 @@
 	width: 28px;
 	height: 13px;
 }
+
+#ctrl .rotation .menu {
+	min-width: 120px;
+	right: -52px;
+}
diff --git a/player/data-binding.js b/player/data-binding.js
index 2a9e4af..46da958 100644
--- a/player/data-binding.js
+++ b/player/data-binding.js
@@ -50,6 +50,10 @@ dom.jqPlayerVideo.on( {
 	opacitychange: function() {
 		lg( "ON: opacitychange" );
 		playerUI.opacity( api.video.opacity() );
+	},
+	rotationchange: function() {
+		lg( "ON: rotationchange" );
+		playerUI.rotation( api.video.rotation() );
 	}
 });
 
diff --git a/player/events/rotation.js b/player/events/rotation.js
index bd05faa..de17aed 100644
--- a/player/events/rotation.js
+++ b/player/events/rotation.js
@@ -1,38 +1,7 @@
 (function(){
 
-var
-	jqVideo = dom.jqPlayerVideo,
-	jqRotation = dom.jqPlayerRotationIcon
-;
-
-function getRotationDegrees( obj ) {
-	var matrix = obj.css( "transform" );
-
-	if( matrix !== 'none' ) {
-		var
-			values =
-				matrix
-					.split( '(' )[ 1 ]
-					.split( ')' )[ 0 ]
-					.split( ',' )
-			,
-			a = values[ 0 ],
-			b = values[ 1 ],
-			angle = Math.round( Math.atan2( b, a ) * ( 180 / Math.PI ) )
-		;
-	} else { var angle = 0; }
-	//return (angle < 0) ? angle + 360 : angle;
-	return angle;
-}
-
-function rotate( degree ) {
-	var rotation = getRotationDegrees( jqVideo );
-
-	jqVideo.css( { transform: "rotate(" + ( rotation + degree ) + "deg)" } );
-}
-
-
-
-jqRotation.click( function() { rotate( 45 ); } );
+dom.jqPlayerRotationSlider.change( function() {
+	api.video.rotation( this.value );
+});
 
 })();
diff --git a/player/player-ui.js b/player/player-ui.js
index 1661de8..64c8a05 100644
--- a/player/player-ui.js
+++ b/player/player-ui.js
@@ -21,6 +21,10 @@ var
 	// Button: fullscreen.
 	jqBtnFScr = dom.jqPlayerFullscreenBtn,
 
+	// Button, slider: rotation.
+	jqRotationIcon = dom.jqPlayerRotationIcon,
+	jqRotationSlider = dom.jqPlayerRotationSlider,
+
 	// Button, slider: opacity.
 	jqOpacityIcon = dom.jqPlayerOpacityIcon,
 	jqOpacitySlider = dom.jqPlayerOpacitySlider,
@@ -158,6 +162,11 @@ window.playerUI = that = {
 	speed: function( rate ) {
 		return that.actionDesc( "Speed : " + rate.toFixed( 2 ) + "x" );
 	},
+	rotation: function( rot ) {
+		dom.jqPlayerVideo.css( { transform: "rotate(" + rot + "deg)" } );
+		dom.jqPlayerRotationValue.text( rot + "°" );
+		return that;
+	},
 	opacity: function( op ) {
 		dom.jqPlayerScreen.css( "opacity", op );
 		jqOpacitySlider.element().val( op );
diff --git a/tools/utils.js b/tools/utils.js
index bd5c140..4458f42 100644
--- a/tools/utils.js
+++ b/tools/utils.js
@@ -18,6 +18,7 @@ window.utils = {
 	},
 	range: function( a, val, b, ori ) {
 		var valn = +val;
+
 		if ( arguments.length === 4 && val[ 1 ] === "=" ) {
 			valn =
 				( ori || 0 ) +