⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lyric.java

📁 YOYOPlayer MP3播放器 java+JMF实现
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */package com.hadeslee.yoyoplayer.lyric;import com.hadeslee.yoyoplayer.playlist.PlayListItem;import com.hadeslee.yoyoplayer.util.Config;import com.hadeslee.yoyoplayer.util.Util;import java.awt.Color;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.LinearGradientPaint;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileFilter;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.Serializable;import java.io.StringReader;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List;import java.util.logging.Level;import java.util.logging.Logger;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 表示一首歌的歌词对象,它可以以某种方式来画自己 * @author hadeslee */public class Lyric implements Serializable {    private static final long serialVersionUID = 20071125L;    private static Logger log = Logger.getLogger(Lyric.class.getName());    private int width;//表示歌词的显示区域的宽度    private int height;//表示歌词的显示区域的高度    private long time;//表示当前的时间是多少了。以毫秒为单位    private long tempTime;//表示一个暂时的时间,用于拖动的时候,确定应该到哪了    private List<Sentence> list = new ArrayList<Sentence>();//里面装的是所有的句子    private boolean isMoving;//是否正在被拖动     private int currentIndex;//当前正在显示的歌词的下标    private boolean initDone;//是否初始化完毕了    private transient PlayListItem info;//有关于这首歌的信息    private transient File file;//该歌词所存在文件    private boolean enabled = true;//是否起用了该对象,默认是起用的    private long during = Integer.MAX_VALUE;//这首歌的长度    /**     * 用ID3V1标签的字节和歌名来初始化歌词     * 歌词将自动在本地或者网络上搜索相关的歌词并建立关联     * 本地搜索将硬编码为user.home文件夹下面的Lyrics文件夹     * 以后改为可以手动设置.     * @param songName 歌名     * @param data ID3V1的数据     */    public Lyric(final PlayListItem info) {        this.info = info;        this.during = info.getLength() * 1000;        this.file = info.getLyricFile();        log.info("传进来的歌名是:" + info.toString());        //只要有关联好了的,就不用搜索了直接用就是了        if (file != null&&file.exists()) {            log.log(Level.INFO, "不用找了,直接关联到的歌词是:" + file);            init(file);            initDone = true;            return;        } else {            //否则就起一个线程去找了,先是本地找,然后再是网络上找            new Thread() {                public void run() {                    doInit(info);                    initDone = true;                }            }.start();        }    }    /**     * 读取某个指定的歌词文件,这个构造函数一般用于     * 拖放歌词文件到歌词窗口时调用的,拖放以后,两个自动关联     * @param file 歌词文件     * @param info 歌曲信息     */    public Lyric(File file, PlayListItem info) {        this.file = file;        this.info = info;        init(file);        initDone = true;    }    /**     * 根据歌词内容和播放项构造一个     * 歌词对象     * @param lyric 歌词内容     * @param info 播放项     */    public Lyric(String lyric, PlayListItem info) {        this.info = info;        this.init(lyric);        initDone = true;    }    private void doInit(PlayListItem info) {        init(info);        Sentence temp = null;        //这个时候就要去网络上找了        if (list.size() == 1) {            temp = list.remove(0);            try {                String lyric = Util.getLyric(info);                if (lyric != null) {                    init(lyric);                    saveLyric(lyric, info);                } else {//如果网络也没有找到,就要加回去了                    list.add(temp);                }            } catch (IOException ex) {                Logger.getLogger(Lyric.class.getName()).log(Level.SEVERE, null, ex);                //如果抛了任何异常,也要加回去了                list.add(temp);            }        }    }    /**     * 把下载到的歌词保存起来,免得下次再去找     * @param lyric 歌词内容     * @param info 歌的信息     */    private void saveLyric(String lyric, PlayListItem info) {        try {            //如果歌手不为空,则以歌手名+歌曲名为最好组合            String name = info.getFormattedName() + ".lrc";//            File dir = new File(Config.HOME, "Lyrics" + File.separator);            File dir = Config.getConfig().getSaveLyricDir();            dir.mkdirs();            file = new File(dir, name);            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "GBK"));            bw.write(lyric);            bw.close();            info.setLyricFile(file);            log.info("保存完毕,保存在:" + file);        } catch (Exception exe) {            log.log(Level.SEVERE, "保存歌词出错", exe);        }    }    /**     * 设置此歌词是否起用了,否则就不动了     * @param b 是否起用     */    public void setEnabled(boolean b) {        this.enabled = b;    }    /**     * 得到此歌词保存的地方     * @return 文件     */    public File getLyricFile() {        return file;    }    /**     * 调整整体的时间,比如歌词统一快多少     * 或者歌词统一慢多少,为正说明要快,为负说明要慢     * @param time 要调的时间,单位是毫秒     */    public void adjustTime(int time) {        //如果是只有一个显示的,那就说明没有什么效对的意义了,直接返回        if (list.size() == 1) {            return;        }        for (Sentence s : list) {            s.setFromTime(s.getFromTime() - time);            s.setToTime(s.getToTime() - time);        }    }    /**     * 根据一个文件夹,和一个歌曲的信息     * 从本地搜到最匹配的歌词     * @param dir 目录     * @param info 歌曲信息      * @return 歌词文件     */    private File getMathedLyricFile(File dir, PlayListItem info) {        File matched = null;//已经匹配的文件        File[] fs = dir.listFiles(new FileFilter() {            public boolean accept(File pathname) {                return pathname.getName().toLowerCase().endsWith(".lrc");            }        });        for (File f : fs) {            //全部匹配或者部分匹配都行            if (matchAll(info, f) || matchSongName(info, f)) {                matched = f;                break;            }        }        return matched;    }    /**     * 根据歌的信息去初始化,这个时候     * 可能在本地找到歌词文件,也可能要去网络上搜索了     * @param info 歌曲信息     */    private void init(PlayListItem info) {        File matched = null;        for (File dir : Config.getConfig().getSearchLyricDirs()) {            log.log(Level.FINE, "正在搜索文件夹:" + dir);            //得到歌曲信息后,先本地搜索,先搜索HOME文件夹            //如果还不存在的话,那建一个目录,然后直接退出不管了            if (!dir.exists()) {                dir.mkdirs();            }            matched = getMathedLyricFile(dir, info);            //当搜索到了,就退出            if (matched != null) {                break;            }        }        log.info("找到的是:" + matched);        if (matched != null&&matched.exists()) {            info.setLyricFile(matched);            file = matched;            init(matched);        } else {            init("");        }    }    /**     * 根据文件来初始化     * @param file 文件     */    private void init(File file) {        BufferedReader br = null;        try {            br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "GBK"));            StringBuilder sb = new StringBuilder();            String temp = null;            while ((temp = br.readLine()) != null) {                sb.append(temp).append("\n");            }            init(sb.toString());        } catch (Exception ex) {            Logger.getLogger(Lyric.class.getName()).log(Level.SEVERE, null, ex);                    } finally {            try {                br.close();            } catch (Exception ex) {                Logger.getLogger(Lyric.class.getName()).log(Level.SEVERE, null, ex);            }        }    }    /**     * 是否完全匹配,完全匹配是指直接对应到ID3V1的标签,     * 如果一样,则完全匹配了,完全匹配的LRC的文件格式是:     * 阿木 - 有一种爱叫放手.lrc     * @param info 歌曲信息     * @param file 侯选文件     * @return 是否合格     */    private boolean matchAll(PlayListItem info, File file) {        String name = info.getFormattedName();        String fn = file.getName().substring(0, file.getName().lastIndexOf("."));        if (name.equals(fn)) {            return true;        } else {            return false;        }    }    /**     * 是否匹配了歌曲名     * @param info 歌曲信息     * @param file 侯选文件     * @return 是否合格     */    private boolean matchSongName(PlayListItem info, File file) {        String name = info.getFormattedName();        String rn = file.getName().substring(0, file.getName().lastIndexOf("."));        if (name.equalsIgnoreCase(rn) || info.getTitle().equalsIgnoreCase(rn)) {            return true;        } else {            return false;        }    }    /**     * 最重要的一个方法,它根据读到的歌词内容     * 进行初始化,比如把歌词一句一句分开并计算好时间     * @param content 歌词内容     */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -