【iPhone】iPodの標準的な機能を自分で実装してみる

この前のエントリに引き続いて
「もし自分の手でiPodを実装したらどうなるか」の続きをやってみたいと思います。
前回→ http://d.hatena.ne.jp/gong023/20110429/1304096336
これをやってAVFoundationの基本的な使い方はだいたい押さえられました。

まぁ、もともとそういうフレームワークだから当たり前なのかもしれないけど。
ちなみに前回は「再生している曲の経過時間と残り時間を出す」でした。
我ながらおかしなところをブログにしたなぁと思うのですが、まぁ今回は基本のところを実装していきます。

前回に加えて実装する機能は以下です。
①音楽の再生、一時停止

②音楽の経過時間をUISliderに表示する。
また、UISliderから再生位置を変えられるようにする。

③音量をUISliderを使って調節できるようにする。

また、前提として確認しておきますが使用するフレームワークはAVFoundationです。
AVFoundation.frameworkはiOS3ぐらいから追加されたフレームワークで、(うろ覚え)
音楽の再生や一時停止などは大抵コイツを使えば実装できます。

ちなみに短くて単純な音の再生にはAudioToolboxが使えます。用途は効果音とからしい。
AudioToolboxは30秒以下の.aifとか.mp3がとても簡単に実装できますが、一時停止とかには対応していません。
今回はもう少しリッチな機能が必要なのでAVFoundationフレームワークの方を使います。

<<1:音楽の再生、一時停止>>

まずはここを実装します。

一番基本的なAVFoundationの使い方なので、あんまりくどくど書く事はないんだけど・・・。

まぁ基本ついてで最初から書いていくと、踏んでいく手順としては

①AVFoundation.frameworkをプロジェクトに追加
②任意の音声ファイルをプロジェクトに追加
③ここまで終わってやっとコードをいじくる

ってなりますね。一応忘れないようにしておきますか ___φ( ̄^ ̄ )


では、コードの方を書いてみます。
まずは.hファイルの方で

@property(nonatomic,retain)AVAudioPlayer *audio;

とか宣言しておき、viewDidLoadでaudioの中身を詰めてあげます。

- (void)viewDidLoad {

[superviewDidLoad];
NSString *path=[[NSBundlemainBundle] pathForResource:@"music1"ofType:@"mp3"];
NSURL *url=[NSURLfileURLWithPath:path];

audio = [[AVAudioPlayeralloc] initWithContentsOfURL:url error:nil];


}

そして、ここで定義されたaudioをIBActionのタイミングで再生します。

-(IBAction)play:(id)sender{

if(!audio.playing){
//再生していないとき
[audio play];
[playButton setTitle:@"stop"forState:UIControlStateNormal];
}else {
//再生しているとき
[audio pause];
audio.currentTime=timeslider.value;
[playButtonsetTitle:@"play"forState:UIControlStateNormal];
}

}

ちなみにここでは再生/停止を一つのIBActionの中につっこんであります。
AVAudioPlayerが再生している時は一時停止の機能を、AVAudioPlayerが止まっている時は再生の機能を割り当てます。
それに応じてボタンのタイトルも入れ替えます。



ちなみにここではまったポイントがあるので書いときます。
AVAudioPlayerのメソッドで、pauseは一時停止でstopは停止なんですが、pauseメソッドをつかっているのに曲が毎回始めからの再生になってしまう。
なんでかなーと思ったら、audioを定義するタイミングがまずかったようです。
僕は最初上記ののviewDidLoadで行っているAVAudioPlayerの定義をIBAcation内でやってました。
これだとpauseメソッドが意味なくなっちゃいます。

1:IBActionで新しくAVAudioを定義し、曲を再生

2:pause(一時停止する)

3:もう一度ボタンを押すとAVAudioPlayerが定義し直され、前回再生していた位置ではなくはじめから再生されてしまう。

こうなるので。だからaudioの定義はIBActionで行うのではなくviewDidLoadとかでやんないと今回は上手く動いてくれなかったです。


とりあえずここまでで、音楽の再生と一時停止という基本的な機能を実装できます。



<<2:音楽の経過時間をUISliderに表示する。また、UISliderから再生位置を変えられるようにする>>
はい。今度はこの部分作りまーす。

まずは「音楽の経過時間をUISliderに追加する」部分について。

書くコード自体はそんなに多くありません。先程の-(IBAction)playに以下のコードを追加すればOKです。

-(void)upDateSlider:(NSTimer*)timer{

timeslider.value=audio.currentTime;
[self updateLabel];
}
-(IBAction)play{

if(!audio.playing){
//↓追加
 timer = [NSTimerscheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(upDateSlider:)
userInfo:nil
repeats:YES];

[timer fire];

}else {
//↓追加
if (self.timer) {
[timer invalidate];
timer=nil;
}
audio.currentTime=timeslider.value;
}

一応書いておくと、設計の大枠は
「IBActionが押された時に、NSTimerを生成→そのタイマーに引っ張られてUISliderが更新」となります。
.hの方でNSTimer *timer とUISlider *timesliderとやっとくのもお忘れなく。

ちなみにupDateSliderの中にあるupdateLabelは前回のエントリで書いた「曲の経過時間と残り時間を計算するメソッド」です。
このタイミングで呼んどけばおk。

次に「UISliderから再生位置を変えられるようにする」部分について。
ここも一瞬で実装できるのでさくっと。

- (IBAction)timeSlider:(UISlider *)sender {
[audio setCurrentTime:timeslider.value];
[self updateLabel];
}

はい終わり!ww

突然setCurrentTimeとか書き出してるけどそれははただの勉強のため。
ここでもupdateLabelは呼んでおいてあげないとおかしなことになります。
ちょっと勉強になったのは引数にUISliderの形を使うこと。
こうしないとIBで接続できない・・・多分だけど。
ええそうです。今まで(id)senderと呪文のように唱えていたので知りませんでしたとも。何か文句ございまして?



<<音量をUISliderを使って調節できるようにする。>>
最後にこの部分いきます。


うん。何か嫌な予感がしますが、とりあえずコードのっけてみましょう。

-(IBAction)volumeSlider:(UISlider *)slider{

audio.volume=valumeslider.value;
}

うわー。



うわー。



やっちゃったよ。これもめっちゃすぐ終わったよ。
しかも新しい事は特にしてないし (´・ω・`;)
やることはvalumesliderを宣言してIBで引っ付けてあげる事ぐらい?

まぁ簡単にできるに越した事はないし、いっかwwwww

というわけで、これで当初の目標であった3つの機能を実装できました。
AVFoundationフレームワークの基本的な使い方に加えて、UISliderについての勉強にもなったかな。

ただ、これだと今のところ一曲しか再生ができないので、
次は複数の曲を扱うにはどうしたらいいかを考えてみたいと思います。
次の曲に送るにはどうするのか、また一個前の曲に戻るにはどうするか、
ループ再生はどうするか、みたいなところを今頑張って実装してます。

なんか今日書いたコードからだいぶ変更しないとできない予感・・・。





できたらまたブログに書きます。