Posts Tagged: Cocoa


31
Jan 10

MClock : 最前面に表示する時計

「会議中にはプロジェクタを時計で映せば時間管理がしやすい」らしいので、常に最前面に表示する時計を作ってみた。

GitHubにおいてある: MClock

全然大したことはやってなくて、次の2つをやってるだけ。

  • アプリケーション起動時にNSWindowのlevelをNSFloatingWindowLevelにする(なのでアラート画面よりは下に来る)
  • NSTimerで0.5秒ごとにNSDateを生成してNSTextFieldの文字列を更新してる(なので最大0.5秒のずれが生じる)。

デジタル表示だとわかりにくいので、会議の開始・終了時間を設定してプログレスバー表示するとか、改善方法を考え中。


21
Mar 09

QTKitPlayerにフレームを画像として保存する

QTKitPlayerで再生中の動画の、現フレームを画像として保存する方法。ここではpngに限定してる。MovieDocument.hに次のコードを追加。

- (IBAction)doSaveCurrentFrameAsImage:(id)sender
{
    NSSavePanel *savePanel;

    QTTime qtCurrentTime = [mMovie currentTime];
    float currentTime = qtCurrentTime.timeValue / qtCurrentTime.timeScale;

    NSString *baseName = [[[self fileName] lastPathComponent] stringByDeletingPathExtension];
    NSString *fileName = [NSString stringWithFormat:@"%@-%07.2f.%@", baseName, currentTime, @"png"];

    // init
    savePanel = [NSSavePanel savePanel];

    // run the export sheet
    [savePanel beginSheetForDirectory:nil file:fileName modalForWindow:mMovieWindow modalDelegate:self
                       didEndSelector:@selector(saveCurrentFrameAsImagePanelDidEnd: returnCode: contextInfo:) contextInfo:nil];
}

    - (void)saveCurrentFrameAsImagePanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
    if (returnCode == NSOKButton) {

        // 現在のフレームの画像をNSImageで取得
        // 本来の画像サイズで取得するためにオプションにQTMovieNaturalSizeAttributeを追加
        NSArray *keys = [NSArray arrayWithObjects:QTMovieFrameImageType, QTMovieFrameImageSize, nil];
        NSArray *objects = [NSArray arrayWithObjects:QTMovieFrameImageTypeNSImage, [mMovie attributeForKey:QTMovieNaturalSizeAttribute], nil];
        NSDictionary *attrs = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
        NSImage             *image = [(NSImage *)[mMovie frameImageAtTime:[mMovie currentTime] withAttributes:attrs error:NULL] retain];

        // 画像データの変換
        // < http://www15.plala.or.jp/NovemberKou/programming/2ndGeneration/2ndHome/ImagePanelController/createPictureData.html >
        NSBitmapImageRep    *bitmapImageRep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
        NSDictionary        *properties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]
                                                                      forKey:NSImageInterlaced];
        NSData *pngData = [bitmapImageRep representationUsingType:NSPNGFileType
                                                       properties:properties];
        // export
        if (![pngData writeToFile:[sheet filename] atomically:YES])
            NSRunAlertPanel(@"Error", @"Error saving current frame as image.", nil, nil, nil);

        [image release];
    }
}

ちなみにwindowControllerDidLoadNib:あたりで[[mMovieView window] setContentAspectRatio:contentSize];をしておけば、QTMovieViewのアスペクト比も固定されるので便利。


13
Mar 09

universalchardetをCocoaで

Mozillaのエンコーディング判別ライブラリをCに切り出したuniversalchardetを、Cocoaなフレームワークにしてみた。

1 kB程度あればほぼ確実に判別できるので、NSStringのinitWithContentsOfFile:usedEncoding:error:の代わりに使えそう。

でもやっぱり数文字だとミスは増える。

ASCIIに収まる文字のみで構成されている場合には、1 kB程度あっても判別できていない、というかASCII互換なエンコーディングから適当なエンコーディングを選ぶことができない(Shift_JISとして保存された文章だけどASCII部分しか使われていない、という可能性)。

まぁ実用的には自動判別で読めればいいわけだから、適当に返せばいいのかも。というわけで、initWithContentsOfFile:usedEncoding:error:の代替メソッドを作るなら、

  1. まずinitWithContentsOfFile:usedEncoding:error:で読んでみる。UTF-16、32なら判別可能だし、OS 10.5で保存された文章であればファイルシステムの拡張属性から保存時のエンコーディングを読み取ってくれる。
  2. universalchardetで判別し、判別できたらinitWithContentsOfFile:encoding:error:で読み込む。
  3. 判別できなかったらUS-ASCIIのみで構成されている可能性があるので、NSASCIIStringEncodingとしてinitWithContentsOfFile:encoding:error:で読み込んでみる。
  4. 読み込めなかったら、諦める?

というような流れかな?ただしテキストファイルであるとわかっていることが前提(そうでない場合、当然universalchardetで判別できない)。

ちなみに、NKFでNSDataを拡張するNKFCocoaなるものがあるのか。


13
Nov 08

Carbonの新APIによる、Finder経由でのファイル削除

以前はAppleScript経由で面倒っぽかったけど、LeopardからCarbonにAPIが加わったらしい。

CarbonCore Framework Release Notes for Mac OS X v10.5


追記 @ 2009-03-23

とりあえず以下のコードで動くっぽい。要<CoreServices/CoreServices.h>。

- (BOOL)moveFileToTrash:(NSString *)filename
{
    FSRef fileRef;

    // 対象の存在をチェック
    if(![[NSFileManager defaultManager] fileExistsAtPath:filename])
        return NO;

    // FSRefの取得(ちなみにコードを拝借したCocoaDVDPlayerではUTF-8ではなくASCIIにしてた)
    //const char *cPath = [filename UTF8String];
    // 追記その2参照
    const char *cPath = [filename fileSystemRepresentation];
    OSStatus result = FSPathMakeRef ((UInt8*)cPath, &fileRef, NULL);
    if (result != noErr)
        return NO;

    // ゴミ箱に移動
    // オプションはテキトー。Finderのような効果音は別途処理を記述する必要あり
    result = FSMoveObjectToTrashSync(&fileRef, NULL,  kFSFileOperationDefaultOptions);

    return (result == noErr);
}

追記その2 @ 2009-03-28

Cocoa Study Blogの記事のコメントによると、UTF8StringではなくfileSystemRepresentationにすべきだろうとのこと。確かに、現在はUTF-8が使われてるけど、将来的には変更される可能性もあるし、こっちを使った方がいいかも。


27
Sep 08

GTK+ on OSX

Mac OS XでGTKアプリをビルドできる「GTK+ on OSX」 – マイコミジャーナル

例えばこれを使ってビルドされたGIMPの起動にはX11が必要なくなる、ということらしい。

ただしMac OS X 10.4 (Intel) が必要。


29
May 08

Fwd: 詳解 Objective-C 2.0

荻原さんがObjective-C 2.0の本を出す。これは買わねば。


16
May 08

LeopardでNSStringのinitWithContentOfFile:usedEncoding:error:

cocoa-dev-japanのMLへの投稿で見つけたネタを劣化コピーな感じでメモしておく。

Tigerでは(少なくとも日本語圏的に)まったく役に立たなかったNSStringのinitWithContentsOfFile:usedEncoding:error:だけれども、Leopardでは読み込むファイルのエンコーディングを適切に返してくれる場合もあるとのこと。

それは当該ファイルをLeopardなNSStringのwriteToFile:atomically:encoding:error:で文字列をファイルに書き出していた場合。これはNSStringがその内容をディスクに書き出す際に、拡張ファイルアトリビュート(ファイルシステム的なアレ)にエンコーディングを記録しておき、読み込む際にそれを用いるという仕組み。

したがって、NSDataで書き出した場合(ネット上のテキストファイルをSafariなどのブラウザで保存した場合はたぶんNSDataを使ってる)や、他のマシン上で書き出したものをコピペしてきたとかだと通用しない(と思う)。

誰かuniversalchardetを移植してくれないだろうか、と他力本願に考えている今日この頃。


20
Apr 08

Dat2HTML Rev 0.4をリリース

詳しくはリリースノートを。

Universal Binaryにしてみたつもりだけど、手元にIntel Macがないために試せない罠。


20
Apr 08

Cocoa Wikiのデザインを変えた

放置しっぱなしだったCocoa Wikiのデザインを変えた、というか以前のこのブログのデザインをそのまま流用した。Xcodeのアイコンを勝手に使っちゃったけど、大丈夫だろうか。

パラグラフごとの編集機能(paraedit.inc.php)も追加したし、少しは使いやすくなんるんじゃないかと。

でももうPukiWikiのデザインはあまり書き換えたくない。$page_titleがページのタイトルではなくWikiのタイトルだったり、なんか変だ。あまり大規模なものを作ったことがないけど、こういうもんなのか?