聲音提示和震動提示的開發(fā)
聲音提示可以采用兩種方法:一種是利用系統(tǒng)自帶的CoeSoundPlayer類來實現(xiàn)單音鈴聲的播放;另一種則是利用S60提供的多媒體框架CMda*類來實現(xiàn)音頻播放。
關(guān)于聲音提示的使用
CoeSoundPlayer類使用
該類聲明于coesndpy.h頭文件,庫是cone.lib,最簡單的使用莫過于如下格式的代碼應(yīng)用
TBaSystemSoundType a(KSystemSoundMessageUID);
CoeSoundPlayer::PlaySoundNow(a);
在以上代碼的使用時,第一行聲明一個系統(tǒng)tone的類型,該類型聲明在bassnd.h文件中,同時在mmp中加上bafl.lib庫文件。通常這種簡單應(yīng)用,在模擬器上能夠聽到聲音(3rd MR版本的模擬器上都聽不到聲音),但是在真機上,基本聽不到聲音,一個原因據(jù)說是默認的缺省音量被置成了KSystemSoundDefaultVolume,其值最大可以到100(我親測的結(jié)果是最小為0,沒有聲音,最大只能到10,超過10之后和傳負值一樣都會報MMFAudioClient 4的錯誤,程序也會Crash。所以關(guān)于這點最好還是有高人指點下)。另外bassnd.h中定義的類型還有KSystemSoundRingUID, KSystemSoundAlarmUID, KUidSystemSoundError, KUidSystemSoundEvent等,具體的效果,可以自己親測下。
稍微復(fù)雜一點的應(yīng)用代碼如下:
TBaSystemSoundType soundType(KSystemSoundMessageUID);
//TBaSystemSoundInfo::TTone soundTone(aFrequency, aDuration);
TBaSystemSoundInfo::TTone soundTone(1500, 3*1000*1000);
TBaSystemSoundInfo soundInfo(soundType, soundTone);
BaSystemSound::SetSoundL(CCoeEnv::Static()->FsSession(), soundInfo);
CoeSoundPlayer::PlaySoundNow(soundType);
在這里,我對音調(diào)不是很懂,但是aFrequency的值,經(jīng)人測試100到3400是工作正常,效果很好(可能1000到3000最好), 3600到3800就變?nèi)趿耍偻系?/span>4000基本上已經(jīng)聽不到了。這種方法一般在真機上還是可以感受出來的,并非像第一種情況,只有模擬器上有效果。
只是長時間播放簡單的音調(diào)估計很刺耳,那么我們就可以通過事先設(shè)計好的rng文件來進行播放單音鈴聲,具體代碼如下:
_LIT(KRingToneFileName1, "\\Data\\Sounds\\simple\\alarm.rng");
const TInt KRingingTypeSilent = 4; // Silent
TInt tRingingType (0);
CRepository* tRepository = CRepository::NewLC(KCRUidProfileEngine);
User::LeaveIfError( tRepository ->Get(KProEngActiveRingingType, tRingingType ) );
if ( tRingingType != KRingingTypeSilent )
{
TBaSystemSoundType soundType(KSystemSoundRingUID);
TBaSystemSoundName soundName(KRingToneFileName1);
CompleteWithAppPath(soundName);
TBaSystemSoundInfo soundInfo(soundType, soundName, 10,
KSystemSoundDefaultPriority);
BaSystemSound::SetSoundL(CCoeEnv::Static()->FsSession(), soundInfo);
CoeSoundPlayer::PlaySoundNow(soundType);
//CoeSoundPlayer::PlaySound(soundType);
}
CleanupStack::PopAndDestroy(); // tRepository
使用以上代碼需要注意的是alarm.rng文件必須要有,否則會沒有聲音傳出,該文件在FP2版本的模擬器路徑下沒有,可以在S60_3rd_MR\Epoc32\release\winscw\udeb\z\system\sounds\simple下找到,并將其拷貝到相應(yīng)的epoc32\release\winscw\udeb\z\system\sounds\simple下面即可。
注:另外,在這里雖然對情景模式是否靜音進行了判斷,其實不判斷也是可以的,因為情景模式設(shè)為靜音,仍然是可以播放出聲音來的。這點很不同于震動。
多媒體框架的使用
S60的MMF(多媒體框架)提供了對音頻進行播放、錄制和格式轉(zhuǎn)換等功能函數(shù),具體的功能類如下:
CMdaAudioPlayerUtility:音頻播放;
CMdaAudioRecorderUtility:音頻錄制;
CMdaAudioConvertUtility:音頻格式轉(zhuǎn)換;
CMdaAudioToneUtility:音調(diào)播放
CMdaAudioInputUtility/ CMdaAudioOutputUtility:音頻流操作
對于這一塊內(nèi)容的介紹在靈活使用EMCCsoft提供的AudioPlayer例子程序就會比較清楚,在這里就不多做展開了。唯一需要提醒的是,相應(yīng)的回調(diào)接口虛函數(shù)一定要實現(xiàn),否則不好控制。另設(shè)置音量的函數(shù)SetVolume也是只能在0~10之間,否則也會報MMFAudioClient 4錯誤。
在用CMdaAudioPlayerUtility進行音樂文件比如*.wav格式播放時,假如一個文件還沒有播放完,又開始播放一個新文件,也會引發(fā)MMFAudioClient 4的錯誤。
關(guān)于震動提示的使用
震動這個接口的發(fā)展歷史很奇特,Symbian OS v8.x之前沒有提供震動接口,之后開始使用CVibraControl類提供震動接口,而在Symbian OS v9.x之后在保留原有接口基礎(chǔ)上又提供了新的CHWRMVibra類來提供震動接口。
網(wǎng)上的代碼很多,常見形式如下:
// for S60 2nd FP2 and FP3
#include <vibractrl.h> // CVibraControl, VibraCtrl.lib
void DoVibrateL( TUint16 aDuration )
{
CVibraControl* control = VibraFactory::NewL();
// get vibration setting in the user profile
if ( CVibraControl::EVibraModeON == control->VibraSettings() )
{
control->StartVibraL( aDuration );
}
delete control;
control = NULL;
}
// for S60 3rd
#include <hwrmvibra.h> // CHWRMVibra, HWRMVibraClient.lib
void DoVibrateL( TInt aDuration )
{
CHWRMVibra* vibra = CHWRMVibra::NewLC();
// get vibration setting in the user profile
if ( CHWRMVibra::EVibraModeON == vibra->VibraSettings() )
{
vibra->StartVibraL( aDuration );
}
CleanupStack::PopAndDestroy( vibra );
}
事實上如果原封不動拷貝如上代碼是實現(xiàn)不了震動功能的,因為不管是CHWRMVibra還是CVibraControl對象在被新建并調(diào)用完StartVibraL函數(shù)之后,立即就被析構(gòu)了,因為StartVibraL有類似異步函數(shù)的功能,并非阻塞在持續(xù)時間之內(nèi)才會返回,所以對象還沒起振就刪除了。
震動功能的實現(xiàn)代碼雖然簡單,但是要想震起來還是有點麻煩的,為此我在使用時除了以上問題,還遇到其它幾個問題:
當(dāng)前情景模式里震動提示設(shè)置為關(guān)時,顯然會因為
if ( CVibraControl::EVibraModeON == control->VibraSettings() )
if ( CHWRMVibra::EVibraModeON == vibra->VibraSettings() )
兩個條件判斷沒通過而沒有真實調(diào)用StartVibraL函數(shù),那么我如果將判斷去掉,始終讓其調(diào)用StartVibraL函數(shù)應(yīng)該也會震動的吧?
結(jié)果是震動函數(shù)返回-21即KErrAccessDenied(拒絕接受),這和播放聲音提示時的效果完全兩樣,所以說讀情景配置模式里的參數(shù)在這里完全是必要的。
好,那就加判斷,總算執(zhí)行到了StartVibraL (TUint16 aDuration, TInt aIntensity)函數(shù),假如在這里aDuration超過KHWRMVibraMaxDuration,或者aIntensity不在-100到100之間(這里的強度值是馬達的運轉(zhuǎn)強度值,負值是馬達反轉(zhuǎn),有些文章說該值在+-30范圍內(nèi)會報-2即KErrGeneral錯誤,但是自己用E65親測過,在+-30以內(nèi),沒有報錯,震動感不強烈而已,可能跟手機和具體硬件有關(guān)吧),那么震動效果又沒有起來,此時的震動函數(shù)返回為-6,即KErrAgument(錯誤要求)。
我們解決了以上兩個問題后,還有兩種特殊情況,一種是當(dāng)你的手機在充電時,如果調(diào)用正確的StartVibraL會返回-22錯誤,即KErrLocked(鎖閉)。以上幾種情況還好,雖然不震,但是你可以用TRAP機制捕獲錯誤碼,但是如果當(dāng)你是通過數(shù)據(jù)線的手機PC模式裝上軟件后沒有拔出數(shù)據(jù)線,就算使用TRAP返回時KErrNone,但是手機還是沒有震動起來,你就會頭大了,難道這個函數(shù)在當(dāng)前手機上不管用嗎?
事實是,當(dāng)你拔掉數(shù)據(jù)線,居然震動來了。
唉,問題總算解決了,代碼雖簡單,但是實現(xiàn)卻并不簡單啊。
posted on 2009-08-12 17:38
frank.sunny 閱讀(1894)
評論(1) 編輯 收藏 引用 所屬分類:
symbian 開發(fā)