Soundflower 1.6.1 のインストール

Soundflower1.6.1をLionにインストールしようとしたのだが、うまくいかなかったのでメモ。

インストーラを実行すると正常にインストールされたと表示されるものの、
Soundflowerがデバイスとして認識されない。


はて?なぜだ?と思いつつSoundflowerのissuesページを見てみると、
解決策がすでに掲載されているじゃないか!!

21
Fixed Error "Soundflower is not installed".

After installing from the 1.6.1 installer package,
I got the same error note
when launching Soundflowerbed - "Soundflower is not installed". 
Navigated to  /System/Library/Extensions/Soundflower.kext
and changed the permissions on wheel to "Read Only" instead of "Read & Write". 
I then restarted my machine and everything was fixed.
Seems to work fine now.

-----------------------------------------------
23
Alright, got it fixed.
Changed permission of wheel to "Read Only" on all files in Contents of Soundflower.kext (Show Contents).
Then "sudo kextload /System/Library/Extensions/Soundflower.kext" in Terminal.

引用元:Google Code Archive - Long-term storage for Google Code Project Hosting.

というわけで、
ターミナルから以下のコマンドを実行すれば解決
なお、以下は再起動する変わりに手動で読み込ませています

sudo chmod -R g=r /System/Library/Extensions/Soundflower.kext
sudo kextload /System/Library/Extensions/Soundflower.kext

かべつべ配信通知

CeveTubeの配信通知Macアプリ『LivePopNotice』
Downloads · hsmikan/LivePopNotice · GitHub
とりあえず、整えたつもり。
(整ったのに最新版がbetaからalphaになるという謎仕様)


あとは、ちゃんとエラー処理するのとバグつぶしです。
もしも使ってくださる方がいらして、
バグ発見/アイデア等がありましたらご報告をお願いします。
PPixyの掲示板



そして、アイコンの使用許可をくださった湯呑さんありがとうございます。

Xcode4のスニペットの削除

自分で追加したスニペットの削除しようと思ったのだが、
UIにそんな感じのが見つからない。
(ちゃんと探せばあるのかも)
ということで、保存されている元データを消すことに。
自分で追加したスニペット
~/Library/Developer/Xcode/UserData/CodeSnippets/
に保存されているので、ここから適切なものを選んで削除してやればいい。
ただ、ファイル名がUID化されているので中身を順番に確かめてから削除することになる。
これは、面倒くさい
中身はplistなのでファイル自体は読みやすいのが、せめてもの救いだろうか

音声出力デバイスの一覧を取得する

NSSoundの

- (void)setPlaybackDeviceIdentifier:(NSString *)playbackDeviceIdentifier;

に渡す引数について
とりあえず、出力デバイスの一覧欲しいよねってことで、
やってみます。


さて、playbackDeviceIdentifierをどうやってもってくるものか。。。
ちなみにNSSoundには、選択可能なデバイスを返してくれるようなメソッドは用意されていません。
CoreAudioを使ってデバイスのIDを取得します。
参考URL
http://objective-audio.jp/2008/04/core-audio-4.html
http://objective-audio.jp/2009/09/coreaudio-audioobject.html
macos - AudioObjectGetPropertyData to get a list of input devices - Stack Overflow

/* CoreAudioを使用するフレームワークに追加するのと、インポートするのを忘れずに */
OSStatus err;
AudioDeviceID *deviceIDPtr = NULL;
UInt32 size;
AudioObjectPropertyAddress propAddr;

/*
 * 全てのデバイスを取得
 *   setPlaybackDeviceIdentifier:にインプットデバイスを渡すと落ちてしまうので、
 *   アウトプットデバイスだけの一覧を取得したい
 *   ただ、アウトプットデバイスの一覧を一発で取得する方法がどうも見当たらない
 *   mScopeにkAudioDevicePropertyScopeOutputを入れてやれば、できそうに見えるが、
 *   AudioDeviceIDには指定できないことに注意。
 *   なので、各デバイスが持っているストリームを逐一チェックすることにする
 */
propAddr.mScope    = kAudioObjectPropertyScopeGlobal;
propAddr.mElement  = kAudioObjectPropertyElementMaster;
propAddr.mSelector = kAudioHardwarePropertyDevices;{
    
    err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propAddr, 0, NULL, &size);
    if(err != noErr) goto catchErr;
    
    deviceIDPtr = malloc(size);
    
    err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAddr, 0, NULL, &size, deviceIDPtr);
    if(err != noErr) goto catchErr;
}

/* 取得したデバイスの数 */
UInt32 count = size / sizeof(AudioDeviceID);

/* 各デバイス */
int i;
for(i=0; i<count; i++){
    
    // デバイスがアウトプットストリームを持っているか確かめる
    propAddr.mSelector = kAudioDevicePropertyStreams;{
        propAddr.mScope    = kAudioDevicePropertyScopeOutput;
        err = AudioObjectGetPropertyDataSize(deviceIDPtr[i], &propAddr, 0, NULL, &size);
        if (err != noErr) {
            goto catchErr;
        }
        
        UInt32 streamCount = size/sizeof(AudioStreamID);
        if (streamCount == 0) {
            continue;
        }
    }
    
    
    propAddr.mScope    = kAudioObjectPropertyScopeGlobal;
    
    
    // デバイスのUIDを取得
    //  こいつを 『setPlaybackDeviceIdentifier:』に渡してやる
    CFStringRef deviceUID;
    propAddr.mSelector = kAudioDevicePropertyDeviceUID;{
        err = AudioObjectGetPropertyDataSize(deviceIDPtr[i], &propAddr, 0, NULL, &size);
        if(err != noErr) goto catchErr;
        
        err = AudioObjectGetPropertyData(deviceIDPtr[i], &propAddr, 0, NULL, &size, &deviceUID);
        if(err != noErr) {
            CFRelease( deviceUID );
            goto catchErr;
        }
    }
    
    // デバイスの名前を取得
    CFStringRef deviceName;
    propAddr.mSelector = kAudioObjectPropertyName;{
        err = AudioObjectGetPropertyDataSize( deviceIDPtr[i], &propAddr, 0, NULL, &size );
        if(err != noErr) goto catchErr;
        
        err = AudioObjectGetPropertyData( deviceIDPtr[i], &propAddr, 0, NULL, &size, &deviceName ); 
        if(err != noErr) {
            CFRelease( deviceName );
            CFRelease( deviceUID );
            goto catchErr;
        }
    }

   /* do something */

   CFRelease( deviceName );
   CFRelease( deviceUID );
}