- swf版 https://yunpstatic.oss-cn-beijing.aliyuncs.com/artonline/apps/lrceditor/bin/LRCEditor.swf
- exe版 https://yunpstatic.oss-cn-beijing.aliyuncs.com/artonline/apps/lrceditor/bin/LRCEditor.7z
主要源码如下
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:sound="com.topyunp.lrceditor.sound.*" xmlns:lrc="com.topyunp.lrceditor.lrc.*"
width="100%" height="100%" fontFamily="AliShuHei" layout="vertical" paddingBottom="10"
paddingLeft="10" paddingRight="10" paddingTop="10" fontSize="16">
<fx:Declarations>
<sound:SoundPlayer id="player" progress="player_progressHandler(event)"/>
<lrc:Lrc id="lrc"/>
<fx:XML id="saveLrcMenuItems">
<root>
<menuitem label="GBK" charset="gbk"/>
<menuitem label="UTF-8" charset="utf-8"/>
</root>
</fx:XML>
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.topyunp.lrceditor.assets.Assets;
import com.topyunp.lrceditor.dialogs.FileDialog;
import com.topyunp.lrceditor.utils.StringUtils;
import com.topyunp.lrceditor.utils.TimeFormatter;
import mx.controls.Menu;
import mx.events.MenuEvent;
[Embed(source="assets/AlimamaShuHeiTi-Bold.otf", embedAsCFF="false", fontName="AliShuHei")]
private static var AliShuHei:Class;
[Bindable]
private var selectedSoundName:String = "";
[Bindable]
private var lrcContent:String = "";
[Bindable]
private var timeLabel:String = "[00:00]";
[Bindable]
private var currentLrcLineContent:String = "";
protected function btnSelectMp3_clickHandler(event:MouseEvent):void {
FileDialog.show([new FileFilter("MP3文件", "*.mp3")], function (fileName:String, data:ByteArray):void {
player.source = data;
selectedSoundName = fileName;
});
}
protected function btnPlayPause_clickHandler(event:MouseEvent):void {
if (player.playing) {
player.pause();
} else {
lrc.decode(lrcContent);
trace(lrc);
player.play();
}
}
protected function playProgressBar_clickHandler(event:MouseEvent):void {
player.play((playProgressBar.mouseX / playProgressBar.width) * player.totalTime);
}
private function btnInsertTimeLabel_clickHandler(event:MouseEvent):void {
// trace(lrcContentTextArea.selectionBeginIndex);
var begin:int = StringUtils.findLineBegin(lrcContent, lrcContentTextArea.selectionBeginIndex - 1);
// trace("selected begin: " + begin);
lrcContent = lrcContent.substring(0, begin) + timeLabel + lrcContent.substring(begin);
var end:int = StringUtils.findLineEnd(lrcContent, begin);
var nextLineBegin:int = end + 1;
if (nextLineBegin < lrcContent.length) {
var nextLineEnd:int = StringUtils.findLineEnd(lrcContent, nextLineBegin);
if (nextLineEnd >= nextLineBegin && nextLineEnd <= lrcContent.length) {
lrcContentTextArea.setSelection(nextLineBegin, nextLineEnd);
// trace("select range:", nextLineBegin, nextLineEnd);
}
} else {
lrcContentTextArea.setSelection(0, StringUtils.findLineEnd(lrcContent, 0));
}
lrcContentTextArea.setFocus();
}
private function player_progressHandler(event:ProgressEvent):void {
timeLabel = "[" + TimeFormatter.convertMsToMinutesAndSeconds(event.bytesLoaded) + "]";
var content:String = lrc.getContent(Math.round(event.bytesLoaded / 1000));
if (content) {
currentLrcLineContent = content;
}
}
private function btnSaveLrc_clickHandler(event:MouseEvent):void {
var myMenu:Menu = Menu.createMenu(this, saveLrcMenuItems, false);
myMenu.labelField = "@label";
myMenu.addEventListener(MenuEvent.ITEM_CLICK, menuItemHandler);
var point:Point = new Point(btnSaveLrc.x, btnSaveLrc.y);
myMenu.show(point.x + 10, point.y + 40);
}
private function menuItemHandler(event:MenuEvent):void {
saveLrc(event.item.@charset);
}
private function saveLrc(charset:String = "utf-8"):void {
var dotPosition:int = selectedSoundName.lastIndexOf(".");
var fileName:String = null;
if (dotPosition > -1) {
fileName = selectedSoundName.substring(0, selectedSoundName.lastIndexOf("."));
} else {
fileName = "" + (new Date().getTime());
}
fileName += ".lrc";
var data:ByteArray = new ByteArray();
data.writeMultiByte(lrcContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n"), charset);
data.position = 0;
var fr:FileReference = new FileReference();
fr.save(data, fileName);
}
]]>
</fx:Script>
<mx:HBox width="100%" verticalAlign="middle">
<mx:Button focusEnabled="false" label="插入时间 {timeLabel}" id="btnInsertTimeLabel"
click="btnInsertTimeLabel_clickHandler(event)"/>
<mx:Button focusEnabled="false" label="保存LRC" id="btnSaveLrc" click="btnSaveLrc_clickHandler(event)"/>
<mx:Button focusEnabled="false" id="btnSelectMp3" label="选择歌曲" click="btnSelectMp3_clickHandler(event)"/>
<mx:Label width="200" text="{selectedSoundName}" fontSize="12" textAlign="center"/>
<mx:HBox horizontalGap="0">
<mx:Button id="btnStop" width="24" click="player.stop()" cornerRadius="0"
enabled="{player.source!=null}" icon="{Assets.Stop}"/>
<mx:Button id="btnPlayPause" width="24" click="btnPlayPause_clickHandler(event)"
cornerRadius="0" enabled="{player.source!=null}"
icon="{player.playing?Assets.Pause:Assets.Play}"/>
</mx:HBox>
<mx:ProgressBar id="playProgressBar" width="100%" label="{currentLrcLineContent}"
click="playProgressBar_clickHandler(event)" labelPlacement="center"
source="{player}"/>
<mx:Label width="110"
text="{TimeFormatter.convertMsToMinutesAndSeconds(playProgressBar.value)}/{TimeFormatter.convertMsToMinutesAndSeconds(playProgressBar.maximum)}"
textAlign="right"/>
</mx:HBox>
<mx:TextArea focusEnabled="true" width="100%" height="100%" wordWrap="false" id="lrcContentTextArea"
text="@{lrcContent}" horizontalScrollPolicy="off"/>
</mx:Application>