Можно ли программно изменить значок громкости на подключенном диске в Mac OS X? - PullRequest
12 голосов
/ 10 февраля 2012

Я хочу программно изменить значок громкости для стековой файловой системы, реализованной с использованием OSXFUSE (ранее MacFUSE).Значок должен отражать состояние смонтированной файловой системы.

Подход, который я пытался заставить работать, заключается в сопоставлении запросов для /.VolumeIcon.icns с соответствующим значком в комплекте приложений.Затем отправка уведомлений об изменениях в файловую систему с указанием фактического пути (path) и пути монтирования (mountPath).

    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: @"/Volumes"]; 
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: [mountPath stringByDeletingLastPathComponent]];
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: mountPath];
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: [path stringByDeletingLastPathComponent]];
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: path];

    FNNotifyByPath([[[mountPath stringByDeletingLastPathComponent] dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions);
    FNNotifyByPath([[[path stringByDeletingLastPathComponent] dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions);
    FNNotifyByPath([[@"/Volumes" dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions);

Пошаговый отладчик Я вижу, что этот код ударил, но код для сопоставления /.VolumeIcon.icns вызывается нечасто и никогда в ответ на эти уведомления.

Ответы [ 2 ]

3 голосов
/ 14 февраля 2012

Я думаю, что короткий ответ, вам не повезло.Длинный ответ таков: хотя проект OSXFUSE отличается от проекта Fuse4X, оба они получены из одного и того же источника, и Fuse4X может сказать о значках громкости в своих часто задаваемых вопросах:

Q 4.1.Почему тома Fuse4X отображаются с иконками «сервер» (или «сетевой том»)?

A: Если быть точным, то по умолчанию тома Fuse4X отображаются как нелокальные тома, к которым Finder, к сожалению, относится так же, как и «серверы».Это хороший вопрос о том, почему Fuse4X обычно маркирует свои объемы как нелокальные.Некоторые люди считают, что в случае дисковых файловых систем Fuse4X должен помечать том как локальный.Что ж, давайте посмотрим.

Для того, чтобы vfs был локальным в Mac OS X, вам нужно «реальное» дисковое устройство - узел в стиле / dev / disk *.Такой реальный узел устройства диска в случае Fuse4X проблематичен: во время монтирования для локального тома ядро ​​само откроет узел устройства и передаст его Fuse4X.При этом ядро ​​должно убедиться, что устройство в данный момент не используется (например, чтобы запретить несколько монтирований одного устройства).Это происходит до того, как управление переходит к Fuse4X и установка может продолжаться.Это было бы хорошо, если бы в ядре находилась вся файловая система, но в случае Fuse4X программа файловой системы в пространстве пользователя также хотела бы (исключительно) открыть дисковое устройство.

1 голос
/ 16 февраля 2012

Взгляните на исходный код искателя пути .

- (BOOL)setAsCustomIconForVolume:(NString *)path;
{
    FSref FSRefpath = convertoFsref(path);
    // filename for custom icon is ".VolumeIcon.icns"
    NSString *iconPath = [path stringByAppendingPathComponent:@".VolumeIcon.icns"];

    // remove any existing file first.

    [self writeToFile:iconPath];
    FSSetHasCustomIcon(FSRefpath);

    // rebuild volumeList


    return YES;
}
OSErr FSSetHasCustomIcon(
                   const FSRef *ref)
{
    return ( FSChangeFinderFlags(ref, true, kHasCustomIcon) );
}
OSErr FSChangeFinderFlags(
                    const FSRef *ref,
                    Boolean setBits,
                    UInt16 flagBits)
{
    OSErr           result;
    FSCatalogInfo   catalogInfo;
    FSRef           parentRef;

    /* get the current finderInfo */
    result = FSGetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, &parentRef);
    require_noerr(result, FSGetCatalogInfo);

    /* set or clear the appropriate bits in the finderInfo.finderFlags */
    if ( setBits )
    {
        /* OR in the bits */
        ((FileInfo *)&catalogInfo.finderInfo)->finderFlags |= flagBits;
    }
    else
    {
        /* AND out the bits */
        ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~flagBits;
    }

    /* save the modified finderInfo */
    result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
    require_noerr(result, FSSetCatalogInfo);

FSSetCatalogInfo:
FSGetCatalogInfo:

        return ( result );
}  

NTVolumeNotificationMgr
NTIconFamily

...