home *** CD-ROM | disk | FTP | other *** search
/ Phoenix Heaven Sunny 2 / APPARE2.BIN / oh_towns / gwav / src / gwav.c < prev    next >
C/C++ Source or Header  |  1995-06-20  |  34KB  |  1,113 lines

  1. /************************************************************************/
  2. /*                       PCM Player 'GWAV' V1.1 L32                        */
  3. /*                                                                        */
  4. /*                               『GWAV.EXG』                            */
  5. /*                                                                        */
  6. /*                  Copyright(C) 1994,1995 by メルキュール                */
  7. /************************************************************************/
  8. /*    シェルアプリとしては、ほとんど最低限のことしかしていないが、とりあ    */
  9. /*    えず動いているのでよしとする(メモリ不足時の動作に不安あり…ほとんど    */
  10. /*    対策とってないし)                                                    */
  11. /*    なお、本来は、SNDとWAVの資源はタスク切り替え時に退避復元してやらな    */
  12. /*    くてはならないのだが、そうするとバックグラウンドで音が鳴らなくなっ    */
  13. /*    てつまらないので、あえて強行している                                */
  14. /*    だから、ほんとはあまり真似してほしくない…(^^;                        */
  15. /*    それから、ところどころ現れる'EIN_'関数はEIN(TM)プロジュクトの関数群    */
  16. /*    で、終了時の座標を記憶するリジュームマネージャとして使用している    */
  17. /*    GUIライブラリの関数群とは違うので、EINTM.LIBを組み込まないと使用    */
  18. /*    できない                                                            */
  19. /*    しかし、だ。WAVEに規定外の周波数のデータを放り込むとエラーで        */
  20. /*    はじかれるとは知らなかったのであった(V1.1L31対応)                    */
  21. /*    さらにNULLポインタでcompareするバグも後から発覚(V1.1L32対応)        */
  22. /************************************************************************/
  23. /*    注:コンパイル時にwarningが出るが、問題ないのがわかっているので無視    */
  24. /************************************************************************/
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <limits.h>
  29. #include <winb.h>
  30. #include <te.h>
  31. #include <fntb.h>
  32. #include <gui.h>
  33. #include <egb.h>
  34. #include <guidbg.h>
  35. #include <file_dlg.h>
  36. #include <snd.h>
  37. #include <wav.h>
  38. #include "eintm.h"                /*    EIN(TM)環境用ライブラリ                */
  39.  
  40. char    *guiEgbPtr ;            /*    EGB のワークアドレス                */
  41.  
  42. /*    部品ID用変数の定義                                                    */
  43. int    backId = -1 ;
  44. int    quitBtnId = -1 ;
  45. int    fnameBtnId = -1 ;
  46. int    fnameMesId = -1 ;
  47. int    fileSlctId = -1 ;
  48. int    wavPlayBtnId = -1 ;
  49. int    wavStopBtnId = -1 ;
  50.  
  51. /*    PCMのチャネル指定                                                    */
  52. #define    ch        69
  53.  
  54. /* リジューム情報読み書きバッファのサイズ(アプリ固有なので要調整)        */
  55. #define    RBUFSIZE    (1024)
  56.  
  57. int        mute_data ;                /*    電子ボリュームのミュート保存用        */
  58. int        wavFlag = FALSE ;        /*    WAVファイル再生モード                */
  59. char    *wavBuffer = NULL ;        /*    PCMデータ格納用バッファへのポインタ    */
  60. char    fileName[32] ;            /*    ファイル名バッファ(画面表示専用)    */
  61. char    path[80] = "\0" ;        /*    パス名バッファ                        */
  62. int        freq, bitno, kind, pcmLen, pcmStart ;
  63.                                 /*    WAVライブラリ用パラメータ            */
  64. int        saveDrv ;                /*    カレントドライブ退避用                */
  65. char    saveDir[68] = "\0" ;    /*    カレントディレクトリ退避用            */
  66. FRAME    rsmFrame ;                /*    リジューム時に必要な部品座標        */
  67. char    RSMID[] = "%%% PCM Player GWAV %%%" ;
  68.                                 /*    リジュームファイル用のキー文字列    */
  69. char    version[] = "PCM Player 'GWAV' V1.1L31" ;
  70.                                 /*    バージョン表記(タスク名)            */
  71. char    copyright[] = "Copyright(C)1994,1995 メルキュール(Jun Somekawa)" ;
  72.                                 /*    Copyright表記                        */
  73.  
  74. /*    WAVEライブラリサポートサンプリング周波数テーブル                    */
  75. int        freqTbl[11] = {
  76.              8000,  9600, 11025, 12000, 16000, 19200,
  77.             22050, 24000, 32000, 44100, 48000
  78.         } ;
  79.  
  80. /*    アラート用メッセージデータ                                            */
  81. static char    *alertStr[] = {
  82.             "GWAV.EXG:\nメモリが不足しています。\n"\
  83.             "メモリを空けてから再チャレンジしましょう。",
  84.             "確認"
  85.         } ;
  86.  
  87. static char    *alertStr2[] = {
  88.             "GWAV.EXG:\nWAVEファイルを再生できる状態ではありません。\n"\
  89.             "マイクロソフトウェーブフォームデータを「使用する」にしてないようです。",
  90.             "確認"
  91.         } ;
  92.  
  93. static char    *alertStr3[] = {
  94.             "GWAV.EXG:\n音声ファイルが見つかりません",
  95.             "確認"
  96.         } ;
  97.  
  98. static char    *alertStr4[] = {
  99.             "GWAV.EXG:\nWAVEファイルフォーマットの異常みたいです。\n"\
  100.             "これでは正常に再生できません。",
  101.             "確認"
  102.         } ;
  103.  
  104.  
  105. /************************************************************************/
  106. /*    Townsシェル呼び出し関数                                                */
  107. /************************************************************************/
  108. int userFunc(apliId, messId, info, data)
  109. int    apliId ;
  110. int    messId ;
  111. int    info ;
  112. int    data ;
  113. {
  114.     register int    ret ;
  115.     POOLDATA        *ptr ;
  116.     int                sw ;
  117.     WINCTRL            *pctrl ;
  118.     int                dx, dy ;
  119.     HYPER            hyp ;
  120.  
  121.     extern char    *splitFileName() ;
  122.     extern int    cbAnalysis() ;
  123.  
  124.     ret = ILLEGAL_FUNCTION ;
  125.  
  126.     switch(messId)
  127.     {
  128.         /*    アクティブになったときの処理                                */
  129.         /*    普通はあまりGM_WAKE時の処理を記述することはない                */
  130.         case    GM_WAKE :
  131.             /*    もし、GWAVが画面外に追い出されているような場合、        */
  132.             /*    アクティブにしても操作できなくなるため、画面内に        */
  133.             /*    移動する処理を行う                                        */
  134.             dx = dy = 0 ;
  135.             MMI_GetControl(&pctrl) ;    /*    画面の大きさを取得する        */
  136.             MMI_SendMessage(backId, MM_GETHYPER, 1, &hyp) ;
  137.             if (hyp.fr.lupx > pctrl->bound.rdwx)
  138.                 dx = pctrl->bound.rdwx - hyp.fr.lupx -
  139.                                             (hyp.fr.rdwx - hyp.fr.lupx) ;
  140.             if (hyp.fr.lupy > pctrl->bound.rdwy)
  141.                 dy = pctrl->bound.rdwy - hyp.fr.lupy -
  142.                                             (hyp.fr.rdwy - hyp.fr.lupy) ;
  143.             if (dx != 0 || dy != 0)
  144.             {
  145.                 /*    移動には、消去して座標移動してから表示するという    */
  146.                 /*    超原始的な方法を採用                                */
  147.                 /*    ほんとはクリップをうまく使って再描画したほうが        */
  148.                 /*    かっこいいんだけど…                                */
  149.                 MMI_SendMessage(backId, MM_ERASE, 0) ;
  150.                 MMI_SendMessage(backId, MM_MOVE, 2, dx, dy) ;
  151.                 MMI_SendMessage(backId, MM_SHOW, 0) ;
  152.             }
  153.             break ;
  154.  
  155.         /*    メモリ不足時の処理                                            */
  156.         /*    他のタスクでメモリがないらしいので、解放してあげよう        */
  157.         /*    後で再生するときには、また読み込めばよいのです                */
  158.         case    GM_PURGE :
  159.             /*    PCMデータ用のバッファを持っていたら解放する                */
  160.             if (wavBuffer != NULL)
  161.             {
  162.                 TL_free(wavBuffer) ;
  163.                 wavBuffer = NULL ;    /*    バッファがないので、NULLにする    */
  164.                 ret = NOERR ;
  165.             }
  166.             break ;
  167.  
  168.         /*    タスク終了時の処理                                            */
  169.         case    GM_QUIT :
  170.             /*    再生中なら、再生を中止する                                */
  171.             /*    停止ボタンを押すように呼び出し関数を実行するだけ        */
  172.             MMI_SendMessage(quitBtnId, MM_EXEC, 2, 0, 0) ;
  173.             ret = NOERR ;
  174.             break;
  175.  
  176.         /*    タスクの一時停止時の処理                                    */
  177.         /*    GM_PAUSEのタイミングではとにかく、もとの状態に可能な限り    */
  178.         /*    復元することを忘れてはいけない                                */
  179.         /*    他のタスクがすべての資源を専有する可能性があるので、        */
  180.         /*    とにかく起動前とほぼ同じ状態に戻すよう努力する                */
  181.         case    GM_PAUSE :
  182.             /*    再生中なら、再生を中止する                                */
  183.             /*    停止ボタンを押すように呼び出し関数を実行するだけ        */
  184.             MMI_SendMessage(wavStopBtnId, MM_EXEC, 2, 0, 0) ;
  185.             SND_elevol_mute(mute_data) ;        /*    ミュート状態を戻す    */
  186.             ret = NOERR ;
  187.             break ;
  188.  
  189.         /*    タスクの動作再開時の処理                                    */
  190.         /*    GM_PAUSEと反対に、自タスクが動作可能になるように処理する    */
  191.         case    GM_CONTINUE :
  192.             /*    再び再生可能なように再設定を行う                        */
  193.             mute_data = SND_get_elevol_mute(0) ;/*  ミュート情報の取得    */
  194.             SND_elevol_mute(mute_data | 0x01) ;    /*  PCMのミュートを解除    */
  195.             ret = NOERR ;
  196.             break;
  197.  
  198.         /*    プールからデータの送信を受けた時の処理                        */
  199.         /*    GWAVではパラメータ文字列を受け取るだけ                        */
  200.         case    GM_SENDDATA :
  201.             /*    パラメータ文字列 の受け取り                                */
  202.             if ((ptr = (POOLDATA *)MMI_CallMessage(MMI_GetApliId(),
  203.                                 GM_POOLDATA, PM_POOLID, data)) != NULL)
  204.             {
  205.                 if (!strcmp((char *)&ptr->Type, POOL_STR_CB))
  206.                 {
  207.                     sw = cbAnalysis(ptr) ;
  208.                     if (sw != ILLEGAL_FUNCTION)
  209.                     {
  210.                         if (info == MMI_GetApliId())
  211.                         {
  212.                             MMI_CallMessage(MMI_GetApliId(), GM_STACKDATA,
  213.                                                             FALSE, data) ;
  214.                         }
  215.                         /*    pathにパラメータ文字列が入っているので、    */
  216.                         /*    メッセージ型部品にファイル名部分のみ設定    */
  217.                         MMI_SendMessage(fnameMesId, MM_SETMSG, 1,
  218.                                         splitFileName(fileName, path)) ;
  219.                         MMI_SendMessage(fnameMesId, MM_SHOW, 0) ;
  220.  
  221.                         /*    PCMデータバッファを解放して、初期化する        */
  222.                         /*    そうでないと新しいデータが読めない            */
  223.                         if (wavBuffer != NULL)
  224.                         {
  225.                             TL_free(wavBuffer) ;
  226.                             wavBuffer = NULL ;
  227.                         }
  228.                         /*    音声再生開始                                */
  229.                         MMI_SendMessage(wavPlayBtnId, MM_EXEC, 2, 0, 0) ;
  230.                         ret = NOERR ;
  231.                     }
  232.                 }
  233.             }
  234.             break ;
  235.     }
  236.  
  237.     return ret ;
  238. }
  239.  
  240. /************************************************************************/
  241. /*    main関数                                                            */
  242. /*    GUIジェネレータでシェルアプリ用に生成した場合、こんな感じになる        */
  243. /*    ただし、argcとargvは追加部分                                        */
  244. /************************************************************************/
  245. void main(int argc, char *argv[])
  246. {
  247.     static MMICTRL mmi ={
  248.                 SCREEN16 | SCREENIGNORE,    /*    ページ0側解像度(16色)    */
  249.                 SCREENUNUSED,                /*    ページ1側解像度            */
  250.                 0,                             /*    書き込みページ            */
  251.                 SCREENAVAILABLE,             /*    表示ページ(色数無依存)    */
  252.                 0,                             /*    表示プライオリティ        */
  253.                 SCREENAVAILABLE,            /*    色数(画面枠自動設定)    */
  254.                 SCREENEXPAND,                 /*    VRAMの横の長さ            */
  255.                                             /*            (解像度無依存)    */
  256.                 0,                             /*    メモリ領域の大きさ        */
  257.                 NULL,                         /*    メモリ領域のアドレス    */
  258.                 0,                             /*    ユーザ領域の大きさ        */
  259.                 NULL,                         /*    ユーザ領域のアドレス    */
  260.                 0, 0,                         /*    画面枠    lupx,lupy        */
  261.                 0, 0,                        /*            rdwx,rdwy        */
  262.                 -16384, -16384,                /*    移動枠    lupx,lupy        */
  263.                 16383, 16383,                /*            rdwx,rdwy        */
  264.                 15,                         /*    白色                    */
  265.                 8,                          /*    黒色                    */
  266.                 7,                          /*    灰色                    */
  267.                 7                             /*    反転色                    */
  268.     } ;
  269.  
  270.     extern int    APL_init() ;
  271.     extern int    APL_end() ;
  272.     extern char    *splitFileName() ;
  273.     extern char    *cbSetupArea() ;
  274.  
  275.     int        kobj ;
  276.  
  277.     /*    二重起動チェック                                                */
  278.     /*    GWAVがすでにシェル上で動作していた場合は、既存のGWAVを有効に    */
  279.     /*    して、後から起動したGWAVを終了する                                */
  280.     /*    2個以上動作しても構わないプログラムなら、この処理は不要        */
  281.     if ((kobj = MMI_CallMessage(MMI_GetApliId(),
  282.                                         GM_QUERYID, QM_KIND, 1)) > NOERR)
  283.     {
  284.         int        id ;
  285.         char    *ptr ;
  286.  
  287.         if (argc > 1)
  288.         {
  289.             /*    パラメータがあればPOOL機能で既存のGWAVにパラメータの    */
  290.             /*    文字列を送信する                                        */
  291.             /*    ただ、GWAVではパラメータはサウンドファイル名の1個だけ    */
  292.             /*    なので、argv[1]だけにする                                */
  293.             if ((ptr = cbSetupArea(argv[1])) != NULL)
  294.             {
  295.                 /*    プールへデータを送る                                */
  296.                 id = MMI_CallMessage(MMI_GetApliId(), GM_STACKDATA,
  297.                                                         TRUE, (int)ptr) ;
  298.                 TL_free(ptr) ;
  299.  
  300.                 /*    プールにデータを送信できたら、次にそれを既存のGWAV    */
  301.                 /*    に送信する                                            */
  302.                 if (id > NOERR)
  303.                     MMI_CallMessage(kobj, GM_SENDDATA, kobj, id) ;
  304.             }
  305.             else
  306.             {
  307.                 /*    メモリ不足でプールに送信できなかった                */
  308.                 MMI_CallMessage(MMI_GetApliId(), GM_ALERT,
  309.                                     AM_ALERT1 | AM_ALERTB0E, (int)alertStr) ;
  310.             }
  311.         }
  312.         /*    既存のGWAVをアクティブにして、自分は終了する                */
  313.         /*    (二重起動の回避)                                            */
  314.         MMI_CallMessage(MMI_GetApliId(), GM_SWITCH, FALSE, kobj) ;
  315.         return ;
  316.     }
  317.  
  318.     /*    初期化処理                                                        */
  319.     if (MMI_Open( &mmi ) == NOERR)
  320.     {
  321.  
  322.         /*    初期化に成功すればメインループに入る.                        */
  323.         if (APL_init() == NOERR)
  324.         {
  325.             if (argc > 1)
  326.             {
  327.                 /*    パラメータはargv[1]の1個だけしか認識しない            */
  328.                 /*    しかも細かいチェックはしていない                    */
  329.                 strcpy(path, argv[1]) ;
  330.  
  331.                 /*    再生中のファイル名をメッセージ型に設定して表示        */
  332.                 MMI_SendMessage(fnameMesId, MM_SETMSG, 1,
  333.                                         splitFileName(fileName, path)) ;
  334.                 MMI_SendMessage(fnameMesId, MM_SHOW, 0) ;
  335.                 /*    再生開始                                            */
  336.                 MMI_SendMessage(wavPlayBtnId, MM_EXEC, 2, 0, 0) ;
  337.             }
  338.             /*    メインループ突入                                        */
  339.             MMI_ExecSystem() ;
  340.  
  341.             /*    後始末                                                    */
  342.             APL_end() ;
  343.         }
  344.         else
  345.         {
  346.             MMI_CallMessage(MMI_GetApliId(), GM_ALERT,
  347.                                     AM_ALERT1 | AM_ALERTB0E, (int)alertStr) ;
  348.         }
  349.     }
  350.  
  351.     /*    終了処理                                                        */
  352.     MMI_Close() ;
  353. }
  354.  
  355. /************************************************************************/
  356. /*    アプリケーション初期化関数                                            */
  357. /************************************************************************/
  358. int APL_init()
  359. {
  360.     extern MMIINIT    initDataIGWAV ;
  361.     extern void        centeringFunc() ;
  362.  
  363.     register int    ret ;
  364.     char    einWork[RSMWORKSIZE] ;    /*    リジュームマネージャのワークエリア        */
  365.     char    buf[RBUFSIZE] ;            /*    リジュームデータ読み込みバッファ        */
  366.     char    *ptr ;                    /*    タグ検索時に利用するポインタ    */
  367.     int        size, x, y;
  368.     HYPER    hyp ;
  369.  
  370.     /*    EGB ワークアドレスの取得.                                        */
  371.     guiEgbPtr = MMI_GetEgbPtr() ;
  372.  
  373.     /*    ハイパ型部品の初期化                                            */
  374.     if ((ret = MMI_initHyper()) < 0)
  375.         return ret ;
  376.     /*    ダイアログ型部品の初期化                                        */
  377.     if ((ret = MMI_initDialogL40()) < 0)
  378.         return ret ;
  379.     /*    アラート型部品の初期化                                            */
  380.     if ((ret = MMI_initAlertL40()) < 0)
  381.         return ret ;
  382.     /*    メッセージ型部品の初期化                                        */
  383.     if ((ret = MMI_initMessageL40()) < 0)
  384.         return ret ;
  385.     /*    ボタン型部品の初期化                                            */
  386.     if ((ret = MMI_initButtonL40()) < 0)
  387.         return ret ;
  388.     /*    ドロウボタン型部品の初期化                                        */
  389.     if ((ret = MMI_initDrawButtonL40()) < 0)
  390.         return ret ;
  391.     /*    アイコンボタン型部品の初期化                                    */
  392.     if ((ret = MMI_initIconL40()) < 0)
  393.         return ret ;
  394.     /*    スクロール型部品の初期化                                        */
  395.     if ((ret = MMI_initScrollBarL40()) < 0)
  396.         return ret ;
  397.     /*    テキスト型部品の初期化                                            */
  398.     if ((ret = MMI_initTextL40()) < 0)
  399.         return ret ;
  400.     /*    リストメニュー型部品の初期化                                    */
  401.     if ((ret = MMI_initListMenuL40()) < 0)
  402.         return ret ;
  403.  
  404.     /*    背景データの初期化                                                */
  405.  
  406.     /*    データの登録                                                    */
  407.     if ((ret = MMI_Init(&initDataIGWAV)) < 0)
  408.         return ret ;
  409.  
  410.     /*    ファイルダイアログライブラリの初期化処理                        */
  411.  
  412.     /*    ファイルダイアログがカレントを変更するため、起動時のカレント    */
  413.     /*    ドライブとカレントディレクトリを保存                            */
  414.     FDG_SaveCurDir() ;
  415.  
  416.     /*    ファイルダイアログライブラリの初期化                            */
  417.     /*    初期化を行わないと正常に動作しない                                */
  418.     /*    戻り値をチェックするのを忘れないこと                            */
  419.     if ((ret = FDG_InitFileDlg()) < 0)
  420.         return ret ;
  421.  
  422.     /*    リジュームマネージャの初期化(アプリのIDタグ登録)                */
  423.     size = 0 ;
  424.  
  425.     /*    失敗(0以外)だったらCD起動なのでリジュームしない                    */
  426.     if (EIN_rsmInit(einWork, RSMID) == 0)
  427.     {
  428.         /*    読み込みバッファの設定                                        */
  429.         EIN_rsmBufSet(einWork, buf, RBUFSIZE) ;
  430.         /*    リジューム情報読み込み                                        */
  431.         size = EIN_rsmLoad(einWork) ;
  432.     }
  433.     /*    ちゃんと読み込めたなら size>0 になるので、設定を変更します        */
  434.     if (size > 0)
  435.     {
  436.         /*    ダイアログ(PANEL)表示位置を、リジューム情報を元に設定        */
  437.         if (((ptr = strstr(buf,"\nPANEL: ")) != NULL ) &&
  438.                             (sscanf(ptr,"\nPANEL: %d %d\n", &x, &y) > 1))
  439.         {
  440.             MMI_SendMessage(backId, MM_GETHYPER, 1, &hyp) ;
  441.             rsmFrame.lupx = x ;
  442.             rsmFrame.lupy = y ;
  443.             rsmFrame.rdwx = x + (hyp.fr.rdwx - hyp.fr.lupx) ;
  444.             rsmFrame.rdwy = y + (hyp.fr.rdwy - hyp.fr.lupy) ;
  445.             if (x < -31)
  446.                 x = 0 ;
  447.             if (y < -31)
  448.                 y = 0 ;
  449.             MMI_SendMessage(backId, MM_MOVE, 1, &rsmFrame) ;
  450.         }
  451.     }
  452.     else
  453.     {
  454.         /*    デフォルトの起動時は必ず画面中央                            */
  455.         /*    リジュームファイルが見つからなかったときは画面中央に表示    */
  456.         centeringFunc(backId) ;
  457.     }
  458.  
  459.     /*    GUI色をメニュー色に設定                                            */
  460.     /*    GUIの色変換テーブルを変更して、どの画面モードでもメニュー色に    */
  461.     /*    なるよう設定する                                                */
  462.     EIN_initGuiColor() ;
  463.  
  464.     /*    背景を表示する                                                    */
  465.     MMI_SendMessage(MMI_GetBaseObj(), MM_SHOW, 0) ;
  466.  
  467.     /*    Townsシェル呼び出し関数(ユーザー関数)の設定                        */
  468.     MMI_SendMessage(MMI_GetBaseObj(), MM_SETEXEC, 1, userFunc);
  469.  
  470.     /*    タスク名の設定                                                    */
  471.     MMI_CallMessage(MMI_GetApliId(), GM_TITLE, (int)version, 0);
  472.  
  473.     mute_data = SND_get_elevol_mute(0) ;    /*  ミュート情報の取得        */
  474.     SND_elevol_mute(mute_data | 0x01) ;        /*  PCMのミュートを解除        */
  475.  
  476.     return NOERR ;
  477. }
  478.  
  479. int    APL_end()
  480. {
  481.     SND_elevol_mute(mute_data) ;            /*    ミュート状態を元に戻す    */
  482.  
  483.     /*    ファイルダイアログライブラリの終了処理                            */
  484.  
  485.     /*    ファイルダイアログのメモリ解放                                    */
  486.     /*    FDG_InitFileDlg関数と対にして使用する関数                        */
  487.     FDG_FreeFileDlg() ;
  488.  
  489.     /*    起動時のカレントドライブとカレントディレクトリを復帰            */
  490.     /*    FDG_SaveCurDir関数と対にして使用する関数                        */
  491.     FDG_RecovCurDir() ;
  492.  
  493.     return NOERR;
  494. }
  495.  
  496. /************************************************************************/
  497. /*    ここからサブプログラム部                                            */
  498. /*    呼び出し関数や個々の関数などの記述                                    */
  499. /************************************************************************/
  500.  
  501. /************************************************************************/
  502. /*    部品を画面中央に移動させる関数                                        */
  503. /*    親部品を指定すれば子部品も移動する                                    */
  504. /************************************************************************/
  505. void    centeringFunc(kobj)
  506. int        kobj ;
  507. {
  508.     int        dx, dy ;
  509.     HYPER    hyp ;
  510.     WINCTRL    *pctrl ;
  511.  
  512.     /*    WINCTRL構造体から画面最大サイズ(現在の解像度)を取得する        */
  513.     MMI_GetControl(&pctrl) ;
  514.  
  515.     /*    解像度にあわせて画面中央に移動させる                            */
  516.     MMI_SendMessage(kobj, MM_GETHYPER, 1, &hyp) ;
  517.     dx = (pctrl->bound.rdwx - hyp.fr.lupx - hyp.fr.rdwx) / 2 ;
  518.     dy = (pctrl->bound.rdwy - hyp.fr.lupy - hyp.fr.rdwy) / 2 ;
  519.     MMI_SendMessage(kobj, MM_MOVE, 2, dx, dy) ;
  520. }
  521.  
  522. /************************************************************************/
  523. /*    フルパスからファイル名を切り出す                                    */
  524. /*    (12文字に納まるようスペースで補完)                                */
  525. /************************************************************************/
  526. char    *splitFileName(char *fName, char *fullPath)
  527. {
  528.     register char    *ptr ;
  529.     char            space[] = "            " ;
  530.  
  531.     /*    fullPathの後ろから前に1文字ずつパス区切り記号'\'を探すため、    */
  532.     /*    fullPathの一番最後の文字へのポインタを求める                    */
  533.     ptr = fullPath + strlen(fullPath) - 1 ;
  534.     do
  535.     {
  536.         /*    文字が'\'で、なおかつその直前の文字が全角1バイト目でないか    */
  537.         /*    調べる(全角2バイト目の'\'である可能性を調べる)                */
  538.         /*    全角1バイト目かどうか調べるにはFNT_iskanjiマクロを使用する    */
  539.         if (*ptr == '\\' && !FNT_iskanji(*(ptr - 1)))
  540.         {
  541.             /*    '\'の直前が全角1バイト目でなければ、パス区切り記号と    */
  542.             /*    判断し、ptr変数が示す文字を'\'の直後の文字(ファイル名の    */
  543.             /*    先頭)にしてから、ループを脱出                            */
  544.             ptr++ ;
  545.             break ;
  546.         }
  547.         ptr-- ;
  548.     }
  549.     while (ptr > fullPath) ;
  550.     /*    fullPathに正しくフルパスで入っていれば、この終了条件を満たして    */
  551.     /*    ループを終了するのではなく、途中のif文の条件で脱出するはず        */
  552.  
  553.     /*    ファイル名部分の位置が分かったので、それ以降の文字列をコピー    */
  554.     strcpy(fileName, ptr) ;
  555.     strcat(fName, space) ;    /*    この方法好きじゃないんだけど・・・        */
  556.     fName[12] = '\0' ;        /*    High-Cのライブラリバグってるからねぇ    */
  557.  
  558.     return fName ;
  559. }
  560.  
  561. /************************************************************************/
  562. /*    ファイルダイアログ処理関数                                            */
  563. /*    呼び出すとファイルダイアログを表示してパス名を取得                    */
  564. /************************************************************************/
  565. int fdlgFunc(pPathName)
  566. char    *pPathName ;    /*    パス名を格納する配列                        */
  567. {
  568.     static    char    *ExtStr[3] = { "*.SND", "*.WAV", NULL } ;
  569.                                 /*    ワイルドカードの指定                */
  570.     unsigned int    MSlctCnt ;    /*    選択されたファイル数                */
  571.     unsigned int    InfSw ;        /*    表示属性                            */
  572.     int                Atr ;        /*    ファイル属性 (未使用)                */
  573.     int                ret ;
  574.     int                capa ;
  575.  
  576.     /*    WAVライブラリが使えないなら、.WAV選択不可とする                    */
  577.     if (WAV_getCapability(&capa, 19200) != 0)
  578.         ExtStr[1] = NULL ;
  579.  
  580.     /*    ファイルダイアログの表示                                        */
  581.  
  582.     /*    読込時にはファイル名テキスト入力不可にする                        */
  583.     /*    サブディレクトリは選択できない(FDG_FILEONLY)                    */
  584.     /*    ファイルが選択されない時実行ボタンを押せない(FDG_SLCTCHK)        */
  585.     /*    ついでにタスク切替え禁止(FDG_ALERT)                                */
  586.     InfSw = FDG_FILEONLY | FDG_SLCTCHK | FDG_REDRAW | FDG_ALERT ;
  587.  
  588.     /*    ファイルダイアログのタイトルを設定する                            */
  589.     FDG_SetTitle("サウンド読込", "読 込", "取 消") ;
  590.  
  591.     /*    退避したカレントディレクトリを復元して、ファイルダイアログ準備    */
  592.     /*    ファイルダイアログは、カレントディレクトリのファイル一覧を表示    */
  593.     /*    する仕様                                                        */
  594.     FM_SelectDisk(saveDrv) ;
  595.     FM_SetCurrentDir(saveDir) ;
  596.  
  597.     /*    ファイルダイアログ表示                                            */
  598.     ret = FDG_DspFileDlg(backId, InfSw, NULL, ExtStr, &MSlctCnt) ;
  599.  
  600.     /*    カレントディレクトリを退避                                        */
  601.     /*    また後でファイルダイアログを表示するときに、直前までと同じ        */
  602.     /*    ディレクトリを表示するために必要                                */
  603.     saveDrv = FM_GetCurrentDisk() ;
  604.     FM_GetCurrentDir(saveDrv, saveDir) ;
  605.  
  606.     if (ret && MSlctCnt > 0)
  607.     {
  608.         /*    "読込"が押され、なおかつファイルが選択されていたならば、    */
  609.         /*    ファイル名を取得する                                        */
  610.         FDG_GetPathName(pPathName, &Atr, 0) ;
  611.     }
  612.     else
  613.     {
  614.         /*    "取消"が押されたか1つもファイルが選択されなかった場合は    */
  615.         /*    ファイル名を取得しないで終了する                            */
  616.         ret = 0 ;
  617.     }
  618.  
  619.     return ret ;
  620. }
  621.  
  622. /************************************************************************/
  623. /*    "CB"形式のプールデータを解析                                        */
  624. /*    実はこの関数、プール用サンプルとほぼ同じもの                        */
  625. /*    (どう処理したらいいのかマニュアルとか見ただけじゃわかんない(^^;)    */
  626. /************************************************************************/
  627. int cbAnalysis(ptr)
  628. POOLDATA    *ptr ;
  629. {
  630.     int                ret = ILLEGAL_FUNCTION ;
  631.     size_t            size, len ;
  632.     unsigned char    *rec, *work ;
  633.     unsigned short    tag ;
  634.  
  635.     if (ptr->Kind & POOL_REAL)
  636.     {
  637.         /*    テキストブロックの先頭アドレスを探す                        */
  638.         if (POL_cbSearchBlock((unsigned char *)ptr->dPtr, PCBF_TEXT, 1,
  639.                                                             &rec, &size))
  640.         {
  641.             work = POL_cbGetRecSize(rec, &len) ;
  642.             /*    タグ解析中                                                */
  643.             do
  644.             {
  645.                 tag = *(unsigned short *)work ;
  646.                 work = POL_cbGetRecSize(work, &len) ;
  647.  
  648.                 /*    テキストファイル名か?                                */
  649.                 if ((tag & 0xff) == PCBF_TEXTFILE)
  650.                 {
  651.                     /*    ファイル名設定                                    */
  652.                     strcpy(path, (char *)work) ;
  653.                     ret = 0 ;
  654.                 }
  655.                 work += len ;
  656.             }
  657.             while ((tag & 0xff) != 0x1f) ;    /*    データレコード終了        */
  658.         }
  659.     }
  660.     return ret ;
  661. }
  662.  
  663. /************************************************************************/
  664. /*    プールデータヘッダ用領域とCB用領域を確保/初期化/ファイル名設定         */
  665. /*    実はこの関数も、プール用サンプルとほぼ同じもの                        */
  666. /*    (どう処理したらいいのかマニュアルとか見ただけじゃわかんない(^^;)    */
  667. /************************************************************************/
  668. char *cbSetupArea(setupStr)
  669. char    *setupStr ;
  670. {
  671.     typedef struct _CB_SMPTEXT {
  672.         CB_TAG_LONG        Main ;
  673.         CB_TAG            Sub ;
  674.         unsigned short    SubId ;
  675.         CB_TAG            Text ;
  676.     } CB_SMPTEXT ;
  677.  
  678.     char            *ret = NULL ;
  679.     char             *ptr ;
  680.     POOLDATA        *pol ;
  681.     unsigned char    *text, *addrec, *cb ;
  682.     size_t            hSize, cbSize, tSize, nSize = 80 ;
  683.     char            str[16] ;
  684.  
  685.     /*    テキストブロックの大きさを計算する                                */
  686.     tSize = sizeof(CB_SMPTEXT) + sizeof(CB_TAG) + nSize ;
  687.  
  688.     /*    "CB"型データ全体の大きさを計算する                                */
  689.     cbSize = PCB_DEF_SIZE + PCB_MREC_SIZE * 2 + tSize ;
  690.  
  691.     /*    プールデータヘッダ用領域の大きさ                                */
  692.     hSize = sizeof(POOLDATA) ;
  693.  
  694.     /*    メモリ獲得時に一定のメモリを残しておく                            */
  695.     if ((TL_checkMemory(1) * 4096) > (1024 * 16 + hSize + cbSize))
  696.     {
  697.         if ((ptr = TL_malloc(hSize + cbSize))==NULL)
  698.             return ret ;
  699.  
  700.         /*    確保したメモリの先頭をプールデータヘッダ用に                */
  701.         /*    残りを"CB"領域に使用する                                    */
  702.         pol = (POOLDATA *)ptr ;
  703.         cb = (unsigned char *)(ptr + hSize);
  704.  
  705.         /*    プールヘッダの設定                                            */
  706.         MMI_CallMessage(MMI_GetApliId(),GM_QUERYID, QM_FILENAME, (int)str) ;
  707.         strcpy((char *)&pol->Creator, str) ;        /*    データ本体編集者    */
  708.         strcpy((char *)&pol->Owner, str) ;            /*    プールデータ作成者    */
  709.         strcpy((char *)&pol->Type, POOL_STR_CB) ;    /*    データ型            */
  710.         pol->apliId = MMI_GetApliId() ;                /*    プールデータ作成者    */
  711.                                                     /*        アプリケーションID    */
  712.         pol->Kind = POOL_REAL ;                        /*    データ種別        */
  713.         pol->dPtr = (void *)cb ;                    /*    データサイズ        */
  714.         pol->dSize = cbSize ;                        /*    データ本体ポインタ    */
  715.  
  716.         /*    "CB"型アクセス用関数を使用して                                */
  717.         /*    "CB"用に確保した領域を"CB"領域として初期化する                */
  718.         if (!POL_cbInit(cb, 2, cbSize, 0))
  719.         {
  720.             /*    "CB"領域にテキストブロックを登録する                    */
  721.             if (!POL_cbAddBlock(cb, PCBF_TEXT, tSize, &text))
  722.             {
  723.                 /*    テキストブロックにレコードを追加する                */
  724.                 POL_cbAddRec(text, PCBF_TEXTKIND, 0, 2, &addrec) ;
  725.                 *(unsigned short *)addrec = 0 ;
  726.  
  727.                 POL_cbAddRec(text, PCBF_TEXTFILE, 0, nSize, &addrec) ;
  728.                 strcpy((char *)addrec, setupStr) ;
  729.  
  730.                 ret = ptr ;
  731.             }
  732.         }
  733.         /*    "CB"領域の設定に失敗した場合は、確保した領域を解放する        */
  734.         if (!ret)
  735.             TL_free(ptr) ;
  736.     }
  737.     return ret ;
  738. }
  739.  
  740. /************************************************************************/
  741. /*    リジューム情報の更新                                                */
  742. /*    EIN(TM)環境用ライブラリのリジュームマネージャを使用                    */
  743. /************************************************************************/
  744. void    saveResumeFile()
  745. {
  746.     char    work[RSMWORKSIZE] ;    /*    リジュームマネージャワーク            */
  747.     char    buf[RBUFSIZE] ;        /*    リジュームデータセーブバッファ        */
  748.     char    aplPath[128] ;        /*    アプリディレクトリパス名            */
  749.     HYPER    hyp ;
  750.  
  751.     /*    リジュームマネージャの初期化に失敗したらセーブできないので終了    */
  752.     /*    失敗(0以外)だったらCD起動なのでリジュームしない                    */
  753.     if (EIN_rsmInit(work, RSMID) != 0)
  754.         return ;
  755.  
  756.     /*    パネルの枠座標を得る                                            */
  757.     MMI_SendMessage(backId, MM_GETHYPER, 1, &hyp) ;
  758.  
  759.     /*    設定が変化していた(ユーザーが部品を移動した)ら保存する        */
  760.     if ((rsmFrame.lupx != hyp.fr.lupx) || (rsmFrame.lupy != hyp.fr.lupy))
  761.     {
  762.         /*    バッファ設定(アプリ識別IDと更新時刻を自動設定する)        */
  763.         EIN_rsmBufSet(work, buf, RBUFSIZE) ;
  764.  
  765.         /*    アプリディレクトリ保存                                        */
  766.         MMI_CallMessage(MMI_GetApliId(), GM_QUERYID, QM_PATH, (int)aplPath) ;
  767.         EIN_rsmBufPrintf(work, "APLPATH: %s", aplPath) ;
  768.  
  769.         /*    アプリ名保存                                                */
  770.         EIN_rsmBufPrintf(work, "TITLE:   %s", version) ;
  771.  
  772.         /*    コメント保存                                                */
  773.         EIN_rsmBufCat(work, "COMMENT: SND/WAV音声データプレイヤーです。") ;
  774.  
  775.         /*    位置保存                                                    */
  776.         EIN_rsmBufPrintf(work, "PANEL:   %d %d", hyp.fr.lupx, hyp.fr.lupy) ;
  777.  
  778.         /*    バッファ終端設定                                            */
  779.         EIN_rsmBufTail(work) ;
  780.  
  781.         /*    バッファの内容を保存                                        */
  782.         /*    (バッファの容量が足りないと失敗するので、容量を増やして        */
  783.         /*    retryするべき…らしいんだけど、やってなかったりする(^^;)    */
  784.         /*    バッファサイズ固定にしちゃってるし…                        */
  785.         EIN_rsmSave(work) ;
  786.  
  787.         /*    リジュームした座標を保存しておく(移動したかどうかの判定)    */
  788.         rsmFrame  = hyp.fr ;
  789.     }
  790. }
  791.  
  792. /************************************************************************/
  793. /*    終了ボタンを押すと実行する呼び出し関数                                */
  794. /*    initDataIGWAV:quitBtnId:MJ_ICONL40の呼び出し関数                    */
  795. /************************************************************************/
  796. int    quitFunc(kobj, messId, argc, pev, trigger)
  797. int        kobj ;
  798. int        messId ;
  799. int        argc ;
  800. EVENT    *pev ;
  801. int        trigger ;
  802. {
  803.     /*    リジュームを行う(EIN(TM)リジュームマネージャ使用)                */
  804.     saveResumeFile() ;
  805.  
  806.     /*    停止ボタンを押して、再生を停止する                                */
  807.     MMI_SendMessage(wavStopBtnId, MM_EXEC, 2, 0, 0) ;
  808.  
  809.     /*    PCMデータバッファを解放                                            */
  810.     /*    解放を忘れると、メモリが残ったままプログラムが終わるので、PCM    */
  811.     /*    データバッファ分だけフリーエリアが減ってしまう                    */
  812.     if (wavBuffer != NULL)
  813.         TL_free(wavBuffer) ;
  814.  
  815.     /*    プログラムを終了                                                */
  816.     MMI_SetHaltFlag(TRUE) ;
  817.  
  818.     return NOERR ;
  819. }
  820.  
  821. /************************************************************************/
  822. /*    再生ボタンを押すと実行する呼び出し関数                                */
  823. /*    initDataIGWAV:wavPlayBtnId:MJ_ICONL40の呼び出し関数                    */
  824. /************************************************************************/
  825. int    wavPlayFunc(kobj, messId, argc, pev, trigger)
  826. int        kobj ;
  827. int        messId ;
  828. int        argc ;
  829. EVENT    *pev ;
  830. int        trigger ;
  831. {
  832.     FILE    *fp ;
  833.     int        note ;
  834.     int        stackPtr ;
  835.     int        rdSize ;
  836.     int        ret ;
  837.     int        capa ;
  838.     char    *ptr ;
  839.  
  840.     /*    停止ボタンを押して、再生を停止する                                */
  841.     MMI_SendMessage(wavStopBtnId, MM_EXEC, 2, 0, 0) ;
  842.  
  843.     /*    拡張子を探そう                                                    */
  844.     /*    '.'がなければ終わってしまう                                        */
  845.     if ((ptr = strrchr(path, '.')) == NULL)
  846.         return NOERR ;
  847.  
  848.     /*    拡張子が.WAVならば、wavFlagをONにして、WAV再生モードに入る        */
  849.     if (strcmp(ptr, ".WAV") == 0)
  850.     {
  851.         /*    WAV再生が不可な状態にあるならば、なにもせず処理を終了        */
  852.         if (WAV_getCapability(&capa, 19200) == 0)
  853.         {
  854.             wavFlag = TRUE ;
  855.         }
  856.         else
  857.         {
  858.             /*    WAVが再生可能ではないのに無理やり再生しようとした        */
  859.             MMI_CallMessage(MMI_GetApliId(), GM_ALERT,
  860.                                     AM_ALERT1 | AM_ALERTB0E, (int)alertStr2) ;
  861.  
  862.             return NOERR ;
  863.         }
  864.     }
  865.     else
  866.     {
  867.         wavFlag = FALSE ;
  868.     }
  869.  
  870.     /*    PCMデータバッファを確保していなければ、確保してデータを読み込む    */
  871.     if (wavBuffer == NULL)
  872.     {
  873.         /*    パスが指定されてなければ、なにもしない                        */
  874.         if (path[0] == '\0')
  875.             return NOERR ;
  876.  
  877.         /*    マウスカーソルを時計マークにする                            */
  878.         MG_PushPtr(MB_WAIT, &stackPtr) ;
  879.  
  880.         /*    データファイルをオープン                                    */
  881.         if ((fp = fopen(path, "rb")) == 0)
  882.         {
  883.             /*    マウスカーソルを元に戻す                                */
  884.             MG_PopPtr(stackPtr) ;
  885.  
  886.             /*    音声ファイルが見つからない                                */
  887.             MMI_CallMessage(MMI_GetApliId(), GM_ALERT,
  888.                                     AM_ALERT1 | AM_ALERTB0E, (int)alertStr3) ;
  889.  
  890.             return NOERR ;
  891.         }
  892.  
  893.         /*    WAV再生モード                                                */
  894.         if (wavFlag == TRUE)
  895.         {
  896.             rdSize = 0 ;
  897.             /*    WAVファイルのヘッダから、必要な情報を得る                */
  898.             /*    ヘッダのサイズが不定なので、正常に読み込めるまでループ    */
  899.             do
  900.             {
  901.                 char    *tmpPtr ;
  902.  
  903.                 rdSize += 50 ;
  904.                 fseek(fp, 0, SEEK_SET) ;
  905.  
  906.                 /*    ヘッダバッファの取得                                */
  907.                 if ((tmpPtr = TL_malloc(rdSize)) == NULL)
  908.                 {
  909.                     /*    データファイルをクローズ                        */
  910.                     fclose(fp) ;
  911.  
  912.                     /*    マウスカーソルを元に戻す                        */
  913.                     MG_PopPtr(stackPtr) ;
  914.  
  915.                     /*    メモリが足りない                                */
  916.                     MMI_CallMessage(MMI_GetApliId(), GM_ALERT,
  917.                                     AM_ALERT1 | AM_ALERTB0E, (int)alertStr) ;
  918.  
  919.                     return NOERR ;
  920.                 }
  921.                 fread(tmpPtr, sizeof(char), rdSize, fp) ;
  922.                 ret = WAV_getWaveInfo(tmpPtr, rdSize, &freq, &bitno,
  923.                                             &kind, &pcmLen, &pcmStart) ;
  924.  
  925.                 /*    いらなくなったので、ヘッダバッファを解放            */
  926.                 TL_free(tmpPtr) ;
  927.             }
  928.             while (ret == 23) ;
  929.         }
  930.         /*    SND再生モード                                                */
  931.         else
  932.         {
  933.             fseek(fp, 0, SEEK_END) ;
  934.             pcmLen = (unsigned int)ftell(fp) ;
  935.             fseek(fp, 0, SEEK_SET) ;
  936.         }
  937.  
  938.         /*    必要なバッファサイズが判明したので、メモリを確保            */
  939.         if ((wavBuffer = TL_malloc(pcmLen)) == NULL)
  940.         {
  941.             /*    データファイルをクローズ                                */
  942.             fclose(fp) ;
  943.  
  944.             /*    マウスカーソルを元に戻す                                */
  945.             MG_PopPtr(stackPtr) ;
  946.  
  947.             /*    メモリが足りない                                */
  948.             MMI_CallMessage(MMI_GetApliId(), GM_ALERT,
  949.                                     AM_ALERT1 | AM_ALERTB0E, (int)alertStr) ;
  950.  
  951.             return NOERR ;
  952.         }
  953.  
  954.         /*    念のためバッファ内を初期化する(TL_mallocは0クリア保証なし)    */
  955.         memset(wavBuffer, 0, pcmLen) ;
  956.  
  957.         /*    WAVなら、WAVデータ本体の先頭にシーク                        */
  958.         /*    WAVの先頭のヘッダ部分は飛ばして読み込まなくてはならない点に    */
  959.         /*    注意すること                                                */
  960.         if (wavFlag == TRUE)
  961.             fseek(fp, pcmStart, SEEK_SET) ;
  962.  
  963.         /*    データの読み込み                                            */
  964.         fread(wavBuffer, sizeof(char), pcmLen, fp) ;
  965.  
  966.         /*    データファイルをクローズ                                    */
  967.         fclose(fp) ;
  968.  
  969.         /*    マウスカーソルを元に戻す                                    */
  970.         MG_PopPtr(stackPtr) ;
  971.     }
  972.  
  973.     if (wavFlag == TRUE)
  974.     {
  975.                                             /*    WAV再生準備                */
  976.         ret = WAV_playPrepare(freq, bitno, kind, wavBuffer, (void (*)())NULL) ;
  977.         if (ret == 21)
  978.         {
  979.             /*    再生周波数がサポートしているものと違う場合、エラー        */
  980.             /*    でも、近い周波数で再生してくれると嬉しい                */
  981.             int    i, prevAbs ;
  982.  
  983.             if (freq < freqTbl[0])
  984.             {
  985.                 /*    アンダーフローは、全部一番低いサンプリング周波数に    */
  986.                 freq = freqTbl[0] ;
  987.             }
  988.             else if (freq > freqTbl[10])
  989.             {
  990.                 /*    オーバーフローは、全部一番高いサンプリング周波数に    */
  991.                 freq = freqTbl[10] ;
  992.             }
  993.             else
  994.             {
  995.                 /*    中間なら近いものを探し出す                            */
  996.                 prevAbs = abs(freq - freqTbl[0]) ;
  997.                 for (i = 1; i < 11; prevAbs = abs(freq - freqTbl[i]), i++)
  998.                 {
  999.                     /*    前のほうが近かったぞ                            */
  1000.                     if (prevAbs < abs(freq - freqTbl[i]))
  1001.                         break ;
  1002.                 }
  1003.                 freq = freqTbl[i - 1] ;
  1004.             }
  1005.                                     /*    WAV再生準備(逆襲の周波数編)    */
  1006.             ret = WAV_playPrepare(freq, bitno, kind, wavBuffer,
  1007.                                                             (void (*)())NULL) ;
  1008.         }
  1009.  
  1010.         if (ret != 0)
  1011.         {
  1012.             /*    再生準備(WAV_playPrepare)に失敗したから再生できず        */
  1013.             MMI_CallMessage(MMI_GetApliId(), GM_ALERT,
  1014.                                     AM_ALERT1 | AM_ALERTB0E, (int)alertStr4) ;
  1015.  
  1016.             TL_free(wavBuffer) ;
  1017.             wavBuffer = NULL ;
  1018.             return NOERR ;
  1019.         }
  1020.  
  1021.         WAV_setVolume(127, 127) ;            /*    ボリュームを最大に        */
  1022.         WAV_play(pcmLen) ;                    /*    WAVの再生開始            */
  1023.     }
  1024.     else
  1025.     {
  1026.         SND_pcm_mode_set(3) ;                /*  PCMの3チャンネルが音声モード    */
  1027.         note = (char)wavBuffer[28] ;        /*  サウンドデータ基本音階の取得    */
  1028.         SND_pcm_play(ch, note, 127, wavBuffer) ;
  1029.                                             /*    SNDの再生開始            */
  1030.                                             /*    (ボリュームは最大)        */
  1031.     }
  1032.  
  1033.     return NOERR ;
  1034. }
  1035.  
  1036. /************************************************************************/
  1037. /*    ファイル選択ボタンを押すと実行する呼び出し関数                        */
  1038. /*    initDataIGWAV:fileSlctId:MJ_ICONL40の呼び出し関数                    */
  1039. /************************************************************************/
  1040. int    loadFunc(kobj, messId, argc, pev, trigger)
  1041. int        kobj ;
  1042. int        messId ;
  1043. int        argc ;
  1044. EVENT    *pev ;
  1045. int        trigger ;
  1046. {
  1047.     /*    ファイルダイアログで何も選択されなかったらそのまま終了            */
  1048.     if (fdlgFunc(path) == 0)
  1049.         return NOERR ;
  1050.  
  1051.     /*    ファイル名をメッセージ型部品に設定                                */
  1052.     MMI_SendMessage(fnameMesId, MM_SETMSG, 1, splitFileName(fileName, path)) ;
  1053.     MMI_SendMessage(fnameMesId, MM_SHOW, 0) ;
  1054.  
  1055.     /*    PCMデータバッファの解放                                            */
  1056.     TL_free(wavBuffer) ;
  1057.     wavBuffer = NULL ;
  1058.  
  1059.     /*    音声再生開始                                                    */
  1060.     MMI_SendMessage(wavPlayBtnId, MM_EXEC, 2, 0, 0) ;
  1061.  
  1062.     return NOERR ;
  1063. }
  1064.  
  1065. /************************************************************************/
  1066. /*    停止ボタンを押すと実行する呼び出し関数                                */
  1067. /*    initDataIGWAV:wavStopBtnId:MJ_ICONL40の呼び出し関数                    */
  1068. /************************************************************************/
  1069. int    wavStopFunc(kobj, messId, argc, pev, trigger)
  1070. int        kobj ;
  1071. int        messId ;
  1072. int        argc ;
  1073. EVENT    *pev ;
  1074. int        trigger ;
  1075. {
  1076.     /*    WAV再生モード時                                                    */
  1077.     if (wavFlag == TRUE)
  1078.     {
  1079.         int    status ;
  1080.  
  1081.         WAV_playStop() ;    /*    WAV再生を止める                            */
  1082.  
  1083.         /*    WAV再生終了を待つ                                            */
  1084.         do
  1085.         {
  1086.             WAV_getStatus(&status) ;
  1087.         }
  1088.         while (status & WAV_ST_PLAY_PLAYING) ;
  1089.  
  1090.         /*    WAV再生可能状態に戻るのを待つ                                */
  1091.         do
  1092.         {
  1093.             WAV_getStatus(&status) ;
  1094.         }
  1095.         while (status & WAV_ST_PLAY_PROCESS) ;
  1096.  
  1097.         /*    WAVをリセットして以後の処理が正常に行えるようにする            */
  1098.         WAV_reset() ;
  1099.         WAV_setVolume(127, 127) ;
  1100.         SND_pcm_sound_delete(-1) ;
  1101.     }
  1102.     /*    SND再生モード時                                                    */
  1103.     else
  1104.     {
  1105.         SND_pcm_play_stop(ch) ;            /*    SND再生を止める                */
  1106.         while (SND_pcm_status(ch))        /*    SND再生終了を待つ            */
  1107.             ;
  1108.         SND_pcm_sound_delete(-1) ;
  1109.     }
  1110.  
  1111.     return NOERR ;
  1112. }
  1113.