LDRをすばやく聴く猿
まみむめも!…ハイ、では。前回の反省を少し踏まえて、livedoor Readerでフィードにあるmp3をQuickTimeプラグインで聴いてみるの巻。
調べてみるとどうやらQuickTimeプラグインをJavaScriptから多少操作できるみたいなので、またGreasemonkeyスクリプトを書いてみました。やっぱりコードはぐちゃぐちゃでスッキリしてないのですが、とりあえずもっとぐちゃぐちゃになる前にここらで止めておこうかという感じです。マズいところは多々あるかと思います。
QuickTimeプラグインでmp3を再生するにはver.4くらいの奴でできるようなので、QuickTimeをインストールしてMIMEタイプの設定をきちんと合わせればたぶん動くと思われます。Firefoxのアドレスバーに「about:plugins」と入力すればインストールされているプラグインを確認できます。
前回はEmbed要素はW3C非標準だからと思って、Object要素を生成してやってしまっていたのですが、今のところFirefoxだとEmbed要素でないとうまく動かないようです。
あと、音楽を聴くには時間がかかります。mp3は目で読めないので、耳で聴くしかありません。LDRの記事の下にプレイヤーを表示すると読むスピードと聴くスピードが違ってくるのでちょっとマズい。フィードを移動しても良いようにプレイヤーの位置を変えました。LDリスナー的なものをくっつける感じで。
操作はviコマンドでやるようにしてみましたので、次にその説明です。簡単に。
- :play ... 記事にあるmp3をまとめてプレイヤーにセットして再生。スペースで区切ってレコードリストからレコードやトラックを選べる。例:「:play 2」で2番目に再生した記事のmp3をまとめて再生。「:play 2-3」で2番目に再生した記事の3曲目を再生。「:play 2 1-2 2-4 1 3」など複数選んでも可。
- :add ... :playの、プレイリストをクリアしないで追加していく版。
- :pause ... 再生したり停止したり。止まってるときの再生ボタン。
- :vol ... 音量を変える。あまり役に立たない。例:「:vol max」「:vol min」「:vol half」「:vol 200」
- :rate ... 再生スピード。今のところ役立たず。
- :step ... 例:「:step -60」60秒前に戻って再生。「:step 300」300秒進む。
ldr_qt_player.user.js (ver.0.?.?)
//==UserScript==
//@name ldr_qt_player
//@namespace http://zeroglab.jp.land.to/
//@include http://reader.livedoor.com/reader/
//@version 0.0.1
//==/UserScript==
(function(){
/*
* var init
*/
var mp3data = [];
var setindex = 0;
var w = unsafeWindow;
/*
* html init
*/
var controlUl = document.getElementById('control_buttons_ul');
var playerbox = document.createElement('li');
playerbox.setAttribute('id','playerbox');
playerbox.setAttribute('class','button');
controlUl.appendChild(playerbox);
var player = document.createElement('embed');
player.setAttribute('id','player');
player.setAttribute('type','audio/mp3');
player.setAttribute('enablejavascript','true');
player.setAttribute('autostart','true');
player.setAttribute('width','150px');
player.setAttribute('height','22px');
player.style.display = 'block';
playerbox.appendChild(player);
var control = document.getElementById('control');
var listbox = document.createElement('div');
listbox.setAttribute('id','listbox');
var h4txt = ['Play List','Record List'];
var idtxt = ['playlist','recordlist'];
for(var i=0; i<2; i++){
var h4 = document.createElement('h4');
h4.innerHTML = h4txt[i];
listbox.appendChild(h4);
var ol = document.createElement('ol');
ol.setAttribute('id',idtxt[i]);
listbox.appendChild(ol);
}
control.appendChild(listbox);
/*
* style
*/
w.LDR_addStyle('#playerbox',
'margin: 0; padding: 0 5px; position: relative; height: 100%; border-bottom: 2px solid #a5c5ff;'
);
w.LDR_addStyle('#listbox',
'margin: .5em 0 0 0; padding: .7em .5em; position: absolute; top: 27px; right: 5%;'+
'z-index: 10; display: none; overflow: auto; max-width: 340px; max-height: 400px;'+
'color: #000000; background: #f8f8f8; border: 2px solid #0098d8; font-size: 90%;'+
'outline: 2px solid #ffffff; -moz-opacity: .9;'
);
w.LDR_addStyle('#listbox h4','color: #0088c8; border-bottom: 1px solid #0098d8;');
w.LDR_addStyle('#playlist',
'margin: .5em 0 1.5em; padding: 0; list-style-type: none;'
);
w.LDR_addStyle('#playlist li',
'margin: .5em 0; padding: .5em; display: inline; font-weight: bold; border-right: 1px dashed #cccccc;'
);
w.LDR_addStyle('#recordlist',
'margin: .5em 0 1.5em; padding: 0; list-style-type: none; counter-reset: record;'
);
w.LDR_addStyle('#recordlist li',
'margin: .5em 0; padding: .5em 1em .5em .5em; font-weight: bold; border-bottom: 1px dashed #cccccc;'
);
w.LDR_addStyle('#recordlist li span','font-weight: normal;');
w.LDR_addStyle('#recordlist li:before','content: counter(record) ; counter-increment: record;');
/*
* toggle listbox
*/
document.addEventListener('keyup',function(){
var vi = document.getElementById('vi');
if(!vi) return;
document.getElementById('listbox').style.display =
(vi.value.indexOf(':play') == -1) ? 'none' :
'block';
},false);
/*
* qt function
*/
var p = w.$('player');
var qt = {
Play: function (){
p.Play();
},
Stop: function(){
p.Stop();
},
SetURL: function(url){
p.SetURL(url);
},
GetQTNEXTUrl: function(index){
return p.GetQTNEXTUrl(index);
},
SetQTNEXTUrl: function(index,url){
p.SetQTNEXTUrl(index,url);
},
GetVolume: function(){
return p.GetVolume();
},
SetVolume: function(v){
p.SetVolume(v);
},
GetRate: function(){
return p.GetRate();
},
Step: function(count){
p.Step(count);
}
};
/*
* function
*/
function listUpEntry(itemId){
var list = [];
var itemBody = document.getElementById('item_body_' + itemId);
var anchors = itemBody.getElementsByTagName('a');
var anchorsLen = anchors.length;
for(var i=0; i<anchorsLen; i++){
var a = anchors[i];
var href = a.getAttribute('href');
if(!href) continue;
if(href.match(/.*\.mp3$/i)){
list[list.length] = href;
}
}
list.txt = (mp3data.length + 1) + '(' + list.length + '曲)';
return list;
}
function listUpData(args){
var list = [];
var argstxt = [];
var argsLen = args.length;
for(var i=0; i<argsLen; i++){
if(args[i].indexOf('-') != -1){
if(!mp3data['track' + args[i]]) continue;
var track = mp3data['track' + args[i]].mp3;
list[list.length] = track;
}else{
if(!mp3data[args[i] - 1]) continue;
var record = mp3data[args[i] - 1].mp3;
var recordLen = record.length;
for(var j=0; j<recordLen; j++){
list[list.length] = record[j];
}
args[i] += '(' + list.length + '曲)';
}
argstxt[argstxt.length] = args[i];
}
list.txt = argstxt.join(', ');
return list;
}
function setPlaylist(listTxt,clear){
var playlist = document.getElementById('playlist');
if(clear) playlist.innerHTML = '';
var li = document.createElement('li');
li.innerHTML = listTxt;
playlist.appendChild(li);
}
function setFile(list){
if(setindex == 0){
qt.SetURL(list[0]);
list.shift();
}
for(var i=0; i<list.length; i++){
var url = '<' + list[i] + '>T<myself>';
qt.SetQTNEXTUrl(setindex + i + 1,url);
}
setindex += i;
qt.SetQTNEXTUrl(setindex,'javascript:document.getElementById("player").Stop();');
}
function inputData(item,list,listLen){
var itemId = item.item_id;
var objRecord = {title: item.title, num: listLen, mp3: list};
mp3data['record' + itemId] = mp3data[mp3data.length] = objRecord;
var recordlist = document.getElementById('recordlist');
var recordlistLi = document.createElement('li');
recordlistLi.innerHTML = '(' + mp3data['record' + itemId].num + '曲) ' +
'<span>' + mp3data['record' + itemId].title + '</span>';
recordlist.appendChild(recordlistLi);
for(var i=0; i<listLen; i++){
mp3data['track' + mp3data.length + '-' + (i+1)] = {mp3: list[i]};
}
w.LDR_addStyle('#item_' + itemId,'background: #e0ffff;');
w.LDR_addStyle('#item_' + itemId + ' div.item_info:after',
'content: " | :play '+ mp3data.length +'('+ listLen +'曲)";');
}
function main(args,item,clear,resTxt){
var argsLen = args.length;
var itemId = item.item_id;
var list = (!argsLen && !mp3data['record'+itemId]) ? listUpEntry(itemId) :
(!argsLen) ? mp3data['record'+itemId].mp3 :
listUpData(args);
var listLen = list.length;
var listTxt = list.txt;
var res = (!listLen) ? 'mp3ファイルが見つかりませんでした' :
(!mp3data['record' + itemId]) ? listLen + '個のmp3が見つかりました' :
listLen + resTxt + listTxt;
w.message(res);
if(!listLen) return;
if(!mp3data['record' + itemId]) inputData(item,list,listLen);
setPlaylist(listTxt,clear);
if(clear) setindex = 0;
setFile(list);
document.getElementById('listbox').style.display = 'block';
}
/*
* command
*/
w.register_command('play',function(){
var args = arguments;
var item = w.get_active_item(true);
if(!item) return;
var clear = true;
var resTxt = '個のmp3を再生します ';
main(args,item,clear,resTxt);
});
w.register_command('add',function(){
var args = arguments;
var item = w.get_active_item(true);
if(!item) return;
var clear = false;
var resTxt = '個のmp3をプレイリストに追加しました ';
main(args,item,clear,resTxt);
});
w.register_command('pause',function(){
var rate = qt.GetRate();
if(rate != 0){
qt.Stop();
var res = '一時停止しました (:pauseで再開)';
}else{
qt.Play();
var res = '再生します';
}
w.message(res);
});
w.register_command('vol',function(volume){
if(volume){
var v = (volume == 'max' || volume > 255) ? 255 :
(volume == 'half') ? 128 :
(volume == 'min' || volume == 'mute') ? 0 :
volume;
qt.SetVolume(v);
}
var res = '現在の音量は ' + qt.GetVolume() + '/255 です';
w.message(res);
});
w.register_command('rate',function(){
var rate = qt.GetRate();
w.message('rate: ' + rate);
});
w.register_command('step',function(count){
count = (!count) ? 60 : count;
qt.Step(count);
w.message('step: ' + count);
qt.Play();
});
})();
ひとり反省会。このままだと、現在再生中の情報が出てこないので不便かもしれません。URLをセットするところにスクリプトを放り込めばもっと色々とゴージャスにできるかもしれません。レコードリストからピンを刺したりブックマークにクリップできたりすれば楽かもしれません。あと記事の書き方によってトラック名が何とかは一様に取り難いと思って、トラック名を見せる部分はばっさり割愛してみました。URLを表示してもいまいちピンとこないので。再生中にライブドアリーダーマンが踊るアニメか、ムーンウォークするアニメかにしたかったけど諦めました。すぐに寝てしまわれます。
このスクリプトをいじってると、「ぶっちゃけ普通にプレイヤーで聴いた方が早い」とか、「Firefoxのなんたら言う拡張で聴いた方が早い」とか…、聞えてきたりこなかったり。
大事なこと。フィードのレコードを試聴して、本当に良いかどうか、満足できるものかどうかは買ってみるまでわからない。ウンヌン。
今回のテーマは、ただ「LDRを聴く」というだけのことでございます。
- 参考資料
- QuickTime: EMBED タグアトリビュート
- HTML Scripting Guide for QuickTime
- JavaScript Scripting Guide for QuickTime
追記:インストールのときに文字化けしてしまうようなので日本語部分をエスケープしました。ファイルの方を修正してます。(10/23)
+ まずかったとこを3ヶ所ほど修正。(10/24)
Technorati Tags:livedoor,reader,greasemonkey

0 comments:
Post a Comment