zoukankan      html  css  js  c++  java
  • lrcdis (外挂式显歌词脚本)

    https://linuxtoy.org/archives/lrcdis.html
    http://www.oschina.net/p/lrcdis/
    http://code.google.com/p/lrcdis/downloads/list


    #!/bin/bash
    # Name:     lrcdis (外挂式显歌词脚本)
    # License:  GPLv3
    # Credit:   xiooli,solcomo,bones7456,oldherl  (2008-2009)
    # Encoding: UTF-8
    # Thanks to: 搜狗歌词搜索

    Version=090908
    #是否开启调试信息
    Debug=0
    Conf_file=~/.config/lrcdis.conf
    Cookie_file=/dev/shm/lrcdis-cookie-file-$USER-"`date +"%s.%N"`-$RANDOM"

    #=========================定义函数=============================

    INIT() {
        #程序初始化函数

        #没有参数,正确执行如果没有配置文件则会产生配置文件并加载配置,有配置文件则加载配置文件

        [ -f "$Conf_file" ] || cat<< EOF > "$Conf_file"
    #===================LRCDIS-CONFIG================
    #保存lrc文件的文件夹
    Lrcdir=~/.lyrics
    #显示模式: osd|notify|fifo|title|cli|kdialog|echo (将歌词输出到一个管道文件,以便用其他命令访问)
    Dismode=osd
    #播放器类型: mpd|mocp|muine|audacious|juk|amarok|exaile|gmusicbrowser|quodlibet|qmmp|rhythmbox|banshee|audacious2|xmms2
    Player=rhythmbox
    #获取歌曲名称方式: id3(id3标签方式)|filename(文件名方式)
    Readname=id3
    #自身时间发生器产生时间的间隔(最好小于1秒)
    Sleeptm=0.6
    #======================[cli]=====================
    #命令行显示时的参数
    #一屏显示行数
    Row=10
    #歌曲标题的颜色(见最后的颜色定义)
    Titlecolor=green
    #歌曲歌词的颜色(见最后的颜色定义)
    Lyricscolor=blue
    #==============[osd, notify & kdialog]=============
    #osd显示时的参数
    #osd显示位置:top, bottom
    Vposition=top
    #osd对齐位置:left, right, center
    Halignment=center
    #osd最长显示时间(超过则隐藏,单位毫秒?)
    Timeout=10000
    #span size
    Size=20000
    #字体颜色: green|white|blue|yellow|grey|...
    #注意,这个颜色与cli模式的颜色不是一回事
    Foreground=green
    #动画效果: off, on
    Animations=off
    #是否加新行,以免挡住panel等: off|on
    Addnewline=off
    #notify模式的图标文件名(只支持绝对路径)
    NotifyIcon=""
    #kdialog显示的timeout
    Ktimeout=5
    #====================[lrc]======================
    #从何处下载歌词: SOGOU_URI,BAIDU_URI,QIANQIAN_URI
    Uri=SOGOU_URI
    #是否检查歌词文件,yes/no,yes将会检查歌词文件是否正确,若不正确则重新下载歌词
    Checklrc=yes
    #下载歌词的最大重试次数,不宜过大
    Maxdowntimes=4
    #================================================
    #定义颜色(仅在cli模式下使用)
    black="30"
    red="31"
    green="32"
    yellow="33"
    blue="34"
    magenta="35"
    cyan="36"
    white="37"
    #======================END========================
    EOF

        . "$Conf_file"
    }

    DEBUGECHO() {
        [ "$Debug" = 1 ] && echo "  $@" >&2
    }

    DO_NAME() {
         1 argument, the filename

         removing .mp3/.wma/.ogg/.ape/.flac etc.
        local    a
        a="`basename "$1"`"
        #理论上说以 . 分隔的最后那部分是扩展名
        a="${a%.[a-zA-Z0-9]*}"
        #a="${a/%.mp3/}"; a="${a/%.MP3/}"
        #a="${a/%.wma/}"; a="${a/%.WMA/}"
        #a="${a/%.ogg/}"; a="${a/%.OGG/}"
        #a="${a/%.ape/}"; a="${a/%.APE/}"
        #a="${a/%.flac/}"; a="${a/%.FLAC/}"
        # 去掉前置的一位或两位数字和".",一般是专辑中的序号
        a="${a/#[0-9]./}"; a="${a/#[0-9][0-9]./}"
        echo "$a"
    }

    USAGE() {
        #显示帮助信息的函数

        #没有参数,执行显示帮助信息

        cat << EOF
    lrcdis $Version (http://code.google.com/p/lrcdis)
    用法: $0 [选项]
    选项:

        -C, --config <配置文件路径>
            指定配置文件 (默认: ~/.config/lrcdis.conf)
        -s, --save-dir <保存目录>
            指定歌词的保存目录 (默认: ~/.lyrics)
        -d, --download <歌曲名>
            仅下载歌词, 保存至歌词目录
        -E, --edit-conf
            进入编辑配置文件的模式
        -p, --player <播放器>
            优先检查此播放器,如果此播放器未运行则继续检查其他播放器
        -m, --mode <显示模式>
            以 <显示模式> 显示歌词,详细参数见下面:
        -m osd
            以osd模式显示歌词(needs gnome-osd)
        -m notify
            以notify模式显示歌词(needs notify-send)
        -m fifo
            将歌词输出到管道文件/dev/shm/lrcfifo
        -m title
            将歌词输出到终端的标题中(支持大多数终端)
        -m kdialog
            将歌词以kdialog的通知模式输出
        -m echo
            将歌词以普通echo模式输出
        -m cli
            以cli模式显示歌词
        -D, --debug
            Debug mode
        -h, --help
            显示本帮助信息并退出
        -v, --version
            显示版本号并退出
    备注:不加任何选项则以 $Conf_file 为配置文件初始化运行
    EOF
    }

    PLAYER_USERS() {
        #一个参数,播放器进程名,返回该进程可能对应的用户ID.
        id -u | tr -d " "
        if [ "$1" = "mpd" ];then
            echo -n ",0" #mpd以root运行算合法
            if id -u mpd >/dev/null 2>&1 ;then
                echo -n ","
                id -u mpd | tr -d " " #mpd以mpd用户运行算合法
            fi
        fi
    }

    PLAYER_RUNNING(){
        #判断播放器进程是否存在
        #一个参数, 播放器名
        #返回0表示进程存在,1表示不存在
        {
        if [ "$1" = "quodlibet" ]; then
            pgrep -fx "python `which quodlibet`" -u "`PLAYER_USERS "$1"`" && return 0
        elif [ "$1" = "banshee" ]; then
            pgrep -x "banshee-1" -u "`PLAYER_USERS "$1"`" && return 0
        elif [ "$1" = "xmms2" ]; then
            pgrep -x "xmms2d" -u "`PLAYER_USERS "$1"`" && return 0
        else
            pgrep -x "$1" -u "`PLAYER_USERS "$1"`" && return 0
        fi
        return 1
        } >/dev/null 2>&1
    }

    CHECK_PLAYER() {
        #自动检查播放器类型的函数

        #没有参数,返回播放器类型
        
        local players i

        #所有被支持的播放器都保存下面的字符串里面
        #gmusicbrowser需要perl-net-dbus让其支持dbus通信才可以
        players="rhythmbox audacious juk amarok amarokapp exaile banshee gmusicbrowser quodlibet qmmp mocp mpd muine mplayer audacious2 xmms2"
        if PLAYER_RUNNING "$Player";then
            echo -n "$Player"
        else
            for i in $players;do
                DEBUGECHO "$Player   $i"
                if PLAYER_RUNNING "$i";then
                    echo -n "$i"|sed "s/amarokapp/amarok/"
                    break
                fi
            done
        fi
    }

    BAIDU_URI() {
        #得到百度歌词文件的下载URL

        #两个参数,$1:gbk编码的歌曲名的urlencode; $2:提取的下载的链接序数
        local nm page items urlstmp
        page="$((${2:-1}/10))"
        items="${#Urls[@]}";[ "$items" = "0" ] && items="1"
        Lrcurl0="http://www.baidu.com/s?&wd=${1}+filetype:lrc&pn=${page}"
        [ "$Lrcurl" != "$Lrcurl0" ] && Lrcurl="$Lrcurl0"
        && Htm="`wget "$Lrcurl"  -q -T 10 -O- 2>/dev/null | iconv -f gbk`"
        if [ ! "${Urls[@]}" ] || [ "$2" -gt "$items" ]; then
               ((page++))
               Urls=($(echo $Htm|grep -o "http[^<>]*.lrc"))
               fi
        DEBUGECHO "BAIDU_URI $Lrcurl0 ${Urls[@]}"
        nm="$((${2:-1}%$items))";((nm--));[ "$nm" -lt 0 ] && nm=0
        [ "${Urls[$nm]}" = "" ] || echo -n "${Urls[$nm]}"
    }

    SOGOU_URI() {
        #得到搜狗歌词文件的下载URL

        #两个参数,$1:gbk编码的歌曲名的urlencode; $2:提取的下载的链接序数
        #(用于第一个链接的歌词不对时重新下载下一个链接)

        local a page nm
        page="$((${2:-1}/5))"
        nm="$((${2:-1}%5))"
        #先获取一个cookie
        [ ! -s "$Cookie_file" ] &&
        wget --keep-session-cookies --save-cookies "$Cookie_file" "http://mp3.sogou.com" -O- >/dev/null 2>&1
        Lrcurl0="http://mp3.sogou.com/gecisearch.so?query=${1}&page=${page}"
        [ "$Lrcurl" != "$Lrcurl0" ] && Lrcurl="$Lrcurl0"
        && Htm="`wget --load-cookies "$Cookie_file" --save-cookies "$Cookie_file" "$Lrcurl" -q -T 10 -O- 2>/dev/null | iconv -f gbk`"
        a="`echo "$Htm" | grep -Fim"${nm}" "downlrc"|awk -F\" '{print $2}'|tail -n1`"
        DEBUGECHO "A $Lrcurl0 $a"
        [ "$a" = "" ] || echo -n 'http://mp3.sogou.com/'"$a"
    }

    QIANQIAN_URI(){
        #得到千千歌词文件的下载URL
        local htm
        DEBUGECHO "$1 | $2"
        htm="`wget "http://www.qianqian.com/lrcresult.php?qfield=1&pageflag=1&qword="$1"" -q -T 10 -O- 2>/dev/null`"
        a="http://www.qianqian.com/""`echo "$htm" | grep -Fim1 lrcresult_frame | awk -F\" '{print $6}'`"
        DEBUGECHO "A $a"
        b="`wget "$a" --referer=www.qianqian.com -O- -q | grep -Fim1 downfromlrc | awk -F\" '{print $6}'`"
        DEBUGECHO "B $b"
        if [ "$b" != "" ]; then
            echo -n 'http://www.qianqian.com/'"$b";
        else
            htm="`wget "http://www.qianqian.com/lrcresult.php?qfield=3&pageflag=1&qword="$1"" -q -T 10 -O- 2>/dev/null`"
            a="http://www.qianqian.com/""`echo "$htm" | grep -Fim1 lrcresult_frame | awk -F\" '{print $6}'`"
            DEBUGECHO "A $a"
            b="`wget "$a" --referer=www.qianqian.com -O- -q | grep -Fim1 downfromlrc | awk -F\" '{print $6}'`"
            DEBUGECHO "B $b"
            if [ "$b" != "" ]; then
                echo -n 'http://www.qianqian.com/'"$b";
            else
                htm="`wget "http://www.qianqian.com/lrcresult.php?qfield=3&pageflag=1&qword="$2"" -q -T 10 -O- 2>/dev/null`"
                a="http://www.qianqian.com/""`echo "$htm" | grep -Fim1 lrcresult_frame | awk -F\" '{print $6}'`"
                DEBUGECHO "A $a"
                b="`wget "$a" --referer=www.qianqian.com -O- -q | grep -Fim1 downfromlrc | awk -F\" '{print $6}'`"
                DEBUGECHO "B $b"
                if [ "$b" != "" ]; then
                    echo -n 'http://www.qianqian.com/'"$b";
                fi
            fi
        fi
    }

    DOWNLRC() {
        #下载歌词的函数

        #参数两个,$1 (str): 歌曲名字; $2 (int):欲提取的下载的链接序数
        #没有返回值,正确执行会下载一个 lrc 文件至 Lrcdir

        local nm link full_link gb file

        nm="$1"
        [ ! -d "$Lrcdir" ] && mkdir -p "$Lrcdir"
        file="$Lrcdir/$nm.lrc"
        
        #将歌曲名字转换为urlencode,utf-8的locale必须先转换为gbk的编码
          gb="$(echo -n "$nm" | iconv -c -t gbk | od -t x1 -A n -w1000|tr " " "%")"

        #从歌词搜索里面找出当前歌曲的歌词下载页,默认从搜狗下
          link="`eval "${Uri:-SOGOU_URI} "$gb" "$2""`"
        DEBUGECHO "Link: $link"
        [ "$link" ] && {
            if [ "$Uri" = "QIANQIAN_URI" ];then
                #千千的需要referer,且不需要转码.
                  wget "$link" --referer=www.qianqian.com -T 5 -t 2 -q -O - | tr -d " " > "$file"
              else
                wget --load-cookies "$Cookie_file" "$link" -T 5 -t 2 -q -O -|iconv -f gbk -c | tr -d " " > "$file"
            fi
            { echo ''; cat "$file"; echo '';} > /tmp/lrcdisTMP.xml
            xmllint /tmp/lrcdisTMP.xml --encode UTF-8 2>/dev/null > /tmp/lrcdisTMP.lrc && {
                cat /tmp/lrcdisTMP.lrc | head -n -1 | tail -n +3 > "$file"
            }
            rm /tmp/lrcdisTMP* &>/dev/null
        }
    }

    CHECK_LRC() {
        #检查歌词文件是否正确
        
        #参数三个,$1: 歌词文件路径; $2: 当前歌曲的标题(包含题目和/或艺人)
        # $3:检查是否放水(yes严格执行,no则总返回合格)
        #正确返回字符串LRC-RIGHT,反之LRC-WRONG
        
        local ti0 ti1 ar0 ar1 judge
        if [ "${3:-yes}" = "yes" ];then
            ti0="`cat "$1"|grep -o "[ti:[^[]*]"|tr -d "[]"|tr [:upper:] [:lower:]`";ti0="${ti0/ti:}"
            ar0="`cat "$1"|grep -o "[ar:[^[]*]"|tr -d "[]"|tr [:upper:] [:lower:]`";ar0="${ar0/ar:}"
            ti1="${2/}
                tmptm=${tm/}
            tmptm=${tm/Dismode=$Dismode/" "$Conf_file"
        ;;
        *)
        echo "无效的显示模式: $Dismode ,用默认的 echo 模式替代." >&2
        ;;
    esac
    Player="`CHECK_PLAYER`"
    if [ "$Player" ];then
        sed -i "s/^Player=.*/Player=$Player/" "$Conf_file"
    else
        DIS_WORDS E "未发现被支持的播放器进程!"
        [ "$Dismode" = cli ] && echo
        exit
    fi
    Title="`GET_TITLE $Player $Readname`"
    pltm="`GET_PLTM $Player`"
    #TODO 目前PlayerStat的值只有Unknow和Playing,以后可以考虑加入Pause等状态.
    PlayerStat="Unknow"

    GET_STAT |while read line0;do
        [ "$Dismode" = "fifo" -a -p "/dev/shm/lrcfifo" ] && echo -n "">/dev/shm/lrcfifo #防止读lrcfifo时等待 amoblin 4.14 9:49 #非fifo模式不必要生成该文件 bones7456
        DEBUGECHO "GET_STAT: $line0<<"
        [ "$line0" = "$line1" ] && continue
        line1="$line0"
        read op arg <<< "$line0"
        [ "$op" = "Error" ] && DIS_WORDS E "$arg"
        [ "$op" = "Title" ] && [ "$title" != "$arg" ] && [ "$arg" != "" ] && {
            title="$arg"
            Title="$arg"
            DIS_WORDS T "$Title";
            CHECK_AND_DOWN_LRC "$Title" "$Checklrc"
            if [ -f "$Lrcdir/$Title.lrc" ]; then
                lrc="$(< "$Lrcdir/$Title.lrc")"
            else
                lrc=""
                DIS_WORDS E "未能下载歌词"
            fi
            #处理 offset
            offset="`echo $lrc|awk -F"offset:" '{gsub("].*$","",$2);print $2/1000}'`";offset=${offset:-0}
        }
        [ "$op" = "Time" ] && [ "$lrc" ] && {
            arg="${arg:-0}";
            arg="`eval "echo|awk '{print "$arg+$offset"}'"`"
            arg=${arg//.*/};arg=${arg:-0}
            arg="`printf '%.2d:%.2d' $(($arg/60)) $(($arg`))`"
             DISPLAY "$arg" "$lrc"
        }
    done
  • 相关阅读:
    Ecshop去掉模版中随机出现Ecshop版权的方法
    ecshop邮件订阅按“订阅”没反应
    ecshop开发帮助
    ecshop循环计数
    ECSHOP购物车页面显示商品简单描述
    ecshop 函数列表大全
    ecshop 商品分类页 取得当前分类下的子分类方法
    ecshop调用指定分类和个数的文章列表
    thymeleaf中的th:assert用法
    thymeleaf中的模板布局
  • 原文地址:https://www.cnblogs.com/lixuebin/p/10814525.html
Copyright © 2011-2022 走看看