sinatra-multi-screen 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/History.txt +6 -0
- data/README.md +19 -9
- data/lib/js/multiscreen.js +27 -13
- data/lib/sinatra-multi-screen/version.rb +1 -1
- data/lib/sinatra/application.rb +2 -4
- data/sample/Gemfile +1 -2
- data/sample/Gemfile.lock +1 -3
- data/sample/README.md +2 -2
- data/sample/main.rb +1 -11
- data/sample/public/js/remote.js +17 -34
- data/sample/public/js/tv.js +12 -64
- data/sample/views/main.scss +0 -4
- data/sample/views/remote.haml +16 -12
- data/sample/views/tv.haml +3 -16
- metadata +2 -3
- data/sample/.gitignore +0 -7
data/.gitignore
CHANGED
data/History.txt
CHANGED
data/README.md
CHANGED
@@ -35,12 +35,12 @@ run Sinatra::Application
|
|
35
35
|
<script src="<%= multi_screen_js %>"></script>
|
36
36
|
```
|
37
37
|
|
38
|
-
### Remote --(dispatch UI Event)
|
38
|
+
### Remote --(dispatch UI Event)--> TV
|
39
39
|
|
40
40
|
Remote Side
|
41
41
|
```javascript
|
42
42
|
var io = new CometIO().connect();
|
43
|
-
var screen = new MultiScreen(io, {type: "remote"});
|
43
|
+
var screen = new MultiScreen(io, {type: "remote", channel: "1"});
|
44
44
|
var tv = screen.tv;
|
45
45
|
|
46
46
|
io.on("connect", function(session){
|
@@ -54,7 +54,8 @@ TV Side
|
|
54
54
|
```
|
55
55
|
```javascript
|
56
56
|
var io = new CometIO().connect();
|
57
|
-
var screen = new MultiScreen(io, {type: "tv"});
|
57
|
+
var screen = new MultiScreen(io, {type: "tv", channel: "1"});
|
58
|
+
var remote = screen.remote;
|
58
59
|
|
59
60
|
$(function(){
|
60
61
|
$("#btn").click(function(e){ // regist click event
|
@@ -67,12 +68,7 @@ $(function(){
|
|
67
68
|
|
68
69
|
TV Side
|
69
70
|
```javascript
|
70
|
-
|
71
|
-
var screen = new MultiScreen(io, {type: "tv"});
|
72
|
-
|
73
|
-
io.on("connect", function(session){
|
74
|
-
screen.remote.push("change_color", {color: #FF0000"}); // push "change_color" event to Remote
|
75
|
-
};
|
71
|
+
remote.push("change_color", {color: #FF0000"}); // push "change_color" event to Remote
|
76
72
|
```
|
77
73
|
|
78
74
|
Remote Side
|
@@ -82,6 +78,20 @@ tv.on("change_color", function(data){ // regist "change_color" event
|
|
82
78
|
});
|
83
79
|
```
|
84
80
|
|
81
|
+
### Remote --(push event)--> TV
|
82
|
+
|
83
|
+
Remote Side
|
84
|
+
```javascript
|
85
|
+
tv.push("mode", "fullscreen"); // push "mode" to TV
|
86
|
+
```
|
87
|
+
|
88
|
+
TV Side
|
89
|
+
```javascript
|
90
|
+
remote.on("mode", function(data){
|
91
|
+
console.log(data);
|
92
|
+
});
|
93
|
+
```
|
94
|
+
|
85
95
|
Samples
|
86
96
|
-------
|
87
97
|
* https://github.com/shokai/sinatra-multi-screen/tree/master/sample
|
data/lib/js/multiscreen.js
CHANGED
@@ -1,18 +1,38 @@
|
|
1
1
|
var MultiScreen = function(cometio, options){
|
2
|
-
if(typeof options === 'undefined'
|
2
|
+
if(typeof options === 'undefined'){
|
3
|
+
throw new Error("argument error: option is empty.");
|
4
|
+
}
|
5
|
+
if(typeof options.type === 'undefined'){
|
3
6
|
throw new Error("argument must have connection type.");
|
4
7
|
}
|
8
|
+
if(typeof options.channel === 'undefined' || options.channel.length < 1){
|
9
|
+
options.channel = "__default__channel__";
|
10
|
+
}
|
5
11
|
var self = this;
|
6
12
|
this.io = cometio;
|
7
13
|
this.options = options;
|
8
14
|
this.io.on("connect", function(session){
|
9
15
|
self.io.push("__multiscreen__options", self.options);
|
10
16
|
});
|
17
|
+
|
18
|
+
var to;
|
19
|
+
if(options.type === 'remote') to = 'tv';
|
20
|
+
else if(options.type === 'tv') to = 'remote';
|
21
|
+
if(typeof to === 'undefined'){
|
22
|
+
throw new Error('argument error: type must be "tv" or "remote"');
|
23
|
+
}
|
24
|
+
this[to] = {};
|
25
|
+
new EventEmitter().apply(this[to]);
|
26
|
+
this[to].push = function(event_name, data){
|
27
|
+
self.io.push("__multiscreen__data", {event: event_name, data: data, options: self.options});
|
28
|
+
};
|
29
|
+
this.io.on("__multiscreen__data", function(data){
|
30
|
+
self[to].emit(data.event, data.data);
|
31
|
+
})
|
32
|
+
|
11
33
|
if(options.type == "remote"){
|
12
|
-
this.tv = {};
|
13
|
-
new EventEmitter().apply(this.tv);
|
14
34
|
this.tv.event = function(selector, event_name, args){
|
15
|
-
self.
|
35
|
+
self.tv.push("ui_event", {selector: selector, event: event_name, args: args});
|
16
36
|
};
|
17
37
|
this.tv.$ = function(selector){
|
18
38
|
return {
|
@@ -39,18 +59,12 @@ var MultiScreen = function(cometio, options){
|
|
39
59
|
}
|
40
60
|
};
|
41
61
|
};
|
42
|
-
this.io.on("__multiscreen__event", function(data){
|
43
|
-
self.tv.emit(data.event, data.args);
|
44
|
-
})
|
45
62
|
}
|
46
63
|
|
47
64
|
if(options.type == "tv"){
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
};
|
52
|
-
this.io.on("__multiscreen__event", function(data){
|
53
|
-
if(typeof data.selector === 'undefined') return;
|
65
|
+
self.remote.on("ui_event", function(data){
|
66
|
+
if(typeof data.selector === 'undefined' ||
|
67
|
+
typeof data.event === 'undefined') return;
|
54
68
|
if(typeof data.args === 'undefined'){
|
55
69
|
$(data.selector)[data.event]();
|
56
70
|
}else{
|
data/lib/sinatra/application.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
1
|
module Sinatra
|
4
2
|
|
5
3
|
class Application
|
6
4
|
|
7
|
-
CometIO.on :
|
5
|
+
CometIO.on :__multiscreen__data do |data, from|
|
8
6
|
opts = data["options"]
|
9
7
|
raise ArgumentError, 'option is empty' if !opts or opts.empty?
|
10
8
|
raise ArgumentError, 'channel is empty' if opts["channel"].empty?
|
@@ -19,7 +17,7 @@ module Sinatra
|
|
19
17
|
"tv"
|
20
18
|
end
|
21
19
|
MultiScreen.channels[opts["channel"]][type].each do |session_id|
|
22
|
-
CometIO.push :
|
20
|
+
CometIO.push :__multiscreen__data, data, {:to => session_id}
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
data/sample/Gemfile
CHANGED
data/sample/Gemfile.lock
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
GEM
|
2
|
-
remote:
|
2
|
+
remote: https://rubygems.org/
|
3
3
|
specs:
|
4
4
|
backports (2.8.2)
|
5
5
|
daemons (1.1.9)
|
@@ -40,7 +40,6 @@ GEM
|
|
40
40
|
rack (>= 1.0.0)
|
41
41
|
thor (0.17.0)
|
42
42
|
tilt (1.3.3)
|
43
|
-
youtube_search (0.1.7)
|
44
43
|
|
45
44
|
PLATFORMS
|
46
45
|
ruby
|
@@ -55,4 +54,3 @@ DEPENDENCIES
|
|
55
54
|
sinatra-cometio
|
56
55
|
sinatra-contrib
|
57
56
|
thin
|
58
|
-
youtube_search
|
data/sample/README.md
CHANGED
data/sample/main.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
helpers do
|
2
2
|
def app_name
|
3
|
-
"Multi-Screen
|
3
|
+
"Sinatra-Multi-Screen Sample"
|
4
4
|
end
|
5
5
|
|
6
6
|
def app_root
|
@@ -36,16 +36,6 @@ get '/remote/:channel' do
|
|
36
36
|
haml :remote
|
37
37
|
end
|
38
38
|
|
39
|
-
get '/search.json' do
|
40
|
-
content_type 'application/json'
|
41
|
-
word = params[:word]
|
42
|
-
begin
|
43
|
-
YoutubeSearch.search(word).first.to_json
|
44
|
-
rescue => e
|
45
|
-
throw :halt, [500, 'Internal Server Error']
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
39
|
get '/:source.css' do
|
50
40
|
scss params[:source].to_sym
|
51
41
|
end
|
data/sample/public/js/remote.js
CHANGED
@@ -1,45 +1,28 @@
|
|
1
|
+
// Remote Side
|
1
2
|
var io = new CometIO().connect();
|
2
3
|
var screen = new MultiScreen(io, {type: "remote", channel: channel});
|
3
4
|
var tv = screen.tv;
|
4
5
|
|
5
6
|
io.on("connect", function(session){
|
6
7
|
console.log("connect!! "+session);
|
8
|
+
});
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
});
|
13
|
-
|
14
|
-
$("#text_search").keyup(function(e){
|
15
|
-
var word = $("#text_search").val();
|
16
|
-
console.log(word);
|
17
|
-
tv.$("#text_search").val(word);
|
18
|
-
});
|
19
|
-
|
20
|
-
$("#btn_play").click(function(e){
|
21
|
-
tv.$("#btn_play").click();
|
22
|
-
});
|
23
|
-
|
24
|
-
$("#btn_seek").click(function(e){
|
25
|
-
tv.$("#btn_seek").click();
|
26
|
-
});
|
27
|
-
$("#btn_seekback").click(function(e){
|
28
|
-
tv.$("#btn_seekback").click();
|
29
|
-
});
|
30
|
-
|
31
|
-
var range_seek = $("#range_seek");
|
32
|
-
range_seek.change(function(e){
|
33
|
-
tv.$("#range_seek").val( range_seek.val() );
|
34
|
-
tv.$("#range_seek").change();
|
35
|
-
});
|
10
|
+
// from TV
|
11
|
+
tv.on("message", function(msg){
|
12
|
+
console.log(msg);
|
13
|
+
});
|
36
14
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
});
|
15
|
+
$(function(){
|
16
|
+
generate_code();
|
17
|
+
$("select").change(generate_code);
|
41
18
|
|
42
|
-
|
43
|
-
|
19
|
+
$("#btn_dispatch").click(function(e){
|
20
|
+
eval( $("#code").val() ); // dispatch UI Event on TV
|
44
21
|
});
|
45
22
|
});
|
23
|
+
|
24
|
+
var generate_code = function(){
|
25
|
+
var selector = $("#selector").val();
|
26
|
+
var event_name = $('#event_name').val();
|
27
|
+
$("#code").val( 'tv.$("'+selector+'").'+event_name+'();' );
|
28
|
+
};
|
data/sample/public/js/tv.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
// TV Side
|
1
2
|
var io = new CometIO().connect();
|
2
3
|
var screen = new MultiScreen(io, {type: "tv", channel: channel});
|
3
4
|
var remote = screen.remote;
|
@@ -6,73 +7,20 @@ io.on("connect", function(session){
|
|
6
7
|
console.log("connect!! "+session);
|
7
8
|
});
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
console.log(
|
12
|
-
|
13
|
-
youtube.addEventListener("onStateChange", "onYouTubeStateChange");
|
14
|
-
};
|
15
|
-
|
16
|
-
var onYouTubeStateChange = function(status){
|
17
|
-
console.log("status changed:"+status);
|
18
|
-
switch(status){
|
19
|
-
case 1:
|
20
|
-
var duration = youtube.getDuration();
|
21
|
-
$("#range_seek").attr("max", duration);
|
22
|
-
remote.push("get_duration", duration);
|
23
|
-
break;
|
24
|
-
};
|
25
|
-
};
|
10
|
+
// catch UI Event from Remote
|
11
|
+
remote.on("ui_event", function(data){
|
12
|
+
console.log(data);
|
13
|
+
});
|
26
14
|
|
27
15
|
$(function(){
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
swfobject.embedSWF(url, "youtube_player", "500", "400", "8", null, null, params, atts);
|
32
|
-
|
33
|
-
$("#btn_search").click(function(e){
|
34
|
-
var word = $("#text_search").val();
|
35
|
-
$.getJSON(search_api, {word: word}, function(res){
|
36
|
-
console.log(res);
|
37
|
-
$("h1").text(res.title);
|
38
|
-
youtube.cueVideoById(res.video_id);
|
39
|
-
var url = youtube.getVideoUrl();
|
40
|
-
$("#video_url").html(
|
41
|
-
$("<a>").attr("href", url).text(url)
|
42
|
-
);
|
43
|
-
});
|
44
|
-
});
|
45
|
-
|
46
|
-
var btn_play = $("#btn_play");
|
47
|
-
btn_play.click(function(e){
|
48
|
-
if(youtube.getPlayerState() == 1){
|
49
|
-
youtube.pauseVideo();
|
50
|
-
btn_play.val('play');
|
51
|
-
}
|
52
|
-
else{
|
53
|
-
youtube.playVideo();
|
54
|
-
btn_play.val('pause');
|
55
|
-
}
|
16
|
+
$(".btn").click(function(e){
|
17
|
+
alert(e.currentTarget.innerText);
|
18
|
+
remote.push("message", "click button #"+e.currentTarget.id); // push to Remote
|
56
19
|
});
|
57
20
|
|
58
|
-
$("
|
59
|
-
|
21
|
+
$(".btn").mouseover(function(e){
|
22
|
+
var color = e.currentTarget.attributes['x-color'].value;
|
23
|
+
$("body").css("background-color", color);
|
24
|
+
remote.push("message", "mouse over "+color); // push to Remote
|
60
25
|
});
|
61
|
-
$("#btn_seekback").click(function(e){
|
62
|
-
youtube.seekTo(youtube.getCurrentTime() - 20);
|
63
|
-
});
|
64
|
-
|
65
|
-
var range_seek = $("#range_seek");
|
66
|
-
range_seek.change(function(e){
|
67
|
-
youtube.seekTo(range_seek.val());
|
68
|
-
});
|
69
|
-
|
70
|
-
setInterval(function(){
|
71
|
-
if(typeof youtube !== 'undefined'){
|
72
|
-
var time = youtube.getCurrentTime();
|
73
|
-
$("#range_seek").val(time);
|
74
|
-
$("#text_seek").val(time);
|
75
|
-
remote.push("seek", time);
|
76
|
-
}
|
77
|
-
}, 1000);
|
78
26
|
});
|
data/sample/views/main.scss
CHANGED
data/sample/views/remote.haml
CHANGED
@@ -13,15 +13,19 @@
|
|
13
13
|
%a{:href => app_root} home
|
14
14
|
%h1 Remote
|
15
15
|
%div#main
|
16
|
-
%div
|
17
|
-
%
|
18
|
-
|
19
|
-
%
|
20
|
-
|
21
|
-
%
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
%
|
27
|
-
|
16
|
+
%div
|
17
|
+
%span selector :
|
18
|
+
%select#selector
|
19
|
+
%option #btn_red
|
20
|
+
%option #btn_green
|
21
|
+
%option #btn_blue
|
22
|
+
%div
|
23
|
+
%span event :
|
24
|
+
%select#event_name
|
25
|
+
%option click
|
26
|
+
%option mouseover
|
27
|
+
%div
|
28
|
+
%span code :
|
29
|
+
%input#code{:type => :text, :size => 50}
|
30
|
+
%div
|
31
|
+
%input#btn_dispatch{:type => :button, :value => "dispatch"}
|
data/sample/views/tv.haml
CHANGED
@@ -1,31 +1,18 @@
|
|
1
1
|
- content_for :html_head do
|
2
2
|
%title= @title
|
3
3
|
:javascript
|
4
|
-
var search_api = "#{app_root}/search.json";
|
5
4
|
var channel = "#{@channel}"
|
6
5
|
|
7
6
|
- content_for :html_foot do
|
8
7
|
%script{:src => "#{app_root}/js/jquery.js"}
|
9
8
|
%script{:src => cometio_js}
|
10
9
|
%script{:src => multi_screen_js}
|
11
|
-
%script{:src => "#{app_root}/js/swfobject.js"}
|
12
10
|
%script{:src => "#{app_root}/js/tv.js"}
|
13
11
|
|
14
12
|
%div#header
|
15
13
|
%a{:href => app_root} home
|
16
14
|
%h1 TV
|
17
15
|
%div#main
|
18
|
-
%
|
19
|
-
%
|
20
|
-
%
|
21
|
-
%p
|
22
|
-
%input#text_search{:type => :text, :value => 'ロシア'}
|
23
|
-
%input#btn_search.btn{:type => :button, :value => 'search'}
|
24
|
-
%p
|
25
|
-
%input#btn_play.btn{:type => :button, :value => 'play'}
|
26
|
-
%p
|
27
|
-
%input#range_seek.range{:type => :range, :min => 0}
|
28
|
-
%input#text_seek{:type => :text, :readonly => true, :size => 7}
|
29
|
-
%p
|
30
|
-
%input#btn_seekback.btn{:type => :button, :value => '<<'}
|
31
|
-
%input#btn_seek.btn{:type => :button, :value => '>>'}
|
16
|
+
%span.btn#btn_red{:type => :button, 'x-color' => '#FAA'} id btn_red
|
17
|
+
%span.btn#btn_green{:type => :button, 'x-color' => '#AFA'} id btn_green
|
18
|
+
%span.btn#btn_blue{:type => :button, 'x-color' => '#AAF'} id btn_blue
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-multi-screen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
@@ -67,7 +67,6 @@ files:
|
|
67
67
|
- lib/sinatra-multi-screen/version.rb
|
68
68
|
- lib/sinatra/application.rb
|
69
69
|
- lib/sinatra/multi_screen.rb
|
70
|
-
- sample/.gitignore
|
71
70
|
- sample/Gemfile
|
72
71
|
- sample/Gemfile.lock
|
73
72
|
- sample/Procfile
|