Browse files

Added news and music control, rearranged UI

  • Loading branch information...
1 parent e41705a commit fa5794a31aa15be471046bc81d0d6f725f5ae6ff superatrain committed Jun 10, 2012
View
8 Gemfile
@@ -33,3 +33,11 @@ gem "padrino-assets", :git => "https://github.com/D1plo1d/padrino-assets.git"
# Weather plugin
gem "yahoo_weatherman", "~> 1.1.5"
+#For config, etc:
+gem "sequel", "~> 3.36.1"
+gem "sqlite3", "~> 1.3.6"
+gem "simple-rss", "~> 1.2.3"
+gem "sanitize", "~> 2.0.3"
+gem "json", "~> 1.6.5"
+gem "vlcrc", "~> 0.1.15"
+
View
14 Gemfile.lock
@@ -94,6 +94,10 @@ GEM
rack-protection (1.2.0)
rack
rake (0.9.2.2)
+ sanitize (2.0.3)
+ nokogiri (>= 1.4.4, < 1.6)
+ sequel (3.36.1)
+ simple-rss (1.2.3)
sinatra (1.3.2)
rack (~> 1.3, >= 1.3.6)
rack-protection (~> 1.2)
@@ -105,6 +109,7 @@ GEM
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
+ sqlite3 (1.3.6)
therubyracer (0.9.10)
libv8 (~> 3.3.10)
thin (1.3.1)
@@ -116,8 +121,11 @@ GEM
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
+ trollop (1.16.2)
url_mount (0.2.1)
rack
+ vlcrc (0.1.15)
+ trollop (~> 1.16.2)
warden (1.1.1)
rack (>= 1.0)
yahoo_weatherman (1.1.5)
@@ -128,13 +136,19 @@ PLATFORMS
DEPENDENCIES
eventmachine (~> 1.0.0.beta.4)
+ json (~> 1.6.5)
padrino (= 0.10.6.c)
padrino-assets!
padrino-contrib
padrino-warden
rack-sprockets!
rake
+ sanitize (~> 2.0.3)
+ sequel (~> 3.36.1)
+ simple-rss (~> 1.2.3)
sinatra-flash
sprockets (>= 2.0)
+ sqlite3 (~> 1.3.6)
thin
+ vlcrc (~> 0.1.15)
yahoo_weatherman (~> 1.1.5)
View
3 app/app.rb
@@ -3,4 +3,7 @@ class App < Padrino::Application
register Padrino::Mailer
register Padrino::Helpers
register Padrino::Assets
+ register Padrino::Cache
+ enable :caching
+
end
View
42 app/controllers/main-site-controller.rb
@@ -5,20 +5,50 @@
render :index
end
- get "/play" do
- "Play"
+
+ get "/streamlist" do
+ "#{stream_list.to_json}"
+ end
+
+
+ get "/add_stream" do
+ get_vlc.playlist_add(params[:source]);
+ ""
+ end
+
+ get "/now_playing" do
+ resp = get_vlc.now_playing;
+ "#{resp}"
end
- get "/pause" do
- "Pause"
+ get "/is_playing" do
+ resp = get_vlc.playing?;
+ "#{resp}"
+ end
+
+ get "/play" do
+ get_vlc.play;
+ "";
end
get "/stop" do
- "Stop"
+ get_vlc.stop;
+ "";
+ end
+
+ get "/set_volume" do
+ get_vlc.set_volume(params[:volume]);
+ ""
+ end
+
+ get "/news", :cache => true do
+ expires_in 300 # update every 5 minutes min...
+ "#{getAllArticles.to_json}";
end
# Passes weather data via json
- get "/weather" do
+ get "/weather", :cache => true do
+ expires_in 300 # Updates every 5 minutes min
"{\"current\":
{\"icon\":\"#{show_weather_icon_current}\",
\"temp\":\"#{weather_temp_current}\",
View
8 app/css/app.sass
@@ -100,7 +100,9 @@ div.row.music-player
p
font-size: 170%
color: #777
-
+
+.newshidden
+ display: none
.streetcars
text-align: center
@@ -124,4 +126,6 @@ div.row.music-player
color: #888
text-align: center
font-size: 150%
- line-height: 32px
+ line-height: 32px
+
+
View
67 app/helpers/helpers.rb
@@ -5,6 +5,73 @@
# ...
# end
+ def get_vlc
+ @vlc = VLCControl.new;
+ @vlc
+ end
+
+ # Sen's code? from old hacktouch software. (the old 2 part ampq method)
+
+ def stream_list
+ db = Sequel.connect("sqlite://#{File.dirname(__FILE__)}/../../hacktouch.sqlite3")
+ stream_list = {}
+ db[:audio_streams].order(:name).each do |stream|
+ stream_list[stream[:name]] = stream[:url];
+ end
+ stream_list
+ end
+
+ def feed_list
+ db = Sequel.connect("sqlite://#{File.dirname(__FILE__)}/../../hacktouch.sqlite3")
+ stream_list = Array.new
+ db[:news_feeds].order(:name).each do |stream|
+ stream_list.push(stream[:url]);
+ end
+ stream_list
+ end
+
+ def refresh_feeds
+ feeds = []
+ feed_list.each do |source|
+ content = ""
+ feeds.push(SimpleRSS.parse open(source) )
+ end
+ feeds
+ end
+
+# Ugly, someone please clean this up.
+# Returns 5 articles from each source, all scrambled into a random order.
+ def getAllArticles
+ number_from_each = 5;
+ articles=Hash.new
+ total=0;
+ feeds = refresh_feeds;
+ random_order = (0..(feeds.length*number_from_each-1)).to_a.sort {rand}
+ feeds.each do |feed|
+ for i in (0..number_from_each-1)
+ logger.info "Adding article #{random_order[total]}"
+ articles["#{random_order[total]}"] = getArticle(feed.items[i],feed)
+ total+=1
+ end
+ end
+ articles
+ end
+
+ def getArticle(article,src)
+ title = Sanitize.clean(article.title);
+ source = Sanitize.clean(src.channel.title);
+ content = Sanitize.clean("#{article.description}");
+ desc = content.slice(0,150);
+ if desc.length > 147
+ desc[147..150]="..."
+ end
+ article = { "title" => title, "content" => content, "source" => source, "description" => desc };
+ article
+ end
+
+
+
+
# Chim's code
# I don't know where's the model in padrino
# So I'm adding a method into the helper which is not that great. I know.
View
96 app/helpers/vlc.rb
@@ -0,0 +1,96 @@
+class VLCControl
+
+ if system('pgrep vlc')
+ logger.info "Found VLC, using existing."
+ else
+ logger.info "Starting new vlc instance..."
+ IO.popen('vlc --intf telnet');
+ end
+
+ @@vlc=TCPSocket.new("127.0.0.1", 4212)
+ @@vlc.puts "admin"
+ @@vlc.puts "set prompt \"\""
+
+ logger.info "Connected to VLC successfully"
+
+ def initialize
+ end
+
+
+ def playlist_clear
+ exec_cmd "clear"
+ end
+
+ def pause
+ exec_cmd "pause"
+ end
+
+ def stop
+ exec_cmd "stop"
+ end
+
+ def play
+ exec_cmd "play"
+ end
+
+ # NB: Automatically starts playing.
+ def playlist_add(source)
+ exec_cmd "add #{source}"
+ end
+
+ # Volume goes from 0 to 512
+ def set_volume(level)
+ exec_cmd "volume #{level}"
+ end
+
+ def playing?
+ flush_input(@@vlc)
+ @@vlc.puts("is_playing")
+ get_plain_response.chomp
+ end
+
+ def now_playing
+ flush_input(@@vlc)
+ @@vlc.puts "get_title"
+ get_plain_response.chomp!
+ end
+
+ def flush_input(handle)
+ # flush any input left in the buffer (non-blockingly, obviously)
+ begin
+ handle.read_nonblock(4096)
+ rescue
+ end
+ end
+
+ def get_plain_response
+ # return a 'plain response' to a command, filtering out any status change messages.
+ @@vlc.readpartial(4096).each_line do |line|
+ return line if line !~ /status change/;
+ end
+ ""
+ end
+
+ def get_retval
+ re_retval = /^\S+: returned (\d+)/;
+ # capture any VLC output, then pick out the return value of the last command and discard anything else
+ vlc_output = @@vlc.readpartial(4096);
+ re_match = re_retval.match(vlc_output);
+ if(re_match) then
+ return re_match[1];
+ end
+ end
+
+ def exec_cmd(cmd)
+ flush_input(@@vlc)
+ @@vlc.puts(cmd)
+ # get_retval
+ end
+
+ def close
+ @@vlc.close
+ logger.info "Closed VLC telnet session";
+ ""
+ end
+end
+
View
98 app/js/app.js.coffee
@@ -49,7 +49,7 @@ $ ->
renderSchedule = (schedule) ->
- console.log times
+ # console.log times
# Generating nice, human readable bus times
dateStrings = for date in Object.values(schedule)[0]
@@ -79,6 +79,9 @@ $ ->
update()
+# News: Testing
+$ ->
+ updateNews()
# Weather Updates:
# Auto every 10 minutes
@@ -90,7 +93,7 @@ $ ->
#Cats
$ ->
getKitten()
- $(".draw-btn").click -> getKitten()
+ $(".draw-btn").click -> getKitten()
# Volume Control
@@ -101,6 +104,12 @@ $ ->
setVolumeLevel = (level) =>
$volumeLevelIndicator.css "width", "#{level}px"
+ real_level = level* 256 / $volume.innerWidth() ;
+ $.ajax '/set_volume',
+ type: 'GET',
+ dataType: 'html',
+ data: { 'volume': "#{Math.round(real_level)}"}
+
# The volume up and down icons turn the volume to full and mute respectively
$volumeContainer.find(".icon-volume-up").click => setVolumeLevel($volume.innerWidth())
@@ -109,40 +118,83 @@ $ ->
# Clicking the progress bar sets the volume to the clicked level
$volume.click (e) => setVolumeLevel e.offsetX
-# Music Player
-# TODO
-# $ ->
-# $("#play").click ->
-# console.log("test")
-# $.ajax '/play',
-# type: 'GET'
-# dataType: 'html'
-# success: (data, textStatus, jqXHR) ->
-# console.log(data)
-
-# Browse Music
+
+# Browse Music + Music Player
$ ->
+ playing = 0;
+ titleUpdater = ->
+ $.ajax '/is_playing',
+ type: 'GET',
+ dataType: 'html',
+ success: (data) ->
+ if data == "1"
+ playing = 1;
+
+ if playing == 1
+ $.ajax '/now_playing',
+ type: 'GET',
+ dataType: 'html',
+ success: (data) ->
+ $(".song-name").html(data)
+ else
+ $(".song-name").html("Not Playing");
+ window.setInterval titleUpdater, 10000
+
+ stream_list="";
+ $.ajax '/streamlist',
+ type: 'GET',
+ dataType: 'json',
+ success: (data) ->
+ stream_list = data
+ $.each data, (key,value) ->
+ $(".audio_streams").append("<tr><td>"+key+"</td></tr>")
+
$(".songs-list").on "click", "tr", (e) ->
- console.log e
+ console.log $(e.target).html()
+ console.log stream_list[$(e.target).html()]
$(e.delegateTarget).find("tr.selected").removeClass("selected")
$(e.currentTarget).addClass("selected")
+ # Load new Stream instantly.
+ $.ajax '/add_stream',
+ type: 'GET',
+ data: {'source': stream_list[$(e.target).html()]},
+ dataType: 'html'
+ success: (data) ->
+ console.log(data)
+ $(".song-name").html("Loading...")
+
+# Music Controls:
+
+ $("#play").click ->
+ $.ajax '/play',
+ type: 'GET',
+ dataType: 'html'
+ $(".song-name").html("Loading...")
+
+ $("#stop").click ->
+ $.ajax '/stop',
+ type: 'GET',
+ dataType: 'html'
+ $(".song-name").html("Not Playing");
# Navigation
$ ->
- $(".home-btn").click -> $(".pages").attr "class", "pages show-page-0"
- $(".page-0 .buttons .btn").click (e) ->
- pageId = $(".page-0 .buttons .btn").index(e.target) + 1
- console.log(pageId)
- $(".pages").attr("class", "pages show-page-#{pageId}")
+ num_pages=7
+ $(".buttons .btn").click (e) ->
+ if $(".buttons .btn").index(e.target) > -1
+ pageId = $(".buttons .btn").index(e.target) % num_pages
+ console.log(pageId)
+ $(".pages").attr("class", "pages show-page-#{pageId}")
# News
$ ->
$newsModal = $('#newsModal').modal("hide")
$(".article").on "click", "a.news-more", (e) ->
title = $(e.delegateTarget).find("h2").html()
- description = $(e.delegateTarget).data("content")
- $newsModal.find("h3").html(title)
- $newsModal.find("p").html(description)
+ content =$(e.delegateTarget).find(".news-content").html()
+ source = $(e.delegateTarget).find(".news-source").html()
+ $newsModal.find("h3").html(title + " From: " + source)
+ $newsModal.find("p").html(content)
$newsModal.modal('show')
View
12 app/views/browse_music.haml
@@ -1,10 +1,8 @@
.row.songs-list
.span12
- %table.table.table-striped
+ %table.table.table-striped.audio_streams
%tr.headers
- %th Title
- %th Artist
- - (0..20).each do |a|
- %tr
- %td Lol Wut
- %td An Artist
+ %th Stream
+-# - (0..20).each do |a|
+-# %tr
+-# %td Unknown-Stream
View
115 app/views/home.haml
@@ -1,67 +1,48 @@
-.container
- .row.title
- .span8
- %h1
- %span.hack Hack
- %span.touch Touch
-
- %h2 *now with 100% more 2.0
- .now= # JS sets the inner html of this to the current time
-
- .row.music-player
- .span12
- %hr
- .music-title
- %i.icon-headphones
- %span.song-name Baptism - Crystal Castles
- .volume-level
- %i.icon-volume-down
- .progress.progress-success.volume-level-progress
- .bar{style: "width: 40%"}
- %i.icon-volume-up
-
- - buttons = [ {title: "Play", icon: "play"}, {title: "Pause", icon: "pause"}, {title: "Stop", icon: "stop"} ]
- - buttons.each do |b|
- .btn.btn-large{:id => b[:icon], :style => (b[:title] == "Pause")? "display: none;" : ""}
- %i{:class=>"icon-#{b[:icon]}"}
- = b[:title]
-
-
- .progress.progress-success.playback-progress
- .bar{style: "width: 20%"}
- %hr.music-hr
-
- .row.buttons
- .span12
- - pages[1..-1].each do |b|
- .btn.btn-large
- %i{:class=>"icon-#{b[:icon]}"}
- = b[:title]
- %hr
-
- .row.news
- .span12.article{:"data-content" => "A local man died of old age at the age of 60 because he was old."}
- %h2 Man Dies at the age of 90
- %p
- A local man died of old age at the age of 90 because he was old.
- %a.news-more{:href=>"#"} Read more...
- %hr
-
- .row
- .streetcars.span12
- .streetcar.north
- .icon-arrow-up
- Next North Bound Streetcar:
- .time{:id => "timen"}= #JS set
- .row
- .streetcars.span12
- .streetcar.south
- .icon-arrow-down
- Next South Bound Streetcar:
- .time{:id => "times"}= #JS set
-
- .row
- .span12
- .streetcars-updated
- Streetcars updated ~
- %span.streetcars-updated-timestamp
+.row.title
+ .span8
+ .now= # JS sets the inner html of this to the current time
+
+.row.music-player
+ .span12
+ %hr
+ .music-title
+ %i.icon-headphones
+ %span.song-name Baptism - Crystal Castles
+ .volume-level
+ %i.icon-volume-down
+ .progress.progress-success.volume-level-progress
+ .bar{style: "width: 40%"}
+ %i.icon-volume-up
+
+ - buttons = [ {title: "Play", icon: "play"}, {title: "Pause", icon: "pause"}, {title: "Stop", icon: "stop"} ]
+ - buttons.each do |b|
+ .btn.btn-large{:id => b[:icon], :style => (b[:title] == "Pause")? "display: none;" : ""}
+ %i{:class=>"icon-#{b[:icon]}"}
+ = b[:title]
+
+ %hr.music-hr
+
+.row.news
+ .span12.article
+ %h2{:id => "news-title-home"} A Man dies at 90
+ %p.news-description{:id => "news-description-home"}
+ A local man died of old age at the age of 90 because he was old.
+ %a.news-more{:href=>"#"} Read more...
+ %p.news-content.newshidden{:id => "news-content-home"}
+ A local man died of old age at the age of 90 because he was old.
+ %p.news-source.newshidden{:id => "news-source-home"}
+ Bob told me
+ %hr
+
+.row
+ .streetcars.span12
+ .streetcar.north
+ .icon-arrow-up
+ Next North Bound Streetcar:
+ .time{:id => "timen"}= #JS set
+.row
+ .streetcars.span12
+ .streetcar.south
+ .icon-arrow-down
+ Next South Bound Streetcar:
+ .time{:id => "times"}= #JS set
View
17 app/views/index.haml 100755 → 100644
@@ -1,21 +1,22 @@
- pages = [ {title: "Home"}, {title: "Browse Music", icon: "headphones"}, {title: "Door Logs", icon: "th-list"}, {title: "News", icon: "inbox"}, {title: "Weather Report", icon: "bar-chart"}, {title: "Street Cars", icon: "road"}, {title: "Cats", icon: "github-sign"} ]
.pages.show-page-0
- %div{:class => "page-0"}
- = haml :home, locals: {pages: pages}, layout: false
-
- - pages[1..-1].each_with_index do |page, index|
- %div{:class => "page-#{index+1}"}
+ - pages.each_with_index do |page, index|
+ %div{:class => "page-#{index}"}
.container
.row.title
.span12
%h1
%i{:class => "icon-#{page[:icon]}"}
%span.touch= page[:title]
= haml page[:title].downcase.gsub(" ", "_").to_sym, layout: false
- .row
+ %hr
+ .row.buttons
.span12
- .btn.btn-primary.btn-large.pull-right.home-btn Back to the other stuffs
+ - pages.each do |b|
+ .btn.btn-large
+ %i{:class=>"icon-#{b[:icon]}"}
+ = b[:title]
.modal.hide.fade#newsModal
- = haml :"modals/news_article", layout: false
+ = haml :"modals/news_article", layout: false
View
16 app/views/news.haml 100755 → 100644
@@ -1,10 +1,14 @@
.row.songs-list
.span12
- %table.table.table-striped
- - (0..4).each do |a|
- %tr.article{:"data-content" => "A local man died of old age at the age of 60 because he was old."}
+ %table.table.table-striped.news-table
+ - (0..(feed_list.length*5 - 1)).each do |a|
+ %tr.article
%td
- %h2 A Man dies at 90
- %p
+ %h2{:id => "news-title-#{a}"} A Man dies at 90
+ %p.news-description{:id => "news-description-#{a}"}
A local man died of old age at the age of 90 because he was old.
- %a.news-more{:href=>"#"} Read more...
+ %a.news-more{:href=>"#"} Read more...
+ %p.news-content.newshidden{:id => "news-content-#{a}"}
+ A local man died of old age at the age of 60 because he was old.
+ %p.news-source.newshidden{:id => "news-source-#{a}"}
+ Bob told me
View
BIN hacktouch.sqlite3
Binary file not shown.
View
32 lib/js/news.js
@@ -0,0 +1,32 @@
+// AJAX call to update the news
+function updateNews() {
+$.ajax({
+ type: "GET",
+ url: "/news",
+ success: function(data) {
+ obj = jQuery.parseJSON(data);
+ //console.log(obj);
+ for (var id in obj)
+ if (obj.hasOwnProperty(id))
+ for (var type in obj[id])
+ if (obj[id].hasOwnProperty(type))
+ {
+ //console.log("news-"+type+"-"+id+" = "+ obj[id][type]);
+ try {
+ document.getElementById("news-"+type+"-"+id).innerHTML = obj[id][type];
+ }catch(err) {
+ // console.log(err)
+ }
+ if (id == 0)
+ try {
+ document.getElementById("news-"+type+"-home").innerHTML = obj[id][type];
+ }catch(err) {
+ // console.log(err)
+ }
+ }
+
+
+ }
+ });
+ }
+

0 comments on commit fa5794a

Please sign in to comment.