Bringing on
1
Gemfile
|
@ -6,6 +6,7 @@ gem 'rails', '3.0.8'
|
|||
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
||||
|
||||
gem 'sqlite3'
|
||||
gem 'pg'
|
||||
|
||||
# Use unicorn as the web server
|
||||
# gem 'unicorn'
|
||||
|
|
|
@ -39,6 +39,7 @@ GEM
|
|||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
mime-types (1.16)
|
||||
pg (0.11.0)
|
||||
polyglot (0.3.1)
|
||||
rack (1.2.3)
|
||||
rack-mount (0.6.14)
|
||||
|
@ -69,5 +70,6 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
pg
|
||||
rails (= 3.0.8)
|
||||
sqlite3
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
class Album < ActiveRecord::Base
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
class Artist < ActiveRecord::Base
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
class MusicBrainzArtist < ActiveRecord::Base
|
||||
|
||||
establish_connection :musicbrainz
|
||||
set_table_name 'musicbrainz.bh_artist'
|
||||
|
||||
has_many :albums, :conditions => "release_type = 1", :order => 'year ASC, id ASC'
|
||||
|
||||
def self.getByName(name)
|
||||
Artist.first(:conditions => ['name = ? AND id=credit_id', name], :order => 'rating DESC')
|
||||
end
|
||||
|
||||
def self.getLastFmAutocomplete(query)
|
||||
return nil if query.nil? or query.strip.empty?
|
||||
|
||||
json = ActiveSupport::JSON.decode(open(
|
||||
'http://www.last.fm/search/autocomplete' <<
|
||||
'?q=' << URI.escape(query)
|
||||
).read)
|
||||
return json.empty? ? nil : json
|
||||
end
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
class Track < ActiveRecord::Base
|
||||
end
|
|
@ -20,3 +20,11 @@ production:
|
|||
database: db/production.sqlite3
|
||||
pool: 5
|
||||
timeout: 5000
|
||||
|
||||
|
||||
musicbrainz:
|
||||
host: 192.168.0.128
|
||||
adapter: postgresql
|
||||
database: beathaven
|
||||
username: postgres
|
||||
password: password
|
|
@ -0,0 +1,14 @@
|
|||
class CreateArtists < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :artists do |t|
|
||||
t.string :name
|
||||
t.text :desc
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :artists
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
class CreateAlbums < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :albums do |t|
|
||||
t.string :name
|
||||
t.integer :artist_id
|
||||
t.integer :year
|
||||
t.integer :status
|
||||
t.string :pic_url
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :albums
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
class CreateTracks < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :tracks do |t|
|
||||
t.string :name
|
||||
t.integer :album_id
|
||||
t.integer :position
|
||||
t.integer :bonus
|
||||
t.integer :live
|
||||
t.integer :acoustic
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :tracks
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
# This file is auto-generated from the current state of the database. Instead
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20110613135648) do
|
||||
|
||||
create_table "albums", :force => true do |t|
|
||||
t.string "name"
|
||||
t.integer "artist_id"
|
||||
t.integer "year"
|
||||
t.integer "status"
|
||||
t.string "pic_url"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "artists", :force => true do |t|
|
||||
t.string "name"
|
||||
t.text "desc"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "tracks", :force => true do |t|
|
||||
t.string "name"
|
||||
t.integer "album_id"
|
||||
t.integer "position"
|
||||
t.integer "bonus"
|
||||
t.integer "live"
|
||||
t.integer "acoustic"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
namespace :db do
|
||||
desc 'Imports data from MusicBrainz database'
|
||||
task :import => :environment do
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
worker_processes 1;
|
||||
error_log logs/error.log debug;
|
||||
|
||||
events {
|
||||
worker_connections 256;
|
||||
}
|
||||
|
||||
http {
|
||||
default_type application/octet-stream;
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
keepalive_timeout 65;
|
||||
tcp_nodelay on;
|
||||
|
||||
gzip on;
|
||||
gzip_min_length 1100;
|
||||
gzip_buffers 4 8k;
|
||||
gzip_types text/plain;
|
||||
|
||||
upstream mongrel {
|
||||
server 127.0.0.1:3000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name bh.vim.me localhost susanna brooklyn;
|
||||
#root /Users/chez/Sites;
|
||||
#index index.html index.htm;
|
||||
|
||||
try_files $uri @mongrel;
|
||||
|
||||
location @mongrel {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
proxy_pass http://mongrel;
|
||||
}
|
||||
|
||||
include proxy.conf;
|
||||
|
||||
#error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root html;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
# Proxy download
|
||||
location ~* ^/proxy-stream/(.*?)/(.*?)/(.*?)/(.*?)/(.*) {
|
||||
# Do not allow people to mess with this location directly
|
||||
# Only internal redirects are allowed
|
||||
internal;
|
||||
|
||||
# Location-specific logging
|
||||
#access_log logs/proxy_stream.access.log debug;
|
||||
#error_log logs/proxy_stream.error.log debug;
|
||||
|
||||
# Extract download url from the request
|
||||
set $token $1;
|
||||
set $remixsid $2;
|
||||
set $remixchk $3;
|
||||
set $download_host $4;
|
||||
set $download_uri $5;
|
||||
|
||||
# Compose download url
|
||||
set $download_url http://$download_host/$download_uri;
|
||||
|
||||
# Compose cookie string
|
||||
set $cookie "remixsid=$remixsid;remixchk=$remixchk";
|
||||
|
||||
# Set download request headers
|
||||
proxy_set_header Host $download_host;
|
||||
proxy_set_header Cookie $cookie;
|
||||
proxy_set_header Referer "http://vkontakte.ru/audio?album_id=0";
|
||||
|
||||
# The next two lines could be used if your storage
|
||||
# backend does not support Content-Disposition
|
||||
# headers used to specify file name browsers use
|
||||
# when save content to the disk
|
||||
proxy_ignore_headers Cache-Control Expires;
|
||||
|
||||
|
||||
# Do not touch local disks when proxying
|
||||
# content to clients
|
||||
proxy_max_temp_file_size 0;
|
||||
|
||||
# Download the file and send it to client
|
||||
resolver 192.168.0.1;
|
||||
proxy_pass $download_url;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>BetaHaven</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/layout.css" />
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/misc.css" />
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/player.css" />
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/albums.css" />
|
||||
<script type="text/javascript" charset="utf-8" src="js/jquery.min.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/layout.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/ajax.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/pages.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/audio.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/player.js"></script>
|
||||
<script type="text/javascript" charset="windows-1251" src="http://vkontakte.ru/js/api/openapi.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/vkontakte.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- START PLAYER -->
|
||||
<div id="player-container">
|
||||
<div id="player">
|
||||
<audio id="a"></audio>
|
||||
<div class="now-playing">Jet — Black Hearts</div>
|
||||
<div class="progress">
|
||||
<div class="loaded">
|
||||
<div class="played"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<div class="prev"></div>
|
||||
<div class="play"></div>
|
||||
<div class="next"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="playlist">
|
||||
<ul class="playlist-tracks"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END PLAYER -->
|
||||
|
||||
<!-- START HEADER -->
|
||||
<div id="header-container">
|
||||
<ul id="navigation">
|
||||
<li class="logo">BeatHaven</li>
|
||||
<li>News</li>
|
||||
<li>Settings</li>
|
||||
<li>Logout</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- END HEADER -->
|
||||
|
||||
<!-- START DATA -->
|
||||
<div id="data-container">
|
||||
<a href="/Jet.json" class="data artist">Jet</a>
|
||||
</div>
|
||||
<!-- END DATA -->
|
||||
|
||||
<div id="vk_api_transport"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
/Users/chez/Sites/Progress/
|
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1003 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 19 KiB |
|
@ -0,0 +1,13 @@
|
|||
$(function(){
|
||||
$('a.data').live('click', function(){
|
||||
var button = this;
|
||||
$.get(this.href, function(data){
|
||||
data = eval('('+ data +')');
|
||||
if ($(button).hasClass('artist')) {
|
||||
Pages.renderArtist(data);
|
||||
}
|
||||
})
|
||||
return false;
|
||||
});
|
||||
$('a.data').trigger('click');
|
||||
})
|
|
@ -0,0 +1,51 @@
|
|||
var Audio = {
|
||||
|
||||
audio: null,
|
||||
tid: null,
|
||||
|
||||
init: function() {
|
||||
this.audio = document.getElementById('a');
|
||||
},
|
||||
|
||||
play: function() {
|
||||
this.audio.play();
|
||||
},
|
||||
|
||||
pause: function() {
|
||||
this.audio.pause();
|
||||
},
|
||||
|
||||
setTrack: function(url) {
|
||||
this.audio.setAttribute('src', url);
|
||||
},
|
||||
|
||||
getLoadedPercent: function() {
|
||||
try {
|
||||
return Audio.audio.buffered.end(0) / Audio.audio.duration;
|
||||
} catch(e) {}
|
||||
return 0;
|
||||
},
|
||||
|
||||
getPlayedPercent: function() {
|
||||
try {
|
||||
return Audio.audio.currentTime / Audio.audio.duration;
|
||||
} catch(e) {}
|
||||
return 0;
|
||||
},
|
||||
|
||||
setPlayedPercent: function(val) {
|
||||
if (typeof(this.audio.duration) != undefined) {
|
||||
this.audio.currentTime = Math.round(val * this.audio.duration / 100);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
startListener: function() {
|
||||
Audio.tid = window.setTimeout(Audio.startListener, 100);
|
||||
Player.updateUI(
|
||||
Audio.getLoadedPercent(),
|
||||
Audio.getPlayedPercent()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
$(function(){
|
||||
beathaven.init();
|
||||
$(window).resize(beathaven.adjustSizes)
|
||||
})
|
||||
var beathaven = {
|
||||
|
||||
init: function () {
|
||||
this.drawInterface();
|
||||
this.adjustSizes();
|
||||
},
|
||||
drawInterface: function() {
|
||||
},
|
||||
adjustSizes: function() {
|
||||
$('#data-container').height($(window).height() - $('#header-container').height());
|
||||
$('#player-container').height($(window).height());
|
||||
$('#playlist').height($(window).height() - $('#player').height());
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
var Pages = {
|
||||
|
||||
renderArtist: function(data){
|
||||
var artist_info = $('\
|
||||
<div class="artist-info">\
|
||||
<div class="pic">\
|
||||
<img src="'+ data.artist.pic +'" alt="'+ data.artist.name +'" width="250" />\
|
||||
</div>\
|
||||
<h1 class="name">'+ data.artist.name +'</h1>\
|
||||
<div class="info">\
|
||||
'+ data.artist.desc +'\
|
||||
</div>\
|
||||
</div>\
|
||||
');
|
||||
|
||||
var albums_info = $('<div class="albums"></div>');
|
||||
$.each(data.albums, function(i, album){
|
||||
var album_info = $('\
|
||||
<div class="album">\
|
||||
<h2 class="name">'+ album.name +' ('+ album.year +')</h2>\
|
||||
<div class="pic">\
|
||||
<img src="'+ album.pic +'" alt="'+ album.name +' by '+ data.artist.name +'" width="250" />\
|
||||
<div class="add-album">Add to playlist</div>\
|
||||
</div>\
|
||||
<div class="tracklist">\
|
||||
<ul>\
|
||||
</ul>\
|
||||
</div>\
|
||||
</div>\
|
||||
');
|
||||
|
||||
$.each(album.tracks.album, function(i, track){
|
||||
var track_info = $('\
|
||||
<li>\
|
||||
<span class="index">'+ (i+1) +'</span>\
|
||||
<div class="trackname">'+ track.name +'</div>\
|
||||
<div class="length">'+ track.duration +'</div>\
|
||||
</li>\
|
||||
');
|
||||
|
||||
$(album_info).find('.tracklist ul').append(track_info);
|
||||
});
|
||||
|
||||
$(albums_info).append(album_info);
|
||||
})
|
||||
|
||||
$('#data-container').html('').append(artist_info).append(albums_info);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
<div class="albums">
|
||||
<div class="album">
|
||||
<h2 class="name">Get Born</h2>
|
||||
<div class="pic">
|
||||
<img src="pics/getborn.jpg" alt="Get Born by Jet" width="250" />
|
||||
<div class="add-album">Add to playlist</div>
|
||||
</div>
|
||||
<div class="tracklist">
|
||||
<ul>
|
||||
<li>
|
||||
<div class="trackname">Last Chance</div>
|
||||
<div class="length">1:52</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="trackname">Are You Gonna Be My Girl</div>
|
||||
<div class="length">3:34</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="trackname">Rollover DJ</div>
|
||||
<div class="length">3:17</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
*/
|
|
@ -0,0 +1,59 @@
|
|||
var Player = {
|
||||
|
||||
bar_width: 290,
|
||||
|
||||
getTrackUrl: function(data) {
|
||||
|
||||
},
|
||||
|
||||
addTrack: function(artist, track, length) {
|
||||
$('.playlist-tracks').append('\
|
||||
<li id="i'+ Math.round(Math.random() * 999999) +'">\
|
||||
<div class="item">\
|
||||
<span class="title">'+ artist +' — '+ track +'</span>\
|
||||
<span class="duration">'+ length +'</span>\
|
||||
</div>\
|
||||
</li>\
|
||||
');
|
||||
},
|
||||
|
||||
setTrack: function(obj) {
|
||||
var id = $(obj).attr('id');
|
||||
var query = $(obj).find('.title').html();
|
||||
var length = $(obj).find('.duration').html();
|
||||
|
||||
$('#player .now-playing').html(query);
|
||||
$('.playlist-tracks li').removeClass('now');
|
||||
$('#'+ id).addClass('now');
|
||||
|
||||
loadTracksData(query, this.playSource);
|
||||
},
|
||||
|
||||
playSource: function(url) {
|
||||
Audio.setTrack(url);
|
||||
Audio.play();
|
||||
Audio.startListener();
|
||||
},
|
||||
|
||||
updateUI: function(buffered, played) {
|
||||
$('#player .loaded').width(Math.round(buffered * this.bar_width));
|
||||
$('#player .played').width(Math.round(played * this.bar_width));
|
||||
}
|
||||
}
|
||||
|
||||
$('.add-album').live('click', function() {
|
||||
var artist = $(this).parent().parent().parent().parent().find('.artist-info .name').html();
|
||||
$(this).parent().parent().find('.tracklist li').each(function(i, item){
|
||||
var track_name = $(item).find('.trackname').html();
|
||||
var length = $(item).find('.length').html();
|
||||
Player.addTrack(artist, track_name, length);
|
||||
});
|
||||
})
|
||||
|
||||
$('.playlist-tracks li').live('dblclick', function(){
|
||||
Player.setTrack(this);
|
||||
})
|
||||
|
||||
$(function(){
|
||||
Audio.init();
|
||||
})
|
|
@ -0,0 +1,12 @@
|
|||
$(function(){
|
||||
VK.init({
|
||||
apiId: 2335068,
|
||||
nameTransportPath: "/demo/xd_receiver.html"
|
||||
});
|
||||
})
|
||||
|
||||
function loadTracksData(query, callback) {
|
||||
VK.Api.call('audio.search', {q:query}, function(r){
|
||||
callback(r.response[1].url);
|
||||
})
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
{
|
||||
'artist': {
|
||||
'name': 'Jet',
|
||||
'desc': 'Jet is an Australian rock band formed in 2001 in Melbourne, Australia, consisting of lead guitarist Cameron Muncey, bassist Mark Wilson, and brothers Nic and Chris Cester on vocals/rhythm guitar and drums respectively. The group has sold 6.5 million records worldwide, with their debut album Get Born, released in 2003, accounting for about 3.5 million of that figure. The band\'s most recent album, Shaka Rock, was released on 19 August 2009.',
|
||||
'pic': 'pics/jet.jpg'
|
||||
},
|
||||
'albums': [
|
||||
{
|
||||
'name': 'Get Born',
|
||||
'year': 2003,
|
||||
'pic': '/images/getborn.jpg',
|
||||
'tracks': {
|
||||
'album': [
|
||||
{
|
||||
'name': 'Last Chance',
|
||||
'duration': '1:52',
|
||||
},
|
||||
{
|
||||
'name': 'Are You Gonna Be My Girl',
|
||||
'duration': '3:34',
|
||||
},
|
||||
{
|
||||
'name': 'Rollover DJ',
|
||||
'duration': '3:17',
|
||||
},
|
||||
{
|
||||
'name': 'Look What You\'ve Done',
|
||||
'duration': '3:51',
|
||||
},
|
||||
{
|
||||
'name': 'Get What You Need',
|
||||
'duration': '4:08',
|
||||
},
|
||||
{
|
||||
'name': 'Move On',
|
||||
'duration': '4:21',
|
||||
},
|
||||
{
|
||||
'name': 'Radio Song',
|
||||
'duration': '4:32',
|
||||
},
|
||||
{
|
||||
'name': 'Get Me Outta Here',
|
||||
'duration': '2:56',
|
||||
},
|
||||
{
|
||||
'name': 'Cold Hard Bitch',
|
||||
'duration': '4:03',
|
||||
},
|
||||
{
|
||||
'name': 'Come Around Again',
|
||||
'duration': '4:30',
|
||||
},
|
||||
{
|
||||
'name': 'Take It or Leave It',
|
||||
'duration': '2:23',
|
||||
},
|
||||
{
|
||||
'name': 'Lazy Gun',
|
||||
'duration': '4:42',
|
||||
},
|
||||
{
|
||||
'name': 'Timothy',
|
||||
'duration': '4:30',
|
||||
},
|
||||
{
|
||||
'name': 'Sgt. Major',
|
||||
'duration': '4:05',
|
||||
},
|
||||
{
|
||||
'name': 'Are You Gonna Be My Girl (Acoustic)',
|
||||
'duration': '3:50',
|
||||
},
|
||||
{
|
||||
'name': 'Bruises (Demo)',
|
||||
'duration': '2:37',
|
||||
},
|
||||
{
|
||||
'name': 'Hey Kids (Non-Album Track)',
|
||||
'duration': '3:00',
|
||||
},
|
||||
{
|
||||
'name': 'Move On (Live)',
|
||||
'duration': '4:05',
|
||||
},
|
||||
{
|
||||
'name': 'Cold Hard Bitch (Live)',
|
||||
'duration': '5:01',
|
||||
},
|
||||
{
|
||||
'name': 'You Don\'t Look The Same (Demo)',
|
||||
'duration': '4:40',
|
||||
},
|
||||
{
|
||||
'name': 'Look What You\'ve Done (Live)',
|
||||
'duration': '4:07',
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Shine On',
|
||||
'year': 2006,
|
||||
'pic': '/images/shineon.jpg',
|
||||
'tracks': {
|
||||
'album': [
|
||||
{
|
||||
'name': 'Espirit d\'Escalier',
|
||||
'duration': '0:23',
|
||||
},
|
||||
{
|
||||
'name': 'Holiday',
|
||||
'duration': '3:26',
|
||||
},
|
||||
{
|
||||
'name': 'Put Your Money Where Your Mouth Is',
|
||||
'duration': '2:33',
|
||||
},
|
||||
{
|
||||
'name': 'Bring It on Back',
|
||||
'duration': '4:09',
|
||||
},
|
||||
{
|
||||
'name': 'That\'s All Lies',
|
||||
'duration': '2:44',
|
||||
},
|
||||
{
|
||||
'name': 'Hey Kids',
|
||||
'duration': '3:13',
|
||||
},
|
||||
{
|
||||
'name': 'Kings Horses',
|
||||
'duration': '3:20',
|
||||
},
|
||||
{
|
||||
'name': 'Shine On',
|
||||
'duration': '4:37',
|
||||
},
|
||||
{
|
||||
'name': 'Come On Come On',
|
||||
'duration': '4:24',
|
||||
},
|
||||
{
|
||||
'name': 'Stand Up',
|
||||
'duration': '4:33',
|
||||
},
|
||||
{
|
||||
'name': 'Rip It Up',
|
||||
'duration': '3:20',
|
||||
},
|
||||
{
|
||||
'name': 'Skin and Bones',
|
||||
'duration': '3:17',
|
||||
},
|
||||
{
|
||||
'name': 'Shiny Magazine',
|
||||
'duration': '3:28',
|
||||
},
|
||||
{
|
||||
'name': 'Eleanor',
|
||||
'duration': '3:34',
|
||||
},
|
||||
{
|
||||
'name': 'All You Have to Do',
|
||||
'duration': '4:39',
|
||||
},
|
||||
{
|
||||
'name': 'Snap Your Fingers (Barbados Demo)',
|
||||
'duration': '1:29',
|
||||
},
|
||||
{
|
||||
'name': 'This Night is Yours',
|
||||
'duration': '1:57',
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Shaka Rock',
|
||||
'year': 2009,
|
||||
'pic': '/images/shakarock.jpg',
|
||||
'tracks': {
|
||||
'album': [
|
||||
{
|
||||
'name': 'K.I.A. (Killed In Action)',
|
||||
'duration': '3:29',
|
||||
},
|
||||
{
|
||||
'name': 'Beat On Repeat',
|
||||
'duration': '2:30',
|
||||
},
|
||||
{
|
||||
'name': 'She\'s A Genius',
|
||||
'duration': '2:59',
|
||||
},
|
||||
{
|
||||
'name': 'Black Hearts (On Fire)',
|
||||
'duration': '3:14',
|
||||
},
|
||||
{
|
||||
'name': 'Seventeen',
|
||||
'duration': '3:41',
|
||||
},
|
||||
{
|
||||
'name': 'La Di Da',
|
||||
'duration': '2:53',
|
||||
},
|
||||
{
|
||||
'name': 'Goodbye Hollywood',
|
||||
'duration': '4:13',
|
||||
},
|
||||
{
|
||||
'name': 'Walk',
|
||||
'duration': '3:07',
|
||||
},
|
||||
{
|
||||
'name': 'Times Like This',
|
||||
'duration': '3:20',
|
||||
},
|
||||
{
|
||||
'name': 'Let Me Out',
|
||||
'duration': '3:12',
|
||||
},
|
||||
{
|
||||
'name': 'Start the Show',
|
||||
'duration': '3:59',
|
||||
},
|
||||
{
|
||||
'name': 'She Holds a Grudge',
|
||||
'duration': '4:18',
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* Main blocks*/
|
||||
.artist-info {
|
||||
width: 100%;
|
||||
float: left;
|
||||
margin: 25px 0;
|
||||
}
|
||||
.albums {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* Artist info block */
|
||||
.artist-info .pic {
|
||||
float: left;
|
||||
width: 250px;
|
||||
margin: 25px 0;
|
||||
}
|
||||
.artist-info .pic img {
|
||||
margin-left: 25px;
|
||||
}
|
||||
.artist-info .name {
|
||||
margin: 25px 0 0 300px;
|
||||
}
|
||||
.artist-info .info {
|
||||
margin: 0 25px 25px 300px;
|
||||
}
|
||||
|
||||
/* Albums block */
|
||||
.album {
|
||||
clear: both;
|
||||
}
|
||||
.album .pic {
|
||||
float: left;
|
||||
width: 250px;
|
||||
}
|
||||
.album .pic > * {
|
||||
margin-left: 25px;
|
||||
}
|
||||
.album .pic .add-album {
|
||||
margin-top: 15px;
|
||||
width: auto;
|
||||
color: #04D;
|
||||
cursor: pointer;
|
||||
}
|
||||
.album .name {
|
||||
display: block;
|
||||
margin: 0 0 10px 300px;
|
||||
}
|
||||
.album .tracklist {
|
||||
margin: 0 25px 30px 300px;
|
||||
}
|
||||
.album .tracklist ul {
|
||||
|
||||
}
|
||||
.album .tracklist ul li {
|
||||
display: block;
|
||||
height: 20px;
|
||||
padding: 5px 0 0 0;
|
||||
border-top: #EEE 1px solid;
|
||||
}
|
||||
.album .tracklist ul li:hover {
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
.album .tracklist ul li:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
.album .tracklist ul li .trackname {
|
||||
float: left;
|
||||
}
|
||||
.album .tracklist ul li .index {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 15px;
|
||||
text-align: right;
|
||||
margin: 3px 5px 0 0;
|
||||
font-size: 10px;
|
||||
color: #555;
|
||||
}
|
||||
.album .tracklist ul li .length {
|
||||
float: right;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#header-container {
|
||||
margin-right: 350px;
|
||||
}
|
||||
#player-container {
|
||||
width: 350px;
|
||||
height: 600px;
|
||||
float: right;
|
||||
}
|
||||
#data-container {
|
||||
width: auto;
|
||||
margin-right: 350px;
|
||||
}
|
||||
|
||||
#player {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
#playlist {
|
||||
width: 100%;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
.fullscreen {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#navigation {
|
||||
background-color: #333;
|
||||
height: 30px;
|
||||
}
|
||||
#navigation li {
|
||||
display: block;
|
||||
float: left;
|
||||
width: auto;
|
||||
height: 30px;
|
||||
margin-left: 10px;
|
||||
color: #FFF;
|
||||
line-height: 30px;
|
||||
text-shadow: #CCC 0px 0px 0.5px;
|
||||
}
|
||||
#navigation li:hover {
|
||||
cursor: pointer;
|
||||
text-shadow: #CCC 0px 0px 2px;
|
||||
}
|
||||
#navigation li.logo {
|
||||
font-size: 20px;
|
||||
line-height: 32px;
|
||||
font-weight: bold;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
/* Colorizing *
|
||||
#player-container { background-color: #CFC; }
|
||||
#data-container { background-color: #CCF; }
|
||||
#player { background-color: #AAC; }
|
||||
#playlist { background-color: #ACC; }
|
||||
.artist-info { background-color: #8EA; }
|
||||
.albums { background-color: #A8E; }
|
|
@ -0,0 +1,68 @@
|
|||
#player {
|
||||
background-color: #222;
|
||||
}
|
||||
#player .now-playing {
|
||||
height: 30px;
|
||||
color: #FFF;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
}
|
||||
#player .progress {
|
||||
width: 290px;
|
||||
height: 10px;
|
||||
background-color: #333;
|
||||
margin: 20px 30px;
|
||||
}
|
||||
#player .progress .loaded {
|
||||
width: 0;
|
||||
height: 10px;
|
||||
background-color: #405050;
|
||||
}
|
||||
#player .progress .played {
|
||||
width: 0;
|
||||
height: 10px;
|
||||
background-color: #09A;
|
||||
}
|
||||
#player .controls {
|
||||
width: 290px;
|
||||
margin: 40px 95px;
|
||||
}
|
||||
#player .controls > div {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
#player .controls .prev {
|
||||
background-image: url('../icns/prev.png');
|
||||
}
|
||||
#player .controls .play {
|
||||
background-image: url('../icns/play.png');
|
||||
}
|
||||
#player .controls .next {
|
||||
background-image: url('../icns/next.png');
|
||||
}
|
||||
|
||||
.playlist-tracks li {
|
||||
display: block;
|
||||
}
|
||||
.playlist-tracks li .item {
|
||||
padding: 5px 6px;
|
||||
}
|
||||
.playlist-tracks li .item:hover {
|
||||
background-color: #D0E0F0;
|
||||
cursor: default;
|
||||
}
|
||||
.playlist-tracks li:nth-child(even) {
|
||||
background-color: #F0F0F0;
|
||||
cursor: default;
|
||||
}
|
||||
.playlist-tracks li.now .item {
|
||||
background-color: #E0EAF0;
|
||||
cursor: default;
|
||||
}
|
||||
.playlist-tracks li .item .duration {
|
||||
display: block;
|
||||
float: right;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Open API XD Receiver</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="http://vkontakte.ru/js/api/xd_receiver.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||
|
||||
one:
|
||||
name: MyString
|
||||
artist_id: 1
|
||||
year: 1
|
||||
status: 1
|
||||
pic_url: MyString
|
||||
|
||||
two:
|
||||
name: MyString
|
||||
artist_id: 1
|
||||
year: 1
|
||||
status: 1
|
||||
pic_url: MyString
|
|
@ -0,0 +1,9 @@
|
|||
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||
|
||||
one:
|
||||
name: MyString
|
||||
desc: MyText
|
||||
|
||||
two:
|
||||
name: MyString
|
||||
desc: MyText
|
|
@ -0,0 +1,17 @@
|
|||
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||
|
||||
one:
|
||||
name: MyString
|
||||
album_id: 1
|
||||
position: 1
|
||||
bonus: 1
|
||||
live: 1
|
||||
acoustic: 1
|
||||
|
||||
two:
|
||||
name: MyString
|
||||
album_id: 1
|
||||
position: 1
|
||||
bonus: 1
|
||||
live: 1
|
||||
acoustic: 1
|
|
@ -0,0 +1,8 @@
|
|||
require 'test_helper'
|
||||
|
||||
class AlbumTest < ActiveSupport::TestCase
|
||||
# Replace this with your real tests.
|
||||
test "the truth" do
|
||||
assert true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
require 'test_helper'
|
||||
|
||||
class ArtistTest < ActiveSupport::TestCase
|
||||
# Replace this with your real tests.
|
||||
test "the truth" do
|
||||
assert true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
require 'test_helper'
|
||||
|
||||
class TrackTest < ActiveSupport::TestCase
|
||||
# Replace this with your real tests.
|
||||
test "the truth" do
|
||||
assert true
|
||||
end
|
||||
end
|