serve itunes library directly and import js frontend

This commit is contained in:
j 2012-09-06 12:39:24 +02:00
parent 56d92d1d3d
commit 866174e47e
4 changed files with 281 additions and 19 deletions

View file

@ -155,6 +155,10 @@ class Server(Resource):
return f
if request.path == '/api/':
return self
if request.path == '/library.xml':
f = File(self.backend.xml)
f.isLeaf = True
return f
if request.path.startswith('/track/'):
track_id = request.path.split('/')[-1].split('.')[0]
track = self.backend.library['Tracks'].get(track_id)

View file

@ -5,7 +5,7 @@
<title>0xcd</title>
<link rel="shortcut icon" type="image/png" href="/png/icon16.png"/>
<script type="text/javascript" src="/oxjs/build/Ox.js"></script>
<script type="text/javascript" src="/js/site.js"></script>
<script type="text/javascript" src="/js/index.js"></script>
</head>
<body>
</body>

276
oxcd/static/js/index.js Normal file
View file

@ -0,0 +1,276 @@
'use strict';
Ox.load('UI', function() {
var app = {
$ui: {},
data: {},
site: {
columns: [
{
format: function(value) {
return value ? $('<img>').addClass('symbol').attr({
src: Ox.UI.getImageURL('symbolMute')
}) : '';
},
id: 'playing',
operator: '-',
removable: false,
resizable: false,
title: 'Playing',
titleImage: 'mute',
visible: true,
width: 16
},
{
format: function(value) {
return value ? '' : $('<img>').addClass('symbol').attr({
src: Ox.UI.getImageURL('symbolCheck')
});
},
id: 'disabled',
operator: '+',
removable: false,
resizable: false,
title: 'Enabled',
titleImage: 'check',
visible: true,
width: 16
},
{
format: function(value) {
return app.utils.formatTitle(value);
},
id: 'name',
operator: '+',
removable: false,
title: 'Name',
visible: true,
width: 192
},
{
id: 'artist',
operator: '+',
sort: function(value, data) {
return data.albumArtist ? data.sortAlbumArtist || data.albumArtist
: data.compilation ? ''
: data.sortArtist || data.artist || '';
},
title: 'Artist',
visible: true,
width: 192
},
{
format: function(value) {
return app.utils.formatTitle(value);
},
id: 'album',
operator: '+',
title: 'Album',
visible: true,
width: 192
},
{
align: 'right',
id: 'year',
operator: '+',
title: 'Year',
visible: true,
width: 64
},
{
align: 'right',
format: function(value) {
return app.utils.formatTime(value);
},
id: 'totalTime',
operator: '-',
title: 'Time',
visible: true,
width: 64
},
{
align: 'right',
format: function(value) {
return Ox.formatValue(value, 'B');
},
id: 'size',
operator: '-',
title: 'Size',
visible: true,
width: 64,
}
]
},
user: {
library: '/library.xml',
sort: [
{key: 'artist', operator: '+'},
{key: 'year', operator: '+'},
{key: 'album', operator: '+'},
{key: 'discNumber', operator: '+'},
{key: 'trackNumber', operator: '+'}
]
},
ui: {},
utils: {}
};
app.load = function() {
app.$ui.appPanel = app.ui.appPanel().appendTo(Ox.$body);
app.utils.parseLibrary(function(data) {
app.user.music = data;
app.loaded = true;
app.$ui.appPanel.replaceElement(1, app.$ui.list = app.ui.list());
});
}
app.ui.appPanel = function() {
var $element = Ox.SplitPanel({
elements: [
{element: app.$ui.toolbar = app.ui.toolbar(), size: 24},
{element: app.$ui.list = app.ui.list()},
{element: app.$ui.statusbar = app.ui.statusbar(), size: 24}
],
orientation: 'vertical'
});
return $element;
};
app.ui.toolbar = function() {
var $element = Ox.Bar({size: 24});
return $element;
};
app.ui.list = function() {
var $element = !app.loaded ? Ox.Element() : Ox.TableList({
columns: app.site.columns,
columnsRemovable: true,
columnsVisible: true,
items: app.user.music.tracks,
keys: ['albumArtist', 'compilation', 'sortAlbumArtist', 'sortArtist'],
/*
query: {
conditions: [
{key: 'artist', operator: '==', value: 'Mary Lou Lord'},
{key: 'artist', operator: '==', value: 'Liz Phair'}
],
operator: '|'
},
*/
scrollbarVisible: true,
sort: app.user.sort,
sums: ['size', 'totalTime'],
unique: 'trackID'
})
.bindEvent({
init: function(data) {
app.$ui.statusbar.update(data);
},
open: function(data) {
app.utils.play(data.ids[0]);
},
openpreview: function(data) {
$element.closePreview();
app.utils.play(data.ids[0]);
},
select: function(data) {
app.$ui.statusbar.update(data);
}
});
return $element;
};
app.ui.statusbar = function() {
var $status = $('<div>').attr({id: 'status'}),
$element = Ox.Bar({size: 24})
.append($status);
$element.update = function(data) {
var items;
if (data) {
if (data.items) {
app.data.status = data;
} else if (data.ids && data.ids.length > 1) {
var items = app.user.music.tracks.filter(function(track) {
return Ox.contains(data.ids, track.trackID);
});
data.selected = data.ids.length;
['size', 'totalTime'].forEach(function(key) {
data[key] = items.reduce(function(p, c) {
return p + c[key];
}, 0);
});
}
}
$status.html(
data ? (data.selected ? data.selected + ' of ' : '')
+ Ox.formatNumber(app.data.status.items) + ' item'
+ (app.data.status.items == 1 ? '' : 's') + ', '
+ app.utils.formatTime(data.totalTime || app.data.status.totalTime) + ' total time, '
+ Ox.formatValue(data.size || app.data.status.size, 'B')
: 'Loading...'
);
};
$element.update();
return $element;
};
app.utils.formatTime = function(duration) {
return Ox.formatDuration(duration / 1000).replace(/^00:/, '').replace(/^0/, '');
};
app.utils.formatTitle = function(title) {
return title.replace(/\[(.+)\]$/, '<span class="OxLight">($1)</span>');
};
app.utils.parseKey = function(key) {
return key[0].toLowerCase() + key.substr(1).replace(/ /g, '');
};
app.utils.parseLibrary = function(callback) {
Ox.get(app.user.library, function(xml) {
var data = {playlists: [], tracks: []},
library = app.utils.parseXML($(xml).children()[0]);
Ox.forEach(library.tracks, function(track) {
if (track.kind == 'MPEG audio file' && !track.podcast) {
app.site.columns.map(function(column) {
return column.id;
}).forEach(function(key) {
if (!track[key]) {
track[key] = '';
}
})
data.tracks.push(track);
}
});
callback(data);
});
};
app.utils.parseXML = function(xml) {
var type = xml.nodeName.toLowerCase(), value;
if (type == 'array') {
value = [];
$(xml).children().each(function(k, v) {
value.push(app.utils.parseXML(v));
});
} else if (type == 'data') {
value = xml.innerHTML.replace(/(\n|\t)/g, '');
} else if (type == 'date') {
value = xml.innerHTML;
} else if (type == 'dict') {
value = {};
$(xml).children('key').each(function(k, v) {
value[app.utils.parseKey(v.innerHTML)] = app.utils.parseXML($(v).next()[0]);
});
} else if (type == 'false') {
value = false;
} else if (type == 'integer') {
value = parseInt(xml.innerHTML);
} else if (type == 'string') {
value = xml.innerHTML;
} else if (type == 'true') {
value = true;
}
return value;
};
app.utils.play = function(id) {
if (app.user.playing) {
app.$ui.list.value(app.user.playing, 'playing', false);
}
if (id != app.user.playing) {
app.user.playing = id;
app.$ui.list.value(app.user.playing, 'playing', true);
}
};
app.load();
});

View file

@ -1,18 +0,0 @@
Ox.load('UI', function() {
window.oxcd = Ox.App({
name: 'oxcd',
url: '/api/'
}).bindEvent({
load: function(data) {
oxcd.api.library(function(result) {
var items = Ox.values(result.data.Tracks),
element = Ox.Element();
items.forEach(function(item) {
element.append($('<div>').html('<a href="/track/'+item['Track ID']+'.mp3">'+item['Track ID'] + ': '+item.Name+'</a>'))
console.log('<a href="/track/'+item['Track ID']+'.mp3">'+item['Track ID'] + ':'+item.Name+'</a>');
});
Ox.UI.$body.append(element);
})
}
});
});