高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technical Q&A QA1340
Registering for sleep notifications

Q: コンピュータがスリープ状態に入るときと、スリープ状態が解除されるときに、アプリケーションが通知を受け取るようにするにはどうしたらよいのでしょうか。

A: 次のコードは、スリープ通知ハンドラをインストールする方法を示しています。アプリケーションはこの通知を使用して、システムがスリープ状態になるときと、スリープ状態から解除されるときにアクションを実行することができます。何か重要な処理が進んでいるけれども、ほとんどのアプリケーションはアイドルスリープを無効にできないという場合には、スリープコールバックを使用して、アイドルスリープを回避することもできます。

リスト 1. スリープ通知ハンドラのインストール

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>

#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>

#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>

io_connect_t  root_port;

void
MySleepCallBack(void * x, io_service_t y, natural_t messageType, void * messageArgument)
{
    printf("messageType %08lx, arg %08lx\n",
      (long unsigned int)messageType, (long unsigned int)messageArgument);
    
    switch ( messageType ) {
        case kIOMessageSystemWillSleep:
            IOAllowPowerChange(root_port, (long)messageArgument);
            break;
        case kIOMessageCanSystemSleep:
            /* アイドルスリープが作動するけれども、アプリケーションは IOCancelPowerChange を呼び出すことで、
            スリープ状態を回避することができる。ほとんどのアプリケーションはこれを行うべきではない。*/

            //IOCancelPowerChange(root_port, (long)messageArgument);

            /*  Power Manager は、これらの関数の 1 つを通じての応答を、30 秒まで待つ。
            IOAllowPowerChange() を呼び出すことによる電力の変更を受け入れなければ、
            30 秒までスリープ状態が延期される。*/

            IOAllowPowerChange(root_port, (long)messageArgument);
            break;
        case kIOMessageSystemHasPoweredOn:
            break;
    }
}


int
main(int argc, char **argv)
{
    IONotificationPortRef  notify;
    io_object_t            anIterator;

    root_port = IORegisterForSystemPower(0, &notify, MySleepCallBack, &anIterator);
    if ( root_port == NULL ) {
            printf("IORegisterForSystemPower failed\n");
            return 1;
    }

    CFRunLoopAddSource(CFRunLoopGetCurrent(),
                        IONotificationPortGetRunLoopSource(notify),
                        kCFRunLoopCommonModes);
                        
    printf("waiting...\n\n");
    
    /* スリープ通知を受け取る実行ループを開始。すでに Carbon または Cocoa の
    EventLoop が実行している場合は、これを呼び出す必要はない。*/
    CFRunLoopRun();
        
    return (0);
}

ドキュメントの改訂履歴

日付メモ
2004-10-25初版

掲載日: 2004-10-25