音声再生アプリに、一時停止機能を追加しました。
一時停止機能は結構必要になることも多そうだね~
音声ファイルの再生中にplayボタンを押すことで、ポーズができるような機能追加を行いました。結構処理的に、入り組んでいて、整理してプログラムの流れを追わないと、プログラム的な仕組みがどうなっているかつかみづらい項目でもあります。まずは、プログラムを動作させることができるように改変するところまでを行います。
公式チュートリアルでは、次のページの「Adding pause functionality」の項目になります。
こんな人の役に立つかも
・JUCEフレームワークに入門したい人
・JUCEプログラミングでオーディオアプリを作成したい人
・JUCEで音声再生を行いたい人
追加する機能の詳細
ポーズ機能では、次のような動作を追加することになります。
①音声ファイルの再生中にplayボタンを押すと再生中のポジションで一時停止します。(Pause)
②一時停止中にplayボタン(Pause)で再生再開します。
③一時停止中にstopボタンで、音声の再生をキャンセルして初期状態に戻します。(Return to zero)
音声の状態の追加
「MainComponent.h」のprivateな変数にPausingとPausedという2つの状態を追加しました。
private:
enum TransportState
{
Stopped,
Starting,
Playing,
Pausing,//←追加しました。
Paused,//←追加しました。
Stopping
};
changeState関数の変更
changeState関数を次のように変更します。
void MainComponent::changeState(MainComponent::TransportState newState)
{
if (state != newState)
{
state = newState;
switch (state)
{
case Stopped:
stopButton.setEnabled(false);
playButton.setEnabled(true);
transportSource.setPosition(0.0);
break;
case Starting:
//playButton.setEnabled(false);//[1]再生中にplayボタンで一時停止とするので、ここは削除します。
transportSource.start();
break;
case Playing:
playButton.setButtonText("Pause");//[2]
再生中は、playボタンの表記をPauseにします。
stopButton.setButtonText("Stop");//[2]
stopボタンのテキストはStopです。
stopButton.setEnabled(true);
break;
//[3]Pausingのときの処理です。
case Pausing:
transportSource.stop();
break;
//[4]一時停止中は、playボタンの表記をResume(再開)にします。
//また、stopボタンの表記はReturn to zeroにします。
case Paused:
playButton.setButtonText("Resume");
stopButton.setButtonText("Return to Zero");
break;
case Stopping:
transportSource.stop();
break;
}
}
}
[1]では、以前は再生を開始したら、playボタンを押せないようにすればOKでしたが、playがpauseに変化しなければいけないので、音声再生状態が「Starting」の時は、playボタンを押せないようにする設定を削除します。
[2]での、音声再生中の時は、playボタンをPauseにして、一時停止ボタンの機能に変更しますので、テキストを変更します。
[3]は新規に追加された状態「Pausing」です。Pausing状態に変更となったときは、transportSourceを停止状態にします。
[4]も新たに追加された状態「Paused」で、一時停止処理が完了して一時停止状態にあります。この時には、playボタンの表示を「Resume(再開)」とし、stopボタンの表示を「Retuen to zero」にしています。
transportSourceのコールバック
transportSourceの音声再生状態が変化したときに呼び出されるコールバック関数、changeListenerCallback関数を次のように変更しました。以前のものはコメントアウトで変更点がわかりやすいようにしてあります。
void MainComponent::changeListenerCallback(juce::ChangeBroadcaster* source)
{
if (source == &transportSource)
{
if (transportSource.isPlaying())
changeState(Playing);
//音声の再生状態が変化したときにstateがStoppingまたはPlayingのときの条件です。
else if ((state == Stopping) || (state == Playing))
changeState(Stopped);
else if (Pausing == state)
changeState(Paused);
//↓以前のelse文です。
/*else
changeState(Stopped);*/
}
}
ここは、処理の流れを追わないとちょっとわかりづらいのですが、一番最初のif文では、最初の音声の再生開始時に入る条件になります。ここで、アプリ全体の音声再生状態を表現するstateがPlayingになります。
実際に、処理のながれをまたの機会で追ってみたいと思います。
ここは、実際にどんな流れで処理が行われているか見てみないとしっくりきませんね。
ボタンのコールバック関数
PlayButtonClicked関数とstopButtoClicked関数を以下のように変更しました。
void MainComponent::playButtonClicked()
{
//changed
if ((state == Stopped) || (state == Paused))
changeState(Starting);
else if (state == Playing)
changeState(Pausing);
//changeState(Starting);
}
void MainComponent::stopButtonClicked()
{
//changed
if (state == Paused)
changeState(Stopped);
else
changeState(Stopping);
//changeState(Stopping);
}
独自に追加した点
ここまでを動作検証するとわかるのですが、「Stop」状態に戻ったときに、ボタンのテキストが「Play」と「Stop」と戻らないことがわかります。ここで、Stop状態のときに、ボタンのテキストを変更するように「chngeState」関数のStoppedの条件に追加しました。
case Stopped:
stopButton.setEnabled(false);
playButton.setEnabled(true);
transportSource.setPosition(0.0);
playButton.setButtonText("Play");//ここを独自に追加しました。
stopButton.setButtonText("Stop");//ここを独自に追加しました。
break;
次回は、一度、この処理の流れを順番に整理してみたいと思います。