記事一覧

Restore the state of MPMediaPickerController??

MPMediaPickerController の状態を復帰させる方法ってないのかしら?
とりあえずそういうメソッドは見あたらないんだが・・・

毎回 picker を開くたびに「すべての曲」リストの一番上に戻されちゃうから不便なんですよね。少なくとも曲/アルバム/アーティストのカテゴリ選択くらいは復帰してほしい;


Are there any ways to restore the state of MPMediaPickerController??
MPMediaPickerController class doesn't seem to have the method to change the state of the picker.

Every time my app opens the picker it shows the top of the list of "all songs" regardless of your last operation on the picker. At least I want it to restore the category(songs/albums/artists) selection....

Fowarding events in standalone QC composition

スタンドアロンで動くQCコンポジションを作るにはこうしろとチュートリアルに書いてあるのだが:
http://developer.apple.com/jp/documentation/GraphicsImaging/Conceptual/QuartzComposer/qc_play_ib/chapter_4_section_1.html#//apple_ref/doc/uid/TP40001357-CH207-TPXREF101
やってみると出来上がったアプリはイベントの受け取りが一切出来ない状態。Fowarding All Events のチェックをONにしてもだ。
この問題はあちこちで報告されてて、そのうち一つで解決策をちらっと述べているものがあった。それは XCode 同梱のサンプルから .nib ファイルをコピーしてくるというもの。
早速 Mouse Tracking という example からコピーして .qtz ファイルを自分のやつに入れ替えてみたところ、見事動いた。
しかし何が違うんだこれ・・・。
ちなみに、コピーしてきたものを利用するには .nib の名前を MainWindow.nib に変える(元の MainWindow.nib は待避か削除ね)か、Info.plist の Main nib file base name を新しい .nib ファイルの名前に変更しないといけないですね。


The tutorial says, to build a standalone QC composition just do like this:
http://developer.apple.com/mac/library/documentation/GraphicsImaging/Conceptual/QuartzComposer/qc_play_ib/qc_play_ib.html
But the resulting application won't respond to any events, even though I have set the Fowarding All Events option to YES.

There are some articles that report the same problem, and one of them shows the hint : copy the .nib file from the example included with XCode.
I copied one from Mouse Tracking example, swapped .qtz file with mine and worked successfully.
I don't know why, but it worked...

MIDI Note Receiver

MIDIのノートNo.で映像のパラメータをコントロールできるようなパッチができるといいなと思って取り組んでるんですが、そのための入力パッチというと MIDI Note Receiver ですよね。
でもこれ、各ノートNo.がそれぞれ独立したアウトプットに割り振られていて、

my_parameter = recieved_MIDI_NoteNo * aRate;

みたいなことをやろうとするとえらい面倒くさいことに・・
誰かいい方法知らないっすかね?


I want to control movie with MIDI controllers, and making a patch to do that.
In my patch I want to control a parameter of a movie with MIDI note value so that I can control the movie with my MIDI keyboard.
To receive MIDI signals using MIDI Note Receiver seems to be the only way, but taking a look at the MIDI Note Receiver's panel to find all the notes are separate in individual outputs, so it's quite difficult to do the thing like this:

my_parameter = recieved_MIDI_NoteNo * aRate;

Does anybody know a good way to do this?

MPMusicPlayer : Rewind and standby at song's end

自分のアプリはいちどに一つの曲しか扱わないのだけど、MPMusicPlayerは基本的に複数の曲を扱う仕様になってる。
これがちょっと面倒なんだな;

再生してる曲が終わると MPMusicPlayerController は次の曲に行こうとする。次の曲がキューにあれば nowPlayingItem に次の曲の mediaItem がセットされるのだけど、次の曲が無い場合は nowPlayingItem は nil になる。
queueに1曲しか無い場合、曲が最後まで行ったまま放っておくと必ず nil になってしまうわけで、そのままだともう一度その曲をプレイすることができなくなってしまう。

解決策は簡単っちゃあ簡単で、曲が終わったのを検知して nowPlayingItem をセットし直せば良い。ただ、そのためには
MPMusicPlayerControllerNowPlayingItemDidChangeNotification を扱うセレクタを記述して、あと通知センター登録とかごにょごにょしなきゃいけないし、あと mediaItem をインスタンス変数として保持したりしなきゃいけない。
こういうのって Bad Access の原因になるからイヤなんだよなぁ・・・

MPMusicRepeatMode に MPMusicRepeatModeOne_RewindAndStop みたいのがありさえすればすごく楽なんだけどな・・・

My app deals with only one song at a time, while MPMusicPlayer is designed for playing multiple songs;
This mismatch makes my app slightly more complex.

When the currently playing song comes to its end MPMusicPlayerController tries to move to the next song.
If there is the next song in the queue nowPlayingItem will be set to its mediaItem variable, but if there is none nowPlayingItem will be set to nil.
The problem here is, my queue always contains only one song, so nowPlayingItem will be reset to nil everytime you play a song to the end, and you cannot replay the song.

The solution is pretty simple to say : reset the nowPlayingItem when the player has finished playing, but to do this you have to write the selector to receive MPMusicPlayerControllerNowPlayingItemDidChangeNotification and some other codes to make it work.
And you also have to retain the mediaItem variable of the song as the instance variable.
I don't like this kind of thing because it often causes the Bad Access error...

It will be much easier only if MPMusicRepeatMode had something like MPMusicRepeatModeOne_RewindAndStop.

AVAudioPlayer's currentTime problem

自分のアプリでは、AVAudioPlayerの現在の再生時間を利用して動作を変えたりしてるんですが、どうもその辺りの動作がちょっとおかしい。

で、グーグル先生で調べてみるとこういうのありました。
http://stackoverflow.com/questions/882753/avaudioplayer-currenttime-problem

AVAudioPlayerの再生時間setterはint値しか取らないらしい;
さらに、再生中に値を変更すると不安定になることがあるらしい;
なんじゃそら;
とりあえず上のリンクのように変えてみたらおかしな挙動はなくなりました。

In my app I let it read the current time of AVAudioPlayer and vary the behavior according to its value.
But sometimes its behavior seems to be a bit strange.

I google'd about it and have found this:
http://stackoverflow.com/questions/882753/avaudioplayer-currenttime-problem

AVAudioPlayer's current playing time setter can take only int value.
And what's more, it will be a bit unstable when you set the value while it's playing.
I modified my app like the link above and now it's working well.

Making an introduction clip

I want to make a short clip to introduce my app on the web and need to make the scene to show how the app works on your real device.
If you only need the pure digital image on the screen you can screen-capture the emulator window with certain kind of freeware, but to show how to operate by your finger and how the accelerometer works you have to shoot the real device by video camera.
It's not easy to hold the device steadily (to use accelerometer you have to hold it floating from the ground) and cast the light without undesirable reflection.
Hmm...

User Presets

オーディオユニットはデフォルトでユーザープリセットをしかるべきディレクトリから探してメニューに表示する機能があったんですねえ。Logic 7 だと Save Preset As のときに指定ディレクトリに飛んでくれないので気づきませんでした。

I've just found that the default AudioUnit has the function to search the user presets in certain directories and show them in the preset menu.
I didn't notice that because on my main environment (Logic 7) it doesn't show the proper directory to save presets by default.

Adding subview to NSImageView

NSImageViewにサブビューを追加する

※今回から英語も併記することにしました(余裕があるときだけ;)

Interface Builder で UI を作ってるんですが、背景画像の上に各種部品を配置しようと思ったら、背景画像がすべてを覆い隠してしまって全くダメダメに。
なんでや!?と思って調べたら、同列の subview 同士の重ね順の概念自体が無く、Interface Builder 上で指定した重ね順というのは単なる編集上の便利機能にすぎない。
Subview 同士を重ねてしまった場合の挙動は定義されていないのでどう重ね順がどうなるかはその時々で変わってしまう、とのこと。

で、解決策のヒントになったのがこれ。
http://stackoverflow.com/questions/2415561/apple-interface-builder-adding-subview-to-uiimageview
あくまで iPhone OS の方ですが、同じようにやってみたら成功しました。

(1)まず背景用として NSImageView じゃなくて NSView を配置
(2)オブジェクトビュー画面で各種部品を NSView の傘下に入れる
(3)インスペクタで NSView のクラスを NSImageView に変更
(4)ビューコントローラのヘッダファイルにアウトレットを追加
 (IBOutlet) NSImageView * anImageView;
(5)Interface Builder上でこれとさっき配置したビューをコネクト
(6)ビューコントローラの .m ファイルの setAU に
 [anImageView setImage:....]
 でイメージを追加


From this topic I'm going to add English version of each issue, too.

I'm now building the custom view for my Magical 8bit Plug by Interface Builder, and what I want to do right now is
to put my UI parts on my custom background image.
It looks nice on Interface Builder, but compile and run it to have found the background image covers all other parts and nothing works.

I wonder why and google'd a bit to have found that
there's no concept of layering order between "sibling" subviews (subviews belong to the same parent view),
so you cannot tell the order of the layered subviews before running it.

I've got the hint to solve this problem from here:
http://stackoverflow.com/questions/2415561/apple-interface-builder-adding-subview-to-uiimageview

It's an iPhone issue, not Cocoa, but it worked as well.

(1)Put NSView, not NSImageView, for background image container. Do not put image here.
(2)On Object View Window move your UI parts under NSView to make them be children of NSView.
(3)Change the Class of NSView to NSImageView by Inspector.
(4)Add the declaration of the outlet on your ViewController's header file.
 (IBOutlet) NSImageView * anImageView;
(5)On Interface Builder connect this outlet to the view you put on (1).
(6)add your background image by invoking setImage in the setAU selector of your ViewController's .m file.
 [anImageView setImage:....]

スライダーのレールの方

さて、レールの方だ。
オーバーライドするセレクタは drawBarInside: ということで、あとの要領自体はノブとだいたい同じだった。
Cocoa的にはレールじゃなくてバーって呼ぶみたいね。

サイズはどうやら完全な任意指定はできないみたいですねえ。
横サイズは InterfaceBuilder 上で横に引っ張れば任意の大きさにできるけど、縦サイズは mini/small/regular の3種類から選ぶしかないみたい。好きなサイズでやりたければ NSCell を直接継承して好きにやりなさいってことかな??
いずれにしても、そのサイズが引数 aRect に渡ってきます。

ちなみに、横サイズは 133px が標準的っぽい雰囲気ですかね。Audio Unit Effect with Cocoa UI のテンプレートに入ってたスライダーが 133px なのと、GarageBand の Generic UI が 133px でした。縦サイズはテンプレートの方が Regular で、GarageBand は Small のようです。

-(void)drawBarInside:(NSRect)aRect flipped:(BOOL)flipped
{
NSBundle *bundle = [NSBundle bundleWithIdentifier : @"com.MyCompany.audiounit.MyGreatPlugin"];
NSString *path = [bundle pathForImageResource:@"sliderRail.png"];
NSImage* img = [[[NSImage alloc] initByReferencingFile:path] autorelease];
[img drawInRect:aRect
fromRect:NSMakeRect(0,0,[img size].width,[img size].height)
operation:NSCompositeSourceOver
fraction:1.0];
}

スライダー画像のカスタマイズ

やっとツマミの方の画像をカスタマイズできたぞ!!!
NSSliderじゃなくてNSSliderCellの方をいじるわけですね。そして、単に setImage 的なものを呼ぶんじゃなくて drawKnob なるセレクタをオーバーライドしないといけない。さらに初心者にやさしくない bundle を絡めた画像指定。
・・・ハードル高杉!!!

/* MyGreatPlugin_CocoaView.h */

@interface MySliderCell : NSSliderCell
{
}
-(void)drawKnob:(NSRect)knobRect;

/* MyGreatPlugin_CocoaView.m */

@implementation MySliderCell

-(void) drawKnob:(NSRect)knobRect
{
NSBundle *bundle = [NSBundle bundleWithIdentifier : @"com.MyCompany.audiounit.MyGreatPlugin"];
NSString *path = [bundle pathForImageResource:@"MySliderKnobImage.png"];
NSImage* img = [[[NSImage alloc] initByReferencingFile:path] autorelease];
[[self controlView] lockFocus];
[img drawInRect:knobRect
fromRect:NSMakeRect(0,0,[img size].width,[img size].height)
operation:NSCompositeSourceOver
fraction:1.0];
[[self controlView] unlockFocus];
}

これを記述してセーブすると Interface Builder の方でスライダーセルのクラスとして MySliderCell が選択できるようになるので、それを選択するとやっとソースと.xibが結びつきます。

さて次は、knobRectの大きさの設定と、レールの方の画像設定だな・・・。