2 * @file main-win-music.cpp
3 * @brief Windows版固有実装(BGM)
6 #include "main-win/main-win-music.h"
7 #include "dungeon/quest.h"
8 #include "floor/floor-town.h"
9 #include "main-win/main-win-define.h"
10 #include "main-win/main-win-file-utils.h"
11 #include "main-win/main-win-mci.h"
12 #include "main-win/main-win-mmsystem.h"
13 #include "main-win/main-win-tokenizer.h"
14 #include "main/scene-table.h"
15 #include "term/z-term.h"
16 #include "util/angband-files.h"
17 #include "world/world.h"
19 static int current_music_type = TERM_XTRA_MUSIC_MUTE;
20 static int current_music_id = 0;
21 // current filename being played
22 static char current_music_path[MAIN_WIN_MAX_PATH];
27 concptr ANGBAND_DIR_XTRA_MUSIC;
32 CfgData *music_cfg_data;
34 namespace main_win_music {
37 * @brief action-valに対応する[Basic]セクションのキー名を取得する
38 * @param index "term_xtra()"の第2引数action-valに対応する値
42 static concptr basic_key_at(int index, char *buf)
46 if (index >= MUSIC_BASIC_MAX)
49 return angband_music_basic_name[index];
52 static inline DUNGEON_IDX get_dungeon_count()
54 return current_world_ptr->max_d_idx;
58 * @brief action-valに対応する[Dungeon]セクションのキー名を取得する
59 * @param index "term_xtra()"の第2引数action-valに対応する値
63 static concptr dungeon_key_at(int index, char *buf)
65 if (index >= get_dungeon_count())
68 sprintf(buf, "dungeon%03d", index);
72 static inline QUEST_IDX get_quest_count()
78 * @brief action-valに対応する[Quest]セクションのキー名を取得する
79 * @param index "term_xtra()"の第2引数action-valに対応する値
83 static concptr quest_key_at(int index, char *buf)
85 if (index >= get_quest_count())
88 sprintf(buf, "quest%03d", index);
92 static inline TOWN_IDX get_town_count()
98 * @brief action-valに対応する[Town]セクションのキー名を取得する
99 * @param index "term_xtra()"の第2引数action-valに対応する値
103 static concptr town_key_at(int index, char *buf)
105 if (index >= get_town_count())
108 sprintf(buf, "town%03d", index);
113 * @brief BGMの設定を読み込む。
115 * "music_debug.cfg"ファイルを優先して読み込む。無ければ"music.cfg"ファイルを読み込む。
116 * この処理は複数回実行されることを想定していない。複数回実行した場合には前回読み込まれた設定のメモリは解放されない。
118 void load_music_prefs()
120 CfgReader reader(ANGBAND_DIR_XTRA_MUSIC, { "music_debug.cfg", "music.cfg" });
122 GetPrivateProfileString("Device", "type", "MPEGVideo", mci_device_type, _countof(mci_device_type), reader.get_cfg_path());
125 music_cfg_data = reader.read_sections({
126 { "Basic", TERM_XTRA_MUSIC_BASIC, basic_key_at },
127 { "Dungeon", TERM_XTRA_MUSIC_DUNGEON, dungeon_key_at },
128 { "Quest", TERM_XTRA_MUSIC_QUEST, quest_key_at },
129 { "Town", TERM_XTRA_MUSIC_TOWN, town_key_at }
137 errr stop_music(void)
139 mciSendCommand(mci_open_parms.wDeviceID, MCI_STOP, MCI_WAIT, 0);
140 mciSendCommand(mci_open_parms.wDeviceID, MCI_CLOSE, MCI_WAIT, 0);
141 current_music_type = TERM_XTRA_MUSIC_MUTE;
142 current_music_id = 0;
143 strcpy(current_music_path, "\0");
150 errr play_music(int type, int val)
152 if (type == TERM_XTRA_MUSIC_MUTE)
155 if (current_music_type == type && current_music_id == val)
156 return 0; // now playing
158 concptr filename = music_cfg_data->get_rand(type, val);
160 return 1; // no setting
162 char buf[MAIN_WIN_MAX_PATH];
163 path_build(buf, MAIN_WIN_MAX_PATH, ANGBAND_DIR_XTRA_MUSIC, filename);
165 if (current_music_type != TERM_XTRA_MUSIC_MUTE)
166 if (0 == strcmp(current_music_path, buf))
167 return 0; // now playing same file
169 current_music_type = type;
170 current_music_id = val;
171 strcpy(current_music_path, buf);
173 mci_open_parms.lpstrDeviceType = mci_device_type;
174 mci_open_parms.lpstrElementName = buf;
175 mciSendCommand(mci_open_parms.wDeviceID, MCI_STOP, MCI_WAIT, 0);
176 mciSendCommand(mci_open_parms.wDeviceID, MCI_CLOSE, MCI_WAIT, 0);
177 mciSendCommand(mci_open_parms.wDeviceID, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT | MCI_NOTIFY, (DWORD)&mci_open_parms);
178 // Send MCI_PLAY in the notification event once MCI_OPEN is completed
183 * Play a music matches a situation
185 errr play_music_scene()
187 // テーブルの先頭から順に再生を試み、再生できたら抜ける
188 auto ite = get_scene_table_iterator();
189 const errr err_sucsess = 0;
190 while (play_music(ite->type, ite->val) != err_sucsess) {
200 void on_mci_notify(WPARAM wFlags, LONG lDevID)
202 UNREFERENCED_PARAMETER(lDevID);
204 if (wFlags == MCI_NOTIFY_SUCCESSFUL) {
205 // play a music (repeat)
206 mciSendCommand(mci_open_parms.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START | MCI_WAIT, 0);
207 mciSendCommand(mci_open_parms.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)&mci_play_parms);