Linux手機DIY.Shell應用擴展一 隨機來電鈴聲(E680系列)

  Linux手機DIY.Shell應用擴展一.隨機來電鈴聲(E680系列)
   草木瓜
   2007-03-18
   一、什麽是Shell
   在開始正題前,總習慣于從網上抄一些東東,來「豐富」下文章的內容。
   Shell是一種具備特殊功能的程序,它是介于使用者和 UNIX/Linux 操作系統核
  心程序(kernel)間的一個接口。換而言之,就是你平常要想操作 UNIX/Linux 的話,
  就需要通過Shell來進行。
   爲什麽我們說 Shell 是一種介于系統核心程序與使用者間的中介者呢?讀過操
  作系統概論的讀者們都知道操作系統是一個系統資源的管理者與分配者,當用戶有請
  求時,得向系統提出;從操作系統的角度來看,它也必須防止使用者因爲錯誤的操作
  而造成系統的損害。衆所周知,對計算機系統下命令得通過預定義的命令或程序。
   Shell本身就是一個程序,一個已經由別人寫好並且編譯過的程序,它從輸入設
  備讀取命令,將其轉換爲計算機操作系統可以理解的機器碼,然後執行。
  各種操作系統其實都有它自己的Shell,以大家容易理解的DOS爲例,它的Shell
  就是command.com文件。Windows下的DOS命令dir,copy等之類都是通過其解釋執行
  的。
   Unix/Linux系統下Shell也有多種。常用的有Bourne Shell(sh)、C-Shell
  (csh)、Korn Shell(ksh)和Bourne Again Shell(bash)。
   Bourne Shell(sh)是AT&T Bell實驗室的Steven Bourne爲AT&T的Unix開發的,
  它是Unix的默認Shell,也是其它Shell的開發基礎。Bourne Shell在編程方面相當
  優秀,但在處理與用戶的交互方面不如其它幾種Shell。
   C Shell(csh)是加州伯克利大學的Bill Joy爲BSD Unix開發的,與sh不同,它
  的語法與C語言很相似。它提供了Bourne Shell所不能處理的用戶交互特征,如命令
  補全、命令別名、曆史命令替換等。但是,C Shell與BourneShell並不兼容。
   Korn Shell(ksh)是AT&T Bell實驗室的David Korn開發的,它集合了C Shell
  和Bourne Shell的優點,並且與Bourne Shell向下完全兼容。Korn Shell的效率很
  高,其命令交互界面和編程交互界面都很好。
   Bourne Again Shell(bash)是自由軟件基金會(GNU)開發的一個Shell,它是Linux
  系統中一個默認的Shell。Bash不但與Bourne Shell兼容,還繼承了C Shell、Korn
  Shell等衆多優點。
  <Linux手機DIY系列:http://blog.csdn.net/liwei_cmg/category/241839.aspx>
   二、隨機來電鈴音的總體思路
   隨機來電鈴這東西早就有人實現,方法也是多種多樣的。具體這個東西的作用是
  仁者見仁,智者見智。個人覺得偶爾用用感覺也不錯,重要的是挖掘Shell擴展手機
  應用的潛力。而且Shell對大多數人來說,上手也比較容易,相關資料也十分多。夏新
  E600和飛利浦968的安裝包就是通過簡單的一些Shell來實現。可以說,研究這些手機
  最爲關鍵的部分,就是Shell!
   現在大多數Linux智能手機,鈴音配置都是以文本格式存在,可見理論上直接修改
  這類文件就可以輕松實現對短信息和手機鈴聲進行更改。但在實際操作過程中發現,直
  接去修改這個文件的話,E680是不能夠即時生效的,需要重新設置刷新才行。
   後經一些嘗試發現,先設置好鈴音的配置文件,修改實際的對應鈴聲文件最爲有效。
  
   AlertRingTone1 = /mmc/mmca1/Music/Ring/ring.mp3
   AlertRingTone2 = /mmc/mmca1/Music/Ring/ring.mp3
   AlertRingerIDs = 0
   AlertStyleIconDir = /usr/language/alertStyle/
   AlertSystemVolume = 10
   AlertTextMsg = /mmc/mmca1/Music/Ring/message.mp3
  
   [AlertTextMsg]對應短信息鈴聲,[AlertRingTone1]對應來電鈴聲,這個配置文
  件我不去改它,動態修改的是ring.mp3,message.mp3的實際文件。修改的過程僅僅就是
  mv Artist.mp3 ring.mp3這麽簡單。
   下面需要解決的就是修改時機和隨即性兩個問題。我這裏顯然是一個在後台不斷循
  環運行的Shell腳本,當短信息或者來電時,系統會啓動alterprocss這個進程,這個腳
  本自然能檢測的這個進程相關信息,並修改相應的鈴聲文件。至于隨機性,其實來電本
  身就是隨機事件,這裏只用了一個僞隨即方法,即根據來電的時間信息,進行鈴聲文件
  選擇。
   三、腳本文件全內容
  001 #!/bin/bash
  002
  003
  004 #當前路徑
  005 Path_Current=/mmc/mmca1/soft/ring
  006
  007 #日志文件
  008 File_Log=$Path_Current/log.txt
  009
  010 #來電鈴聲目錄
  011 if [ ! -f $Path_Current/ring.txt ]
  012 then
  013 echo /mmc/mmca1/Music/Game > $Path_Current/ring.txt
  014 fi
  015 Path_Ring=`cat $Path_Current/ring.txt`
  016
  017 #短信息鈴聲目錄
  018 if [ ! -f $Path_Current/msg.txt ]
  019 then
  020 echo /mmc/mmca1/Music/Game > $Path_Current/msg.txt
  021 fi
  022 Path_Message=`cat $Path_Current/msg.txt`
  023
  024 #固定來電消息文件目錄
  025 if [ ! -f $Path_Current/default.txt ]
  026 then
  027 echo /mmc/mmca1/Music/Ring > $Path_Current/default.txt
  028 IsReset=1
  029 else
  030 IsReset=0
  031 fi
  032 Path_Default=`cat $Path_Current/default.txt`
  033
  034
  035 #系統預定義短信最長秒
  036 if [ ! -f $Path_Current/maxmessage.txt ]
  037 then
  038 echo "15" > $Path_Current/maxmessage.txt
  039 fi
  040 Var_MsgMaxSec $Path_Current/maxmessage.txt`
  041
  042 #指定的短消息鈴聲
  043 Default_MessageFile=$Path_Default/message.mp3
  044 #指定的電話鈴聲
  045 Default_RingFile=$Path_Default/ring.mp3
  046
  047
  048 #指令集
  049 File_Busybox=/mmc/mmca1/tmp/busybox
  050 #臨時處理配置的文件
  051 File_Sed=$Path_Current/tmpsed.txt
  052 #臨時文件大聲
  053 File_TmpRingLoud=$Path_Current/tmpRingLoud.pts
  054 #臨時文件輕聲
  055 File_TmpRingSoft=$Path_Current/tmpRingSoft.pts
  056
  057 #臨時進程文件
  058 File_TmpProcess=$Path_Current/tmpgrep.txt
  059
  060
  061 #臨時可供隨機的文件列表
  062 FileList_Tmp=filelist.txt
  063
  064 #系統大聲的配置文件
  065 File_RingLoud=/ezxlocal/download/appwrite/setup/RingLoud.pts
  066 #系統輕聲的配置文件
  067 File_RingSoft=/ezxlocal/download/appwrite/setup/RingSoft.pts
  068
  069
  070 echo "====== Random Ring ======" >> $File_Log
  071 echo `$File_Busybox date` " : Start" >> $File_Log
  072
  073
  074 if [ "$IsReset" = "1" ]
  075 then
  076
  077 echo `$File_Busybox date` " : Create New PtsFile" >> $File_Log
  078
  079 #生成新的配置文件
  080 echo "#!/bin/sed -f" > $File_Sed
  081 echo "/AlertRingTone1/ c\\" >> $File_Sed
  082 echo "AlertRingTone1 = $Default_RingFile" >> $File_Sed
  083 echo "/AlertRingTone2/ c\\" >> $File_Sed
  084 echo "AlertRingTone2 = $Default_RingFile" >> $File_Sed
  085 echo "/AlertTextMsg/ c\\" >> $File_Sed
  086 echo "AlertTextMsg = $Default_MessageFile" >> $File_Sed
  087
  088 #echo $File_Sed " " $File_RingLoud
  089 $File_Sed $File_RingLoud > $File_TmpRingLoud
  090 $File_Sed $File_RingSoft > $File_TmpRingSoft
  091
  092 cp -f $File_TmpRingLoud $File_RingLoud
  093 cp -f $File_TmpRingSoft $File_RingSoft
  094
  095 fi
  096
  097 #$File_Busybox renice -20 $$
  098 echo $$ > $Path_Current/proc.txt
  099
  100 echo `$File_Busybox date` " : ProcessID " $$ >> $File_Log
  101
  102 while
  103
  104 do
  105
  106 ProcID_Alert=`pidof alertprocess`
  107
  108 if [ "$ProcID_Alert" = "" ]
  109 then
  110
  111 echo "Runing ..."
  112 sleep 1s
  113
  114 else
  115
  116 echo `$File_Busybox date` " : AlertProcessID " $ProcID_Alert >> $File_Log
  117
  118 ps -ef | grep ".mp3" | grep -v grep > $File_TmpProcess
  119
  120 if grep "ring.mp3" $File_TmpProcess | grep -v grep
  121 then
  122 HaveSession="PHONE"
  123 echo `$File_Busybox date` " : Have Phone " >> $File_Log
  124 fi
  125
  126 if grep "message.mp3" $File_TmpProcess | grep -v grep
  127 then
  128 HaveSession="MESSAGE"
  129 echo `$File_Busybox date` " : Have Message " >> $File_Log
  130 fi
  131
  132 #循環變量
  133 i=0
  134
  135 while [ ! "$ProcID_Alert" = "" ]
  136 do
  137 ProcID_Alert=`pidof alertprocess`
  138 sleep 1s
  139 #echo "sleep now!"
  140
  141 if [ "$HaveSession" = "MESSAGE" ]
  142 then
  143 if [ "$i" = "$Var_MsgMaxSecond" ]
  144 then
  145 kill -9 `pidof alertprocess`
  146 else
  147 i=$(($i+1))
  148 fi
  149 fi
  150
  151 done
  152
  153 Value_Base=`$File_Busybox date -u '+%M%S'`
  154
  155 #echo "OK"
  156
  157 if [ "$HaveSession" = "PHONE" ]
  158 then
  159
  160 #處理隨機來鈴
  161 cd $Path_Ring
  162 rm $FileList_Tmp
  163 find . -name '*[m,M][p,P]3' | sed 's/^.//g' > $FileList_Tmp
  164 Max_Count=`$File_Busybox wc $FileList_Tmp | $File_Busybox awk '{print $1}'`
  165 Value_Round=$(($Value_Base % $Max_Count + 1))
  166
  167 #echo $Value_Round
  168
  169 Name_NextRing=`sed -n "$Value_Round p" $Path_Ring/$FileList_Tmp`
  170 rm $FileList_Tmp
  171
  172 if [ -f $Default_RingFile ]
  173 then
  174
  175 if [ -f $Path_Current/prering.txt ]
  176 then
  177 #echo
  178 mv "$Default_RingFile" "`cat $Path_Current/prering.txt`"
  179 echo `$File_Busybox date` " : mv $Default_RingFile" "`cat $Path_Current/prering.txt`" >> $File_Log
  180 else
  181 rm "$Default_RingFile"
  182 echo `$File_Busybox date` " : rm $Default_RingFile" >> $File_Log
  183 fi
  184
  185 fi
  186
  187 #echo
  188 mv "$Path_Ring$Name_NextRing" "$Default_RingFile"
  189 echo $Path_Ring$Name_NextRing > $Path_Current/prering.txt
  190 echo `$File_Busybox date` " : mv $Path_Ring$Name_NextRing" "$Default_RingFile" >> $File_Log
  191
  192 fi
  193
  194 if [ "$HaveSession" = "MESSAGE" ]
  195 then
  196
  197 #處理隨機短信息
  198 cd $Path_Message
  199 rm $FileList_Tmp
  200 find . -name '*[m,M][p,P]3' | sed 's/^.//g' > $FileList_Tmp
  201 Max_Count=`$File_Busybox wc $FileList_Tmp | $File_Busybox awk '{print $1}'`
  202 Value_Round=$(($Value_Base % $Max_Count + 1))
  203
  204 #echo $Value_Round
  205
  206 Name_NextMessage=`sed -n "$Value_Round p" $Path_Message/$FileList_Tmp`
  207 rm $FileList_Tmp
  208
  209
  210 if [ -f $Default_MessageFile ]
  211 then
  212
  213 if [ -f $Path_Current/premsg.txt ]
  214 then
  215 #echo
  216 mv "$Default_MessageFile" "`cat $Path_Current/premsg.txt`"
  217 echo `$File_Busybox date` " : mv $Default_MessageFile" "`cat $Path_Current/premsg.txt`" >> $File_Log
  218 else
  219 rm "$Default_MessageFile"
  220 echo `$File_Busybox date` " : rm $Default_MessageFile" >> $File_Log
  221 fi
  222
  223 fi
  224
  225 #echo
  226 mv "$Path_Message$Name_NextMessage" "$Default_MessageFile"
  227 echo $Path_Message$Name_NextMessage > $Path_Current/premsg.txt
  228 echo `$File_Busybox date` " : mv $Path_Message$Name_NextMessage" "$Default_MessageFile" >> $File_Log
  229
  230
  231 #kill -9 `pidof alertprocess`
  232 #cp -f $Path_Ring/$Name_NextRing
  233
  234 fi
  235
  236
  237 sleep 1s
  238
  239 fi
  240
  241
  242 done
  四、腳本文件說明
   這個腳本雖然有點注釋,但乍一看還是有點亂,這裏作一些補充。
  
   腳本主要分「變量定義和預處理」<001-100>「主循環」<101-242>兩部分。
  
   A.「變量定義和預處理」
  
   這個腳本命名隨意,但是存放路徑必須與<005>所定義的路徑相同。(注:這裏也
  完全可以用`pwd`來代替。)
   腳本運行後會在當前路徑下生成如下文件:
  
   log.txt 記錄整個運行日志
  
   ring.txt 記錄來電鈴音隨機選擇的目錄,目前腳本會包含該目錄的所有子
   目錄
  
   msg.txt 記錄短信息鈴音隨即選擇的目錄,同上
  
   default.txt 記錄來電的固定文件的目錄,
  
   maxmessage.txt 記錄短信的最長響鈴時間
  
   此外還産生了一些tmp的臨時文件。
  
   B.「主循環」
   系統總會不斷執行<106>這條語句,經過一些嘗試,使用pidof效率是最高的,
  否則後台一旦起了Shell,系統整體速度會略有減慢。
   Shell進程運行後,一旦有來電,會自動執行<114>下面的內容,<118>-<130>
  進行進程信息提取,判斷是短信息還是來電。<132>-<151>是對短信的特別處理,
  如超過最大響鈴時間,即終止響鈴。
   <157>-<234>是對隨即鈴聲文件的真正處理。即每次來電,將文件mv,從而保
  證下次響鈴的隨機性。
   這個腳本主要用了busybox,原因是系統的原來的功能比較有限。
   五、後記
   本腳本涉及的命令是十分常見的:ps,sed,find,grep,date等,所要注意的是
  E680是用bash,對于$(())的數值運算表達方式,其它shell並不能通用。
   對于Linux手機新手來說,現在只需要一些耐心去消化腳本所使用的Shell命令
  和Shell規範。