This repository has been archived by the owner on May 27, 2023. It is now read-only.
/
mojolicious-radio-box.pl
executable file
·3197 lines (3068 loc) · 227 KB
/
mojolicious-radio-box.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/perl
=head1 Mojolicious radio box
Small web application for control radio/music player (cmus).
It can be run on a server/desktop/raspberry pi.
https://github.com/msoap/mojolicious-radio-box
=cut
use strict;
use warnings;
use utf8;
use open qw/:std :utf8/;
use Mojolicious::Lite;
use Data::Dumper;
our $VERSION = '0.01';
our %OPTIONS = (
ini_file => "$ENV{HOME}/.cmus/mojolicious-radio-box.ini",
last_track_file => "$ENV{HOME}/.cmus/last_track.tsv",
playlist_file => "$ENV{HOME}/.cmus/playlist.pl",
listen_address => 'http://*:8080',
hypnotoad_workers => 5,
hypnotoad_accept_interval => 0.1,
);
# ------------------------------------------------------------------------------
# util functions
# ------------------------------------------------------------------------------
sub init {
if (-r $OPTIONS{ini_file}) {
open my $FH, '<', $OPTIONS{ini_file} or die "Error open file: $!\n";
while (my $line = <$FH>) {
chomp $line;
next if $line =~ m/^ \s* $/x || $line =~ m/^ \s* \# .* $/x;
my ($key, $value) = split /\s*=\s*/, $line, 2;
$OPTIONS{$key} = $value;
}
close $FH;
$OPTIONS{radio_playlist_dir} =~ s/^~/$ENV{HOME}/ if defined $OPTIONS{radio_playlist_dir};
}
$OPTIONS{is_mac} = 1 if $^O eq 'darwin';
$OPTIONS{is_linux} = 1 if $^O eq 'linux';
$OPTIONS{is_pulseaudio} = 1 if $OPTIONS{is_linux} && `pacmd --version` =~ m/^pacmd\s+\d+/;
$OPTIONS{is_alsa} = 1 if $OPTIONS{is_linux} && `amixer --version` =~ m/^amixer\s+version\s+\d+/;
# get default sound card for pulseaudio
if ($OPTIONS{is_pulseaudio} && ! defined $OPTIONS{"pa-default-sink"}) {
$OPTIONS{"pa-default-sink"} = `pacmd dump | grep set-default-sink | awk '{print \$2}'`;
$OPTIONS{"pa-default-sink"} = "0" unless defined $OPTIONS{"pa-default-sink"} && length($OPTIONS{"pa-default-sink"}) > 0;
}
}
# ------------------------------------------------------------------------------
=head2 get_radio_stations
Get array with radio-station urls (from $OPTIONS{radio_playlist_dir} dir)
testing:
perl -ME -E 'p from_json(get("http://localhost:8080/get_radio"))'
=cut
sub get_radio_stations {
my $result = [];
if ($OPTIONS{radio_playlist_dir} && -d -r $OPTIONS{radio_playlist_dir}) {
for my $m3u_file (glob("$OPTIONS{radio_playlist_dir}/*.m3u"), glob("$OPTIONS{radio_playlist_dir}/*.pls")) {
my ($title_from_name, $ext) = $m3u_file =~ m{([^/]+)\.(m3u|pls)$};
$title_from_name =~ s/_/ /g;
my ($title, $url);
open my $FH, '<', $m3u_file or die "Error open file: $!\n";
while (my $line = <$FH>) {
chomp $line;
if ($ext eq 'm3u') {
$title = $1 if ! $title && $line =~ /^\#EXTINF: -?\d+, (.+?) \s* $/x;
if (! $url && $line =~ m{^http://}) {
$url = $line;
$url =~ s/\s+//g;
}
last if $title && $url;
} elsif ($ext eq 'pls') {
$title = $1 if $line =~ m{^Title\d+=(.+)\s*$};
$url = $1 if $line =~ m{^File\d+=(http://.+?)\s*$};
last if $url && $title;
}
}
close $FH;
push @$result, {title => $title || $title_from_name, url => $url} if $url && ($title || $title_from_name);
}
}
return $result;
}
# ------------------------------------------------------------------------------
=head1 cmus player client
http://cmus.sourceforge.net
=cut
# ------------------------------------------------------------------------------
=head2 cmus_get_info
Get info from cmus player
testing:
perl -ME -E 'do "src/cmus-client.pm"; p cmus_get_info()'
perl -ME -E 'p from_json(get("http://localhost:8080/get_info"))'
=cut
sub cmus_get_info {
my $info = _cmus_parse_info(`cmus-remote --query`);
# for internet-radio get title from file
if (! exists $info->{stream}
&& $info->{status}
&& $info->{status} eq 'playing'
&& ($info->{duration} == -1 || $info->{file} =~ m[^https?://])
&& -r $OPTIONS{last_track_file}
)
{
open my $FH, '<', $OPTIONS{last_track_file} or die "Error open file: $!\n";
my $add_info = {};
while (my $line = <$FH>) {
chomp $line;
my ($key, $value) = split "\t", $line, 2;
$add_info->{$key} = $value if length($key) > 0;
}
$info->{stream} = $add_info->{title} if $add_info->{title};
close $FH;
}
if ($OPTIONS{is_mac}) {
$info->{volume} = int(`osascript -e "output volume of (get volume settings)"`);
} elsif ($OPTIONS{is_pulseaudio}) {
my ($pa_info) = grep {/set-sink-volume/ && /\Q$OPTIONS{"pa-default-sink"}\E/} `pacmd dump`;
$pa_info =~ /\s+ ([0-9a-fx]+) \s* $/xi;
if (defined $1 && hex($1) >= 0) {
$info->{volume} = int(sprintf("%0.0f", hex($1) / 65536 * 100));
}
} elsif ($OPTIONS{is_alsa}) {
my $alsa_info = join "#", grep {/Front\s+(Left|Right):\s+Playback/} `amixer get Master`;
if ($alsa_info =~ /\d+ \s+ \[(\d{1,3})%\] .+ \d+ \s+ \[(\d{1,3})%\]/sx) {
$info->{volume} = int((int($1) + int($2)) / 2);
}
}
$info->{server_version} = $VERSION;
return $info;
}
# ------------------------------------------------------------------------------
=head2 cmus_pause
Pause/unpause player
=cut
sub cmus_pause {
return _cmus_parse_info(`cmus-remote --pause --query`);
}
# ------------------------------------------------------------------------------
=head2 cmus_play
Play player
=cut
sub cmus_play {
return _cmus_parse_info(`cmus-remote --play --query`);
}
# ------------------------------------------------------------------------------
=head2 cmus_stop
Stop player
=cut
sub cmus_stop {
return _cmus_parse_info(`cmus-remote --stop --query`);
}
# ------------------------------------------------------------------------------
=head2 cmus_next
do next song
=cut
sub cmus_next {
return _cmus_parse_info(`cmus-remote --next --query`);
}
# ------------------------------------------------------------------------------
=head2 cmus_prev
do prev song
=cut
sub cmus_prev {
return _cmus_parse_info(`cmus-remote --prev --query`);
}
# ------------------------------------------------------------------------------
=head2 cmus_play_radio
play radio by url
=cut
sub cmus_play_radio {
my $url = shift;
if ($url) {
open my $PIPE, '|-', 'cmus-remote' or die "Error open file: $!\n";
print $PIPE join("\n", 'view playlist'
, 'save'
, 'clear'
, 'player-stop'
, "add $url"
, 'player-play'
, 'player-next'
) . "\n";
close $PIPE;
}
return cmus_get_info();
}
# ------------------------------------------------------------------------------
=head2 cmus_get_music
=cut
sub cmus_get_music {
if (-r $OPTIONS{playlist_file}) {
open my $FH, '<', $OPTIONS{playlist_file} or die "Error open file: $!\n";
my @playlist = grep {$_ && $_ ne '' && ! m|^https?://|}
map {chomp; $_}
<$FH>;
close $FH;
if (@playlist) {
open my $PIPE, '|-', 'cmus-remote' or die "Error open file: $!\n";
print $PIPE join("\n", 'view playlist'
, 'clear'
, 'player-stop'
, map({"add $_"} @playlist)
, 'player-play'
, 'player-next'
) . "\n";
close $PIPE;
}
}
return cmus_get_info();
}
# ------------------------------------------------------------------------------
=head2 cmus_set_volume
Set sound volume
=cut
sub cmus_set_volume {
my $volume = shift;
die "cmus_set_volume: volume is invalid"
unless defined $volume
&& $volume =~ /^\d+$/
&& $volume >= 0
&& $volume <= 100;
if ($OPTIONS{is_mac}) {
system("osascript", "-e", "set volume output volume $volume");
} elsif ($OPTIONS{is_pulseaudio}) {
system("pactl", "set-sink-volume", $OPTIONS{"pa-default-sink"}, "${volume}%");
} elsif ($OPTIONS{is_alsa}) {
system("amixer", "-q", "set", "Master", "${volume}%");
}
return;
}
# ------------------------------------------------------------------------------
=head1 _cmus_parse_info
Parse lines from cmus-remote -Q
=cut
sub _cmus_parse_info {
my @info_lines = @_;
my $result = {};
for my $line (@info_lines) {
chomp $line;
my ($name, $value) = split /\s+/, $line, 2;
if ($name =~ /^(tag|set)$/) {
my ($sub_name, $value) = split /\s+/, $value, 2;
$value = $value =~ /^(true|false)$/ ? {true => 1, false => 0}->{$value} : $value;
$result->{$name}->{$sub_name} = $value;
} else {
$result->{$name} = $value;
}
}
if ($result->{set}->{softvol} && $result->{set}->{vol_left} >= 0 && $result->{set}->{vol_right} >= 0) {
$result->{soft_volume} = int(($result->{set}->{vol_left} + $result->{set}->{vol_right}) / 2);
}
return $result;
}
# mojolicious routers ----------------------------------------------------------
get '/' => 'index';
get '/get_info' => sub {
my $self = shift;
return $self->render_json({status => 'ok', info => cmus_get_info()});
};
post '/pause' => sub {
my $self = shift;
return $self->render_json({status => 'ok', info => cmus_pause()});
};
post '/play' => sub {
my $self = shift;
return $self->render_json({status => 'ok', info => cmus_play()});
};
post '/stop' => sub {
my $self = shift;
return $self->render_json({status => 'ok', info => cmus_stop()});
};
post '/next' => sub {
my $self = shift;
return $self->render_json({status => 'ok', info => cmus_next()});
};
post '/prev' => sub {
my $self = shift;
return $self->render_json({status => 'ok', info => cmus_prev()});
};
get '/get_radio' => sub {
my $self = shift;
return $self->render_json({status => 'ok', radio_stations => get_radio_stations()});
};
post '/play_radio' => sub {
my $self = shift;
my $url = $self->param("url");
return $self->render_json({status => 'ok', info => cmus_play_radio($url)});
};
get '/get_music' => sub {
my $self = shift;
return $self->render_json({status => 'ok', info => cmus_get_music()});
};
# curl -s -d '' 'http://localhost:8080/set_volume/20'
post '/set_volume/:volume' => [volume => qr/\d+/] => sub {
my $self = shift;
my $volume = $self->param("volume");
cmus_set_volume($volume);
return $self->render_json({status => 'ok'});
};
# curl -s http://localhost:8080/help.txt
get '/help' => sub {
my $self = shift;
my $routes = $self->app->routes();
my $result = join "\n",
map {
($_->{via} ? join("/", @{$_->{via}}) : "ANY")
. " "
. ($_->{pattern}->{pattern} || "/")
}
sort {($a->{pattern}->{pattern} || '') cmp ($b->{pattern}->{pattern} || '')}
@{$routes->{children}};
return $self->render_text($result);
};
get '/version' => sub {
my $self = shift;
return $self->render_text($VERSION);
};
app->hook(
before_dispatch => sub {
my $self = shift;
$self->res->headers->header('Server' => "Mojolicious radio box - $VERSION");
}
);
# go ---------------------------------------------------------------------------
init();
app
->config(
hypnotoad => {
listen => [$OPTIONS{listen_address}],
workers => $OPTIONS{hypnotoad_workers},
accept_interval => $OPTIONS{hypnotoad_accept_interval},
}
)
->secret('KxY0bCQwtVmQa2QdxqX8E0WtmVdpv362NJxofWP')
->start(@ARGV ? @ARGV : ("daemon", "--listen=$OPTIONS{listen_address}"));
__DATA__
@@ index.html.ep
<!doctype html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.3, maximum-scale=2.0, user-scalable=yes"/>
<title>Mojolicious radio box</title>
<script src="/mojo/jquery/jquery.js"></script>
<script src="/script.js"></script>
<style>
h1 {
font-size: 80%;
}
button.nav_buttons {
width: 95px;
height: 30px;
top: 5px;
font-size: 10pt;
border: 1px solid #888;
border-radius: 5px;
background-color: #eee;
box-shadow: 2px 2px 5px #888;
}
button.nav_buttons:hover {
box-shadow: 2px 2px 6px #519BB6;
}
button.nav_buttons i {
font-size: 95%;
}
#div_info {
margin-top: 10px;
margin-bottom: 10px;
font-family: sans-serif;
font-size: 90%;
}
#div_error {
color: red;
display: none;
font-family: sans-serif;
margin-top: 10px;
}
#bt_get_radio, #bt_get_music {
width: 130px;
}
#radio_stations {
width: 170px;
display: none;
}
input#volume_slider {
margin: 7px 7px;
width: 165px;
}
.volume-buttons {
width: 50px;
position: relative;
top: -3px;
font-size: 10pt;
border: 1px solid #888;
background-color: #eee;
}
#volume_down {
border-radius: 15px 3px 3px 15px;
}
#volume_up {
border-radius: 3px 15px 15px 3px;
}
</style>
<link rel="stylesheet" href="/font-awesome.css">
</head>
<body>
<h1>♫♬ Mojolicious radio box</h1>
<div>
<button class="nav_buttons" id="bt_prev"><i class="icon-backward"></i> prev</button>
<button class="nav_buttons" id="bt_pause"><i class="icon-play"></i> play</button>
<button class="nav_buttons" id="bt_next">next <i class="icon-forward"></i></button>
</div>
<div id="div_info"></div>
<button class="nav_buttons" id="bt_get_radio"><i class="icon-tasks"></i> get radio…</button>
<select id="radio_stations"></select><br>
<button class="nav_buttons" id="bt_get_music"><i class="icon-music"></i> get music…</button><br><br>
<button id="volume_down" class="volume-buttons"><i class="icon-volume-down"></i></button>
<input id="volume_slider" type="range" min="0" max="100" step="1">
<button id="volume_up" class="volume-buttons"><i class="icon-volume-up" id="volume_up"></i></button>
<div id="div_error">Server unavailable…</div>
</body>
</html>
@@ not_found.html.ep
<h1>404</h1>
@@ script.js
(function() {
window.App = {
info: {
status: "-",
position: 0,
duration: 0
},
radio_stations: [],
init: function() {
$("#bt_pause").on('click', App.do_pause);
$("#bt_next").on('click', App.do_next);
$("#bt_prev").on('click', App.do_prev);
$("#bt_get_radio").on('click', App.do_get_radio);
$("#bt_get_music").on('click', App.do_get_music);
$("#radio_stations").on('change', App.do_select_radio);
$("#volume_slider").on('change', {
absolute: true
}, App.do_change_volume);
$("#volume_slider").on('blur', {
absolute: true
}, App.do_change_volume);
$("#volume_down").on('click', {
down: 10
}, App.do_change_volume);
$("#volume_up").on('click', {
up: 10
}, App.do_change_volume);
$(document).ajaxError(function() {
return $("#div_error").show().fadeOut(1500, function() {
return $("button.nav_buttons").removeAttr('disabled');
});
});
App.update_info();
if (!navigator.userAgent.match(/WebClip/)) {
return window.setInterval(App.update_info, 15 * 1000);
}
},
update_info: function() {
return $.get('/get_info', function(info_data) {
App.info = info_data.info;
if (App.info.volume != null) {
App.volume = App.info.volume;
}
return App.render_info();
});
},
render_info: function() {
var duration, position;
$("button.nav_buttons").removeAttr('disabled');
if (App.info.status === 'playing') {
$("#bt_pause").html('<i class="icon-pause"> pause');
if (App.info.duration === "-1") {
$("#bt_prev").attr('disabled', 'disabled');
$("#bt_next").attr('disabled', 'disabled');
}
} else if (App.info.status === 'paused' || App.info.status === 'stopped') {
$("#bt_pause").html('<i class="icon-play"> play');
}
if (App.info.tag) {
position = parseInt(App.info.position) > 0 ? " (" + App.format_track_time(parseInt(App.info.position)) + ")" : "";
if (App.info.stream) {
$("#div_info").html("" + App.info.tag.title + "<br>\n<b>" + App.info.stream + position + "</b>");
} else if (App.info.tag.artist && App.info.tag.album) {
duration = parseInt(App.info.duration) > 0 ? " (" + App.format_track_time(parseInt(App.info.duration)) + ")" : "";
$("#div_info").html("" + App.info.tag.artist + "<br>\n<i>" + App.info.tag.album + "</i><br>\n<b>" + App.info.tag.title + duration + "</b>");
$("#radio_stations").hide()[0].selectedIndex = 0;
} else {
$("#div_info").html("<b>" + App.info.tag.title + position + "</b>");
}
}
if (App.info.stream || (App.info.file != null) && App.info.file.match(/https?:\/\//)) {
$("#radio_stations").show();
if (App.radio_stations.length) {
App.render_select_radio();
} else {
App.do_get_radio();
}
}
if (App.volume != null) {
return $('input#volume_slider').val(App.volume);
}
},
render_select_radio: function() {
var item, new_option, select_input, _i, _len, _ref, _results;
select_input = $('#radio_stations')[0];
select_input.options.length = 0;
select_input.options.add(new Option(' - please select station -', ''));
_ref = App.radio_stations;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
item = _ref[_i];
new_option = new Option(item.title, item.url);
if ((App.info.file != null) && App.info.file.match(/https?:\/\//) && App.info.file === item.url) {
new_option.selected = true;
}
_results.push(select_input.options.add(new_option));
}
return _results;
},
format_track_time: function(all_seconds) {
var hours, minutes, result, seconds;
hours = Math.floor(all_seconds / 3600);
minutes = Math.floor((all_seconds - hours * 3600) / 60);
seconds = (all_seconds - hours * 3600 - minutes * 60) % 60;
if (minutes < 10) {
minutes = "0" + minutes;
}
if (seconds < 10) {
seconds = "0" + seconds;
}
result = "" + minutes + ":" + seconds;
if (hours > 0) {
result = "" + hours + ":" + result;
}
return result;
},
do_pause: function() {
$("#bt_pause").attr('disabled', 'disabled');
if (App.info.duration > 0) {
return $.post('/pause', function(info_data) {
App.info = info_data.info;
return App.render_info();
});
} else if (App.info.status === 'playing') {
return $.post('/stop', function(info_data) {
App.info = info_data.info;
return App.render_info();
});
} else if (App.info.status === 'stopped') {
return $.post('/play', function(info_data) {
App.info = info_data.info;
return App.render_info();
});
}
},
do_next: function() {
$("#bt_next").attr('disabled', 'disabled');
return $.post('/next', function(info_data) {
App.info = info_data.info;
return App.render_info();
});
},
do_prev: function() {
$("#bt_prev").attr('disabled', 'disabled');
return $.post('/prev', function(info_data) {
App.info = info_data.info;
return App.render_info();
});
},
do_get_radio: function() {
return $.get('/get_radio', function(result) {
$("#radio_stations").show();
App.radio_stations = result.radio_stations;
return App.render_select_radio();
});
},
do_get_music: function() {
return $.get('/get_music', function(info_data) {
App.info = info_data.info;
return App.render_info();
});
},
do_select_radio: function(event) {
if (event.target.value) {
return $.post('/play_radio', {
url: event.target.value
}, function(info_data) {
App.info = info_data.info;
return App.render_info();
});
}
},
do_change_volume: function(event) {
var new_volume;
if (App._change_valume_tid) {
window.clearTimeout(App._change_valume_tid);
App._change_valume_tid = void 0;
}
new_volume = 0;
if (event.data.up && (App.volume != null)) {
new_volume = App.volume + event.data.up;
if (new_volume > 100) {
new_volume = 100;
}
} else if (event.data.down && (App.volume != null)) {
new_volume = App.volume - event.data.down;
if (new_volume < 0) {
new_volume = 0;
}
} else if (event.data.absolute) {
new_volume = parseInt($("#volume_slider").val());
} else {
return;
}
return App._change_valume_tid = window.setTimeout(function() {
if ((new_volume != null) && new_volume !== App.volume) {
App.volume = new_volume;
$("#volume_slider").val(new_volume);
return $.post('/set_volume/' + new_volume);
}
}, 200);
}
};
$(function() {
return App.init();
});
}).call(this);
@@ font-awesome.css
/*!
* Font Awesome 3.0.2
* the iconic font designed for use with Twitter Bootstrap
* -------------------------------------------------------
* The full suite of pictographic icons, examples, and documentation
* can be found at: http://fortawesome.github.com/Font-Awesome/
*
* License
* -------------------------------------------------------
* - The Font Awesome font is licensed under the SIL Open Font License - http://scripts.sil.org/OFL
* - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License -
* http://opensource.org/licenses/mit-license.html
* - The Font Awesome pictograms are licensed under the CC BY 3.0 License - http://creativecommons.org/licenses/by/3.0/
* - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
* "Font Awesome by Dave Gandy - http://fortawesome.github.com/Font-Awesome"
* Contact
* -------------------------------------------------------
* Email: dave@davegandy.com
* Twitter: http://twitter.com/fortaweso_me
* Work: Lead Product Designer @ http://kyruus.com
*/
@font-face{
font-family:'FontAwesome';
src:url('/fontawesome-webfont.eot?v=3.0.1');
src:url('/fontawesome-webfont.eot?#iefix&v=3.0.1') format('embedded-opentype'),
url('/fontawesome-webfont.woff?v=3.0.1') format('woff'),
url('/fontawesome-webfont.ttf?v=3.0.1') format('truetype');
font-weight:normal;
font-style:normal }
[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0 0;background-repeat:repeat;margin-top:0}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none}[class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none}a [class^="icon-"],a [class*=" icon-"]{display:inline-block}.icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em}.btn [class^="icon-"],.nav [class^="icon-"],.btn [class*=" icon-"],.nav [class*=" icon-"]{display:inline}.btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em}.btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block}.nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em}li [class^="icon-"],.nav li [class^="icon-"],li [class*=" icon-"],.nav li [class*=" icon-"]{display:inline-block;width:1.25em;text-align:center}li [class^="icon-"].icon-large,.nav li [class^="icon-"].icon-large,li [class*=" icon-"].icon-large,.nav li [class*=" icon-"].icon-large{width:1.5625em}ul.icons{list-style-type:none;text-indent:-0.75em}ul.icons li [class^="icon-"],ul.icons li [class*=" icon-"]{width:.75em}.icon-muted{color:#eee}.icon-border{border:solid 1px #eee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.icon-2x{font-size:2em}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.icon-3x{font-size:3em}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.icon-4x{font-size:4em}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.pull-right{float:right}.pull-left{float:left}[class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em}[class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em}.btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em}.btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em}.btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em}.btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em}.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em}.icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}@-moz-document url-prefix(){.icon-spin{height:.9em}.btn .icon-spin{height:auto}.icon-spin.icon-large{height:1.25em}.btn .icon-spin.icon-large{height:.75em}}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content:"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{content:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content:"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wrench:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope-alt:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-lightbulb:before{content:"\f0eb"}.icon-exchange:before{content:"\f0ec"}.icon-cloud-download:before{content:"\f0ed"}.icon-cloud-upload:before{content:"\f0ee"}.icon-user-md:before{content:"\f0f0"}.icon-stethoscope:before{content:"\f0f1"}.icon-suitcase:before{content:"\f0f2"}.icon-bell-alt:before{content:"\f0f3"}.icon-coffee:before{content:"\f0f4"}.icon-food:before{content:"\f0f5"}.icon-file-alt:before{content:"\f0f6"}.icon-building:before{content:"\f0f7"}.icon-hospital:before{content:"\f0f8"}.icon-ambulance:before{content:"\f0f9"}.icon-medkit:before{content:"\f0fa"}.icon-fighter-jet:before{content:"\f0fb"}.icon-beer:before{content:"\f0fc"}.icon-h-sign:before{content:"\f0fd"}.icon-plus-sign-alt:before{content:"\f0fe"}.icon-double-angle-left:before{content:"\f100"}.icon-double-angle-right:before{content:"\f101"}.icon-double-angle-up:before{content:"\f102"}.icon-double-angle-down:before{content:"\f103"}.icon-angle-left:before{content:"\f104"}.icon-angle-right:before{content:"\f105"}.icon-angle-up:before{content:"\f106"}.icon-angle-down:before{content:"\f107"}.icon-desktop:before{content:"\f108"}.icon-laptop:before{content:"\f109"}.icon-tablet:before{content:"\f10a"}.icon-mobile-phone:before{content:"\f10b"}.icon-circle-blank:before{content:"\f10c"}.icon-quote-left:before{content:"\f10d"}.icon-quote-right:before{content:"\f10e"}.icon-spinner:before{content:"\f110"}.icon-circle:before{content:"\f111"}.icon-reply:before{content:"\f112"}.icon-github-alt:before{content:"\f113"}.icon-folder-close-alt:before{content:"\f114"}.icon-folder-open-alt:before{content:"\f115"}
@@ fontawesome-webfont.eot (base64)
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