The player is playing!
This commit is contained in:
		
							parent
							
								
									43422624f1
								
							
						
					
					
						commit
						9f770892f8
					
				
							
								
								
									
										25
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								Gemfile
									
									
									
									
									
								
							@ -2,30 +2,31 @@ source :rubygems
 | 
			
		||||
 | 
			
		||||
gem "rails", "3.2.8"
 | 
			
		||||
gem "pg"
 | 
			
		||||
gem "thin"
 | 
			
		||||
 | 
			
		||||
group :assets do
 | 
			
		||||
  gem "sass-rails",   "~> 3.2.3"
 | 
			
		||||
  gem "coffee-rails", "~> 3.2.1"
 | 
			
		||||
 | 
			
		||||
  gem "therubyracer", platforms: :ruby
 | 
			
		||||
  gem "hogan_assets"
 | 
			
		||||
 | 
			
		||||
  gem "uglifier", ">= 1.0.3"
 | 
			
		||||
 | 
			
		||||
  gem "jquery-rails"
 | 
			
		||||
  gem "rails-backbone"
 | 
			
		||||
  gem "hogan_assets"
 | 
			
		||||
  gem "bourbon"
 | 
			
		||||
  gem "bootstrap-sass", "~> 2.0.4.0"
 | 
			
		||||
  gem "soundmanager-rails"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
gem "jquery-rails"
 | 
			
		||||
group :development do
 | 
			
		||||
  gem "awesome_print", require: "ap"
 | 
			
		||||
 | 
			
		||||
  # Deploy with Capistrano
 | 
			
		||||
  gem "capistrano"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# To use Jbuilder templates for JSON
 | 
			
		||||
gem "jbuilder"
 | 
			
		||||
 | 
			
		||||
gem "thin"
 | 
			
		||||
 | 
			
		||||
# Deploy with Capistrano
 | 
			
		||||
gem "capistrano"
 | 
			
		||||
 | 
			
		||||
gem "robbie", path: "../robbie"
 | 
			
		||||
gem "beatparser", path: "../beatparser"
 | 
			
		||||
gem "rails-backbone"
 | 
			
		||||
gem "eco"
 | 
			
		||||
gem 'bootstrap-sass', '~> 2.0.4.0'
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Gemfile.lock
									
									
									
									
									
								
							@ -44,6 +44,7 @@ GEM
 | 
			
		||||
      i18n (~> 0.6)
 | 
			
		||||
      multi_json (~> 1.0)
 | 
			
		||||
    arel (3.0.2)
 | 
			
		||||
    awesome_print (1.0.2)
 | 
			
		||||
    blankslate (2.1.2.4)
 | 
			
		||||
    bootstrap-sass (2.0.4.0)
 | 
			
		||||
    bourbon (2.1.1)
 | 
			
		||||
@ -63,11 +64,6 @@ GEM
 | 
			
		||||
      execjs
 | 
			
		||||
    coffee-script-source (1.3.3)
 | 
			
		||||
    daemons (1.1.9)
 | 
			
		||||
    eco (1.0.0)
 | 
			
		||||
      coffee-script
 | 
			
		||||
      eco-source
 | 
			
		||||
      execjs
 | 
			
		||||
    eco-source (1.1.0.rc.1)
 | 
			
		||||
    ejs (1.0.0)
 | 
			
		||||
    erubis (2.7.0)
 | 
			
		||||
    eventmachine (0.12.10)
 | 
			
		||||
@ -148,6 +144,7 @@ GEM
 | 
			
		||||
      railties (~> 3.2.0)
 | 
			
		||||
      sass (>= 3.1.10)
 | 
			
		||||
      tilt (~> 1.3)
 | 
			
		||||
    soundmanager-rails (0.1.1)
 | 
			
		||||
    sprockets (2.1.3)
 | 
			
		||||
      hike (~> 1.2)
 | 
			
		||||
      rack (~> 1.0)
 | 
			
		||||
@ -172,12 +169,12 @@ PLATFORMS
 | 
			
		||||
  ruby
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES
 | 
			
		||||
  awesome_print
 | 
			
		||||
  beatparser!
 | 
			
		||||
  bootstrap-sass (~> 2.0.4.0)
 | 
			
		||||
  bourbon
 | 
			
		||||
  capistrano
 | 
			
		||||
  coffee-rails (~> 3.2.1)
 | 
			
		||||
  eco
 | 
			
		||||
  hogan_assets
 | 
			
		||||
  jbuilder
 | 
			
		||||
  jquery-rails
 | 
			
		||||
@ -186,6 +183,7 @@ DEPENDENCIES
 | 
			
		||||
  rails-backbone
 | 
			
		||||
  robbie!
 | 
			
		||||
  sass-rails (~> 3.2.3)
 | 
			
		||||
  soundmanager-rails
 | 
			
		||||
  therubyracer
 | 
			
		||||
  thin
 | 
			
		||||
  uglifier (>= 1.0.3)
 | 
			
		||||
 | 
			
		||||
@ -1,18 +1,8 @@
 | 
			
		||||
// This is a manifest file that'll be compiled into application.js, which will include all the files
 | 
			
		||||
// listed below.
 | 
			
		||||
//
 | 
			
		||||
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
 | 
			
		||||
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
 | 
			
		||||
//
 | 
			
		||||
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
 | 
			
		||||
// the compiled file.
 | 
			
		||||
//
 | 
			
		||||
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
 | 
			
		||||
// GO AFTER THE REQUIRES BELOW.
 | 
			
		||||
//
 | 
			
		||||
//= require jquery
 | 
			
		||||
//= require jquery_ujs
 | 
			
		||||
//= require jquery.autocomplete
 | 
			
		||||
//= require soundmanager
 | 
			
		||||
//= require vk_music
 | 
			
		||||
//= require mustache
 | 
			
		||||
//= require hogan
 | 
			
		||||
//= require underscore
 | 
			
		||||
@ -20,5 +10,6 @@
 | 
			
		||||
//= require backbone_rails_sync
 | 
			
		||||
//= require backbone_datalink
 | 
			
		||||
//= require backbone/beat_haven
 | 
			
		||||
//= require bootstrap-dropdown
 | 
			
		||||
//= require_tree .
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,10 @@
 | 
			
		||||
$ ->
 | 
			
		||||
  $(".navbar-search input").focus ->
 | 
			
		||||
    $(this).animate(width: 249)
 | 
			
		||||
    $(".player").animate(width: 408)
 | 
			
		||||
    $(".player").animate(width: 368)
 | 
			
		||||
  $(".navbar-search input").blur ->
 | 
			
		||||
    $(this).animate(width: 99)
 | 
			
		||||
    $(".player").animate(width: 558)
 | 
			
		||||
    $(".player").animate(width: 518)
 | 
			
		||||
 | 
			
		||||
  window.desired = $(".navbar-search input").autocomplete
 | 
			
		||||
    serviceUrl: "/api/search/complete"
 | 
			
		||||
 | 
			
		||||
@ -9,24 +9,32 @@ window.BeatHaven =
 | 
			
		||||
  Collections: {}
 | 
			
		||||
  Routers: {}
 | 
			
		||||
  Views: {}
 | 
			
		||||
  player: null
 | 
			
		||||
 | 
			
		||||
  Player: null
 | 
			
		||||
  User: null
 | 
			
		||||
 | 
			
		||||
  init: ->
 | 
			
		||||
    new BeatHaven.Routers.Artist()
 | 
			
		||||
    new BeatHaven.Routers.Album()
 | 
			
		||||
    new BeatHaven.Routers.Search()
 | 
			
		||||
    @player = new BeatHaven.Models.Player()
 | 
			
		||||
    @Player = new BeatHaven.Models.Player()
 | 
			
		||||
    @User = new BeatHaven.Models.User()
 | 
			
		||||
    @VK = new BeatHaven.Models.VK()
 | 
			
		||||
 | 
			
		||||
    @VK.init()
 | 
			
		||||
 | 
			
		||||
    Backbone.history.start(pushState: true);
 | 
			
		||||
    $("a").live "click", (e) ->
 | 
			
		||||
      if $(this).attr("href").substr(0, 1) == "/"
 | 
			
		||||
        e.preventDefault()
 | 
			
		||||
        Backbone.history.navigate($(this).attr("href"), true)
 | 
			
		||||
        return false
 | 
			
		||||
      else
 | 
			
		||||
        alert "Window close attempt!"
 | 
			
		||||
        return false
 | 
			
		||||
      true
 | 
			
		||||
      false
 | 
			
		||||
 | 
			
		||||
  log: (data) ->
 | 
			
		||||
    console.log data
 | 
			
		||||
 | 
			
		||||
$ ->
 | 
			
		||||
  BeatHaven.init()
 | 
			
		||||
 | 
			
		||||
# Setup shortcut
 | 
			
		||||
window.BH = window.BeatHaven
 | 
			
		||||
 | 
			
		||||
@ -2,10 +2,63 @@ class BeatHaven.Models.Player extends Backbone.Model
 | 
			
		||||
  playlist_on: false
 | 
			
		||||
  playlist: null
 | 
			
		||||
  tracks: null
 | 
			
		||||
  current_track: null
 | 
			
		||||
 | 
			
		||||
  initialize: ->
 | 
			
		||||
    @playlist = new BeatHaven.Collections.Tracklist()
 | 
			
		||||
    @tracks = new BeatHaven.Collections.Tracklist()
 | 
			
		||||
 | 
			
		||||
  play: (track) ->
 | 
			
		||||
    unless track?
 | 
			
		||||
      if @current_track?
 | 
			
		||||
        @current_track.get("sm_obj").resume()
 | 
			
		||||
      else
 | 
			
		||||
        this.play_something()
 | 
			
		||||
    else
 | 
			
		||||
      if @current_track?
 | 
			
		||||
        @current_track.get("sm_obj").stop()
 | 
			
		||||
        $(".player .progress-bar .bar").css(width: 0)
 | 
			
		||||
      @current_track = track
 | 
			
		||||
      @current_track.get("sm_obj").play()
 | 
			
		||||
      $(".player .controls .play").css(display: "none")
 | 
			
		||||
      $(".player .controls .pause").css(display: "inline-block")
 | 
			
		||||
 | 
			
		||||
  pause: ->
 | 
			
		||||
    return false unless @current_track?
 | 
			
		||||
    @current_track.get("sm_obj").pause()
 | 
			
		||||
    $(".player .controls .play").css(display: "inline-block")
 | 
			
		||||
    $(".player .controls .pause").css(display: "none")
 | 
			
		||||
 | 
			
		||||
  next: ->
 | 
			
		||||
    return false unless @current_track?
 | 
			
		||||
    if @playlist_on
 | 
			
		||||
      # not implemented
 | 
			
		||||
    else
 | 
			
		||||
      nodes = @current_track.node().next()
 | 
			
		||||
      return false unless nodes.length == 1
 | 
			
		||||
      @tracks.get(parseInt($(nodes[0]).data("id"), 10)).play()
 | 
			
		||||
 | 
			
		||||
  prev: ->
 | 
			
		||||
    return false unless @current_track?
 | 
			
		||||
    if @playlist_on
 | 
			
		||||
      # not implemented
 | 
			
		||||
    else
 | 
			
		||||
      nodes = @current_track.node().prev()
 | 
			
		||||
      return false unless nodes.length == 1
 | 
			
		||||
      @tracks.get(parseInt($(nodes[0]).data("id"), 10)).play()
 | 
			
		||||
 | 
			
		||||
  play_something: ->
 | 
			
		||||
    nodes = $(".artist-page .tracks li[data-id]")
 | 
			
		||||
    return false unless nodes.length > 0
 | 
			
		||||
    @tracks.get(parseInt($(nodes[0]).data("id"), 10)).play()
 | 
			
		||||
 | 
			
		||||
  update_title: (params) ->
 | 
			
		||||
    $(".player .progress-bar .title").html("#{params.artists.join(', ')} — #{params.track}")
 | 
			
		||||
 | 
			
		||||
  update_buffer_bar: (event) ->
 | 
			
		||||
    false
 | 
			
		||||
 | 
			
		||||
  update_progress_bar: (obj) ->
 | 
			
		||||
    percent = obj.position / obj.duration * 100
 | 
			
		||||
    $(".player .progress-bar .bar").css(width: "#{percent}%")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,43 @@
 | 
			
		||||
class BeatHaven.Models.Track extends Backbone.Model
 | 
			
		||||
 | 
			
		||||
  play: ->
 | 
			
		||||
    BeatHaven.player.update_title(
 | 
			
		||||
    if @.get("sm_obj")?
 | 
			
		||||
      this.start()
 | 
			
		||||
    else
 | 
			
		||||
      this.find_and_start()
 | 
			
		||||
 | 
			
		||||
  start: ->
 | 
			
		||||
    BH.Player.update_title(
 | 
			
		||||
      artists: @.get("artists")
 | 
			
		||||
      track: @.get("title")
 | 
			
		||||
    )
 | 
			
		||||
    unless @.get("sm_obj")?
 | 
			
		||||
      this.add_to_library(autoload: true, autoplay: false)
 | 
			
		||||
    BH.Player.play(this)
 | 
			
		||||
    $(".artist-page .tracks li[data-id]").removeClass("now-playing")
 | 
			
		||||
    this.node().addClass("now-playing")
 | 
			
		||||
 | 
			
		||||
  find_and_start: ->
 | 
			
		||||
    self = this
 | 
			
		||||
    BH.VK.Music.search @.get("artists")[0], @.get("title"), @.get("length"), (url) ->
 | 
			
		||||
      self.set(url: url)
 | 
			
		||||
      self.start()
 | 
			
		||||
 | 
			
		||||
  add_to_library: (params) ->
 | 
			
		||||
    obj = soundManager.createSound
 | 
			
		||||
      id: @.get("id")
 | 
			
		||||
      url: @.get("url")
 | 
			
		||||
      autoLoad: params.autoload
 | 
			
		||||
      autoPlay: params.autoplay
 | 
			
		||||
      whileloading: ->
 | 
			
		||||
        BH.Player.update_buffer_bar(this)
 | 
			
		||||
      whileplaying: ->
 | 
			
		||||
        BH.Player.update_progress_bar(this)
 | 
			
		||||
      onfinish: ->
 | 
			
		||||
        BH.Player.next()
 | 
			
		||||
      ondataerror: ->
 | 
			
		||||
        BH.Player.next()
 | 
			
		||||
    @.set("sm_obj", obj)
 | 
			
		||||
 | 
			
		||||
  node: ->
 | 
			
		||||
    $(".artist-page .tracks li[data-id='#{@.get("id")}']")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										27
									
								
								app/assets/javascripts/backbone/models/user.js.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								app/assets/javascripts/backbone/models/user.js.coffee
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
class BeatHaven.Models.User extends Backbone.Model
 | 
			
		||||
 | 
			
		||||
  auth: ->
 | 
			
		||||
    BH.log "Authenticating user ..."
 | 
			
		||||
    this.query "/api/session/auth", {}, (response) ->
 | 
			
		||||
      if response.error?
 | 
			
		||||
        # report error
 | 
			
		||||
      else
 | 
			
		||||
        BH.User.set(JSON.parse(response.user))
 | 
			
		||||
        if response.is_newbie
 | 
			
		||||
          BH.log "Requesting user tracks from Vkontakte ..."
 | 
			
		||||
          # BH.VK.set_favorites()
 | 
			
		||||
 | 
			
		||||
  query: (path, params, callback) ->
 | 
			
		||||
    query_params = $.extend {}, @.get("vk_session"), params
 | 
			
		||||
    query_params.authenticity_token = $('meta[name="csrf-token"]').attr("content")
 | 
			
		||||
    $.post path, query_params, callback
 | 
			
		||||
    false
 | 
			
		||||
 | 
			
		||||
  set_favorites: (tracks) ->
 | 
			
		||||
    BH.log tracks
 | 
			
		||||
    BH.log "Sending your Vkontakte media collection to BeatHaven ..."
 | 
			
		||||
    this.query "/user/set_first_favorites", tracks: tracks, (response) ->
 | 
			
		||||
      if response.error?
 | 
			
		||||
        BH.log "Got error: #{response.error}"
 | 
			
		||||
      else
 | 
			
		||||
        BH.log "We believe your favorite artists are #{response.join(', ')}"
 | 
			
		||||
							
								
								
									
										43
									
								
								app/assets/javascripts/backbone/models/vk.js.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/assets/javascripts/backbone/models/vk.js.coffee
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
class BeatHaven.Models.VK extends Backbone.Model
 | 
			
		||||
 | 
			
		||||
  session_length: 3600 # seconds
 | 
			
		||||
  Music: null
 | 
			
		||||
 | 
			
		||||
  popup: ->
 | 
			
		||||
    alert(1)
 | 
			
		||||
 | 
			
		||||
  init: ->
 | 
			
		||||
    @Music = new VkMusic()
 | 
			
		||||
    BH.log "Initializing Vkontakte API ..."
 | 
			
		||||
    window.VK.init(apiId: VK_APP_ID)
 | 
			
		||||
    BH.VK.auth()
 | 
			
		||||
    # VK.Widgets.Like("vk-like", {type: "mini", height: 20, pageUrl: "http://beathaven.org/", text: "Like"})
 | 
			
		||||
 | 
			
		||||
  auth: ->
 | 
			
		||||
    BH.log "Requesting new Vkontakte session ..."
 | 
			
		||||
    window.VK.Auth.getLoginStatus (response) ->
 | 
			
		||||
      BH.VK.auth_info(response)
 | 
			
		||||
      false
 | 
			
		||||
    , 8
 | 
			
		||||
    false
 | 
			
		||||
 | 
			
		||||
  auth_info: (response) ->
 | 
			
		||||
    if typeof response isnt "undefined" and response.session?
 | 
			
		||||
      BH.User.set(vk_session: response.session)
 | 
			
		||||
      BH.User.auth()
 | 
			
		||||
 | 
			
		||||
      if response.session.expire?
 | 
			
		||||
        expire_in = response.session.expire * 1000 - new Date().getTime()
 | 
			
		||||
        # time is an illusion...
 | 
			
		||||
        expire_in = @session_length * 1000
 | 
			
		||||
        BH.log "Session will expire in #{Math.round(expire_in / 1000)} seconds"
 | 
			
		||||
        setTimeout ->
 | 
			
		||||
          BH.log "Session expired"
 | 
			
		||||
          BH.VK.auth()
 | 
			
		||||
        , expire_in + 1000
 | 
			
		||||
    else
 | 
			
		||||
      BH.log "Not authorized"
 | 
			
		||||
 | 
			
		||||
  set_favorites: ->
 | 
			
		||||
    window.VK.Api.call "audio.get", uid: BH.User.vk_id(), (response) ->
 | 
			
		||||
      BH.User.set_favorites(response.response)
 | 
			
		||||
@ -10,6 +10,7 @@
 | 
			
		||||
    {{#album_tracks}}
 | 
			
		||||
      <li data-id="{{track_id}}">
 | 
			
		||||
        <a href="" class="btn btn-round track-play"><i class="icon-play"></i></a>
 | 
			
		||||
        <a href="" class="btn btn-round track-pause"><i class="icon-pause"></i></a>
 | 
			
		||||
        <div class="title">
 | 
			
		||||
          <div class="inner">
 | 
			
		||||
            <a href="{{track_url}}" class="track-link">{{track_title}}</a>
 | 
			
		||||
 | 
			
		||||
@ -23,6 +23,7 @@
 | 
			
		||||
      {{#album_tracks}}
 | 
			
		||||
        <li data-id="{{track_id}}">
 | 
			
		||||
          <a href="" class="btn btn-round track-play"><i class="icon-play"></i></a>
 | 
			
		||||
          <a href="" class="btn btn-round track-pause"><i class="icon-pause"></i></a>
 | 
			
		||||
          <div class="title">
 | 
			
		||||
            <div class="inner">
 | 
			
		||||
              <a href="{{track_url}}" class="track-link">{{track_title}}</a>
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,6 @@ class BeatHaven.Views.AlbumShow extends Backbone.View
 | 
			
		||||
    if typeof @model.get("album_tracks") != "undefined"
 | 
			
		||||
      for track_info in @model.get("album_tracks")
 | 
			
		||||
        track = new BeatHaven.Models.Track(track_info.meta)
 | 
			
		||||
        BeatHaven.player.tracks.push(track)
 | 
			
		||||
        BeatHaven.Player.tracks.push(track)
 | 
			
		||||
      $(@el).html(@template.render(@model.toJSON()))
 | 
			
		||||
    this
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,6 @@ class BeatHaven.Views.ArtistShow extends Backbone.View
 | 
			
		||||
      for album_info in @model.get("artist_albums")
 | 
			
		||||
        for track_info in album_info.album_tracks
 | 
			
		||||
          track = new BeatHaven.Models.Track(track_info.meta)
 | 
			
		||||
          BeatHaven.player.tracks.push(track)
 | 
			
		||||
          BeatHaven.Player.tracks.push(track)
 | 
			
		||||
      $(@el).html(@template.render(@model.toJSON()))
 | 
			
		||||
    this
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								app/assets/javascripts/bindings/auth.js.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/assets/javascripts/bindings/auth.js.coffee
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
$ ->
 | 
			
		||||
  $(".auth a").bind "mouseup", (e) ->
 | 
			
		||||
    e.preventDefault()
 | 
			
		||||
    if BeatHaven.authenticated
 | 
			
		||||
      alert("auth ok!!!!!")
 | 
			
		||||
    else
 | 
			
		||||
      BeatHaven.VK.popup()
 | 
			
		||||
							
								
								
									
										9
									
								
								app/assets/javascripts/bindings/player.js.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/assets/javascripts/bindings/player.js.coffee
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
$ ->
 | 
			
		||||
  $(".player .controls .prev").live "click", (e) ->
 | 
			
		||||
    BH.Player.prev()
 | 
			
		||||
  $(".player .controls .play").live "click", (e) ->
 | 
			
		||||
    BH.Player.play()
 | 
			
		||||
  $(".player .controls .pause").live "click", (e) ->
 | 
			
		||||
    BH.Player.pause()
 | 
			
		||||
  $(".player .controls .next").live "click", (e) ->
 | 
			
		||||
    BH.Player.next()
 | 
			
		||||
							
								
								
									
										5
									
								
								app/assets/javascripts/bindings/track.js.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/assets/javascripts/bindings/track.js.coffee
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
$ ->
 | 
			
		||||
  $(".track-play").live "click", (e) ->
 | 
			
		||||
    e.preventDefault()
 | 
			
		||||
    id = parseInt($(this).parent().data("id"), 10)
 | 
			
		||||
    BH.Player.tracks.get(id).play()
 | 
			
		||||
@ -24,6 +24,23 @@
 | 
			
		||||
      display: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.now-playing {
 | 
			
		||||
      a {
 | 
			
		||||
        color: #126be8 !important;
 | 
			
		||||
        text-shadow: 0 0 1px rgba(255, 255, 255, .2);
 | 
			
		||||
      }
 | 
			
		||||
      .track-play {
 | 
			
		||||
        display: none;
 | 
			
		||||
      }
 | 
			
		||||
      .track-pause {
 | 
			
		||||
        display: block;
 | 
			
		||||
 | 
			
		||||
        i {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .btn-round {
 | 
			
		||||
      width: 10px;
 | 
			
		||||
      height: 22px;
 | 
			
		||||
@ -34,7 +51,7 @@
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .track-play {
 | 
			
		||||
    .track-play, .track-pause {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 3px;
 | 
			
		||||
      left: 5px;
 | 
			
		||||
@ -43,6 +60,9 @@
 | 
			
		||||
        opacity: .3;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .track-pause {
 | 
			
		||||
      display: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Track title
 | 
			
		||||
    .title {
 | 
			
		||||
@ -112,7 +132,7 @@
 | 
			
		||||
      }
 | 
			
		||||
      background-color: rgba(200, 200, 200, .3);
 | 
			
		||||
 | 
			
		||||
      .track-play i {
 | 
			
		||||
      .track-play i, .track-pause i {
 | 
			
		||||
        opacity: 1;
 | 
			
		||||
      }
 | 
			
		||||
      .track-add {
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,7 @@
 | 
			
		||||
@import "artist";
 | 
			
		||||
@import "album-track";
 | 
			
		||||
@import "player";
 | 
			
		||||
@import "auth";
 | 
			
		||||
 | 
			
		||||
@import url(http://fonts.googleapis.com/css?family=Lobster+Two:400,400italic,700);
 | 
			
		||||
@import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro);
 | 
			
		||||
@ -25,6 +26,10 @@ body {
 | 
			
		||||
  .navbar-inner {
 | 
			
		||||
    background: none;
 | 
			
		||||
    @include background-image(linear-gradient(rgba(0, 0, 0, .05) 0, rgba(0, 0, 0, .4) 100%));
 | 
			
		||||
 | 
			
		||||
    .container {
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  a.brand {
 | 
			
		||||
    margin-top: 1px;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								app/assets/stylesheets/auth.css.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/assets/stylesheets/auth.css.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
.navbar .auth {
 | 
			
		||||
  margin: 14px 10px 0 15px;
 | 
			
		||||
}
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
.player {
 | 
			
		||||
  width: 558px;
 | 
			
		||||
  width: 518px;
 | 
			
		||||
 | 
			
		||||
  .controls {
 | 
			
		||||
    float: left;
 | 
			
		||||
@ -8,6 +8,10 @@
 | 
			
		||||
    a {
 | 
			
		||||
      margin: 5px 6px 0 -9px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .pause {
 | 
			
		||||
      display: none;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .progress-bar {
 | 
			
		||||
    position: relative;
 | 
			
		||||
@ -25,6 +29,7 @@
 | 
			
		||||
 | 
			
		||||
    .bar {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      width: 0%;
 | 
			
		||||
      height: 26px;
 | 
			
		||||
      background-color: rgba(255, 255, 255, .1);
 | 
			
		||||
      @include box-shadow(inset 0 0 2px rgba(255, 255, 255, .2));
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										36
									
								
								app/controllers/api/session_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/controllers/api/session_controller.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
module Api
 | 
			
		||||
  class SessionController < ApplicationController
 | 
			
		||||
 | 
			
		||||
    def auth
 | 
			
		||||
      render json: { error: "Signature verification failed!" } unless request_valid?
 | 
			
		||||
 | 
			
		||||
      user_name = "#{params[:user][:first_name]} #{params[:user][:last_name]}"
 | 
			
		||||
 | 
			
		||||
      user = User.find_by_vk_id(params[:mid].to_i)
 | 
			
		||||
      is_newbie = false
 | 
			
		||||
      if user.nil?
 | 
			
		||||
        user = User.create(name: user_name, vk_id: params[:mid].to_i)
 | 
			
		||||
        is_newbie = true
 | 
			
		||||
      elsif user.name != user_name
 | 
			
		||||
        user.update_attributes(name: user_name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      render json: { user: user.dump_json, is_newbie: is_newbie }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
    def request_valid?
 | 
			
		||||
      %w[ expire mid secret sid sig ].map(&:to_sym).each do |key|
 | 
			
		||||
        raise "Parameter not set: #{key}" if params[key].nil?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      validation_string = %w[ expire mid secret sid ].map{ |key|
 | 
			
		||||
        "#{key}=#{params[key.to_sym]}"
 | 
			
		||||
      }.join() << BeatHaven::Application.config.api_accounts["vk"]["api_secret"]
 | 
			
		||||
 | 
			
		||||
      params[:sig] == Digest::MD5.hexdigest(validation_string)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										12
									
								
								app/models/user.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/models/user.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
class User < ActiveRecord::Base
 | 
			
		||||
  attr_accessible :lang, :name, :vk_id
 | 
			
		||||
 | 
			
		||||
  def dump_json
 | 
			
		||||
    Jbuilder.encode do |j|
 | 
			
		||||
      j.id id
 | 
			
		||||
      j.name name
 | 
			
		||||
      j.lang lang
 | 
			
		||||
      j.vk_id vk_id
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										13
									
								
								app/views/application/_player.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/views/application/_player.html.erb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
<div class="player pull-right">
 | 
			
		||||
  <div class="controls">
 | 
			
		||||
    <a href="" class="btn btn-bh-dark prev"><i class="icon-backward icon-white"></i></a>
 | 
			
		||||
    <a href="" class="btn btn-bh-dark play"><i class="icon-play icon-white"></i></a>
 | 
			
		||||
    <a href="" class="btn btn-bh-dark pause"><i class="icon-pause icon-white"></i></a>
 | 
			
		||||
    <a href="" class="btn btn-bh-dark next"><i class="icon-forward icon-white"></i></a>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="progress-bar">
 | 
			
		||||
    <div class="bar"></div>
 | 
			
		||||
    <div class="title">Waiting...</div>
 | 
			
		||||
    <div class="move-it"></div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
@ -4,7 +4,11 @@
 | 
			
		||||
  <title>BeatHaven</title>
 | 
			
		||||
  <%= stylesheet_link_tag    "application", media: "all" %>
 | 
			
		||||
  <%= javascript_include_tag "application" %>
 | 
			
		||||
  <%= javascript_include_tag "http://vkontakte.ru/js/api/openapi.js" %>
 | 
			
		||||
  <%= csrf_meta_tags %>
 | 
			
		||||
  <script type="text/javascript" charset="utf-8">
 | 
			
		||||
    window.VK_APP_ID = 2335068;
 | 
			
		||||
  </script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
 | 
			
		||||
@ -15,18 +19,10 @@
 | 
			
		||||
        <form class="navbar-search pull-left">
 | 
			
		||||
          <input type="search" placeholder="Search" class="search-query">
 | 
			
		||||
        </form>
 | 
			
		||||
        <div class="player pull-right">
 | 
			
		||||
          <div class="controls">
 | 
			
		||||
            <a href="" class="btn btn-bh-dark prev"><i class="icon-backward icon-white"></i></a>
 | 
			
		||||
            <a href="" class="btn btn-bh-dark pause"><i class="icon-pause icon-white"></i></a>
 | 
			
		||||
            <a href="" class="btn btn-bh-dark next"><i class="icon-forward icon-white"></i></a>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="progress-bar">
 | 
			
		||||
            <div class="bar" style="width: 42%"></div>
 | 
			
		||||
            <div class="title">Foo Fighters — Alone + Easy Target</div>
 | 
			
		||||
            <div class="move-it"></div>
 | 
			
		||||
          </div>
 | 
			
		||||
        <div class="auth pull-right">
 | 
			
		||||
          <a href=""><i class="icon-user icon-white"></i></a>
 | 
			
		||||
        </div>
 | 
			
		||||
        <%= render partial: "player" %>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
File.open("#{Rails.root}/config/api_keys.yml") do |file|
 | 
			
		||||
  config = YAML.load(file.read)
 | 
			
		||||
  BeatHaven::Application.config.api_accounts = config
 | 
			
		||||
 | 
			
		||||
  LastFM.api_key = config["lastfm"]["api_key"]
 | 
			
		||||
  LastFM.secret = config["lastfm"]["api_secret"]
 | 
			
		||||
@ -7,6 +7,9 @@ BeatHaven::Application.routes.draw do
 | 
			
		||||
    resources :search, only: [] do
 | 
			
		||||
      collection { get :complete; get :wtfis }
 | 
			
		||||
    end
 | 
			
		||||
    resources :session, only: [] do
 | 
			
		||||
      collection { post :auth }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  match "/:path" => "application#main", constraints: { path: /.*/ }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								db/migrate/20120901191655_create_users.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								db/migrate/20120901191655_create_users.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
class CreateUsers < ActiveRecord::Migration
 | 
			
		||||
  def change
 | 
			
		||||
    create_table :users do |t|
 | 
			
		||||
      t.string :name
 | 
			
		||||
      t.integer :vk_id
 | 
			
		||||
      t.string :lang, default: "ru"
 | 
			
		||||
 | 
			
		||||
      t.timestamps
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										10
									
								
								db/schema.rb
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								db/schema.rb
									
									
									
									
									
								
							@ -11,7 +11,7 @@
 | 
			
		||||
#
 | 
			
		||||
# It's strongly recommended to check this file into your version control system.
 | 
			
		||||
 | 
			
		||||
ActiveRecord::Schema.define(:version => 20120901111329) do
 | 
			
		||||
ActiveRecord::Schema.define(:version => 20120901191655) do
 | 
			
		||||
 | 
			
		||||
  create_table "albums", :force => true do |t|
 | 
			
		||||
    t.integer  "artist_id"
 | 
			
		||||
@ -66,4 +66,12 @@ ActiveRecord::Schema.define(:version => 20120901111329) do
 | 
			
		||||
    t.datetime "updated_at", :null => false
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "users", :force => true do |t|
 | 
			
		||||
    t.string   "name"
 | 
			
		||||
    t.integer  "vk_id"
 | 
			
		||||
    t.string   "lang",       :default => "ru"
 | 
			
		||||
    t.datetime "created_at",                   :null => false
 | 
			
		||||
    t.datetime "updated_at",                   :null => false
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										72
									
								
								vendor/assets/javascripts/vk_music.js.coffee
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								vendor/assets/javascripts/vk_music.js.coffee
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
			
		||||
###
 | 
			
		||||
 * Vkontakte (VK.com) API music search tool
 | 
			
		||||
 * https://github.com/magnolia-fan/vkontakte_music_search
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2011, Gregory Eremin
 | 
			
		||||
 * Licensed under the MIT license.
 | 
			
		||||
 * https://raw.github.com/magnolia-fan/vkontakte_music_search/master/LICENSE
 | 
			
		||||
 ###
 | 
			
		||||
 | 
			
		||||
class window.VkMusic
 | 
			
		||||
  query_results: {}
 | 
			
		||||
 | 
			
		||||
  search: (artist, track, duration, callback, return_all = false) ->
 | 
			
		||||
    query = this.prepareQuery artist, track
 | 
			
		||||
    if @query_results[query]? and not return_all
 | 
			
		||||
      callback @query_results[query]
 | 
			
		||||
    that = this
 | 
			
		||||
    VK.Api.call 'audio.search', q: query, (r) ->
 | 
			
		||||
      results = that.range r.response, artist, track, duration
 | 
			
		||||
      top_result = null
 | 
			
		||||
      if results.length > 0
 | 
			
		||||
        top_result = results[0].url
 | 
			
		||||
      that.query_results[query] = results
 | 
			
		||||
      callback if return_all then results else top_result
 | 
			
		||||
 | 
			
		||||
  range: (data, artist, track, duration) ->
 | 
			
		||||
    if typeof duration is 'string'
 | 
			
		||||
      duration = duration.split ':'
 | 
			
		||||
      duration = parseInt(duration[0], 10) * 60 + parseInt(duration[1], 10)
 | 
			
		||||
    for item, i in data
 | 
			
		||||
      if typeof item isnt 'object'
 | 
			
		||||
        continue
 | 
			
		||||
      item.score = 0
 | 
			
		||||
      item.artist = this.trim(item.artist)
 | 
			
		||||
      item.title = this.trim(item.title)
 | 
			
		||||
      score = 0
 | 
			
		||||
      if item.artist.length > 0
 | 
			
		||||
        if item.artist == artist
 | 
			
		||||
          score += 10
 | 
			
		||||
        else if item.artist.split(artist).length is 2
 | 
			
		||||
          score += 5
 | 
			
		||||
        else if item.title.split(artist).length is 2
 | 
			
		||||
          score += 4
 | 
			
		||||
      if item.artist.length > 0
 | 
			
		||||
        if item.title == track
 | 
			
		||||
          score += 10
 | 
			
		||||
        else if item.title.split(track).length is 2
 | 
			
		||||
          score += 5
 | 
			
		||||
      if duration != 0 and parseInt(item.duration, 10) == duration
 | 
			
		||||
        score += 15
 | 
			
		||||
      else
 | 
			
		||||
        delta = Math.abs parseInt(item.duration, 10) - duration
 | 
			
		||||
        score += (10 - delta) if delta < 10
 | 
			
		||||
      data[i].score = score
 | 
			
		||||
    if data.length > 0
 | 
			
		||||
      if typeof data[0] isnt 'object'
 | 
			
		||||
        data.splice(0, 1)
 | 
			
		||||
      data.sort (a, b) ->
 | 
			
		||||
        b.score - a.score
 | 
			
		||||
    data
 | 
			
		||||
 | 
			
		||||
  prepareQuery: (artist, track) ->
 | 
			
		||||
    artist+" "+track.replace(/\(.*\)/i, '').split('/')[0]
 | 
			
		||||
 | 
			
		||||
  trim: (str) ->
 | 
			
		||||
    while str.indexOf('  ') isnt -1
 | 
			
		||||
      str = str.replace('  ', ' ')
 | 
			
		||||
    if str.charAt(0) is ' '
 | 
			
		||||
      str = str.substring(1)
 | 
			
		||||
    if str.charAt(str.length - 1) is ' '
 | 
			
		||||
      str = str.substring(0, str.length - 1)
 | 
			
		||||
    str
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user