• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

MIDITrail をピカピカにする。鍵盤方向自動切替・多ポート・歌詞対応等


Commit MetaInfo

Revision949cf3661daeb3ae18e4d256f868f95e87b83e23 (tree)
Time2022-08-12 01:13:00
Authoryoshy <yoshy.org.bitbucket@gz.j...>
Commiteryoshy

Log Message

[UPGRADE] original 1.3.3

Change Summary

Incremental Difference

--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,5 +1,5 @@
11
2-Copyright (c) 2010-2019, WADA Masashi <yknk@users.osdn.me>
2+Copyright (c) 2010-2021, WADA Masashi <yknk@users.osdn.me>
33 All rights reserved.
44
55 Redistribution and use in source and binary forms, with or without
--- a/MIDITrail/MIDITrail.rc
+++ b/MIDITrail/MIDITrail.rc
@@ -45,7 +45,12 @@ IDC_MIDITRAIL MENU
4545 BEGIN
4646 POPUP "File"
4747 BEGIN
48- MENUITEM "Open...\tCtrl + O", IDM_OPEN_FILE
48+ MENUITEM "Open File...\tCtrl + O", IDM_OPEN_FILE
49+ MENUITEM "Open Folder...", IDM_OPEN_FOLDER
50+ MENUITEM SEPARATOR
51+ MENUITEM "Previous File\tCtrl + P", IDM_PREVIOUS_FILE
52+ MENUITEM "Next File\tCtrl + N", IDM_NEXT_FILE
53+ MENUITEM SEPARATOR
4954 MENUITEM "Exit", IDM_EXIT
5055 END
5156 POPUP "Playback"
@@ -53,6 +58,7 @@ BEGIN
5358 MENUITEM "Play / Pause\tSpace", IDM_PLAY
5459 MENUITEM "Stop\tEsc", IDM_STOP
5560 MENUITEM "Repeat", IDM_REPEAT
61+ MENUITEM "Folder Playback", IDM_FOLDER_PLAYBACK
5662 MENUITEM SEPARATOR
5763 MENUITEM "Skip Back\t1", IDM_SKIP_BACK
5864 MENUITEM "Skip Forward\t2", IDM_SKIP_FORWARD
--- a/MIDITrail/MIDITrail.vcxproj
+++ b/MIDITrail/MIDITrail.vcxproj
@@ -216,6 +216,7 @@
216216 <ClCompile Include="MTDashboard.cpp" />
217217 <ClCompile Include="MTDashboardLive.cpp" />
218218 <ClCompile Include="MTDynamicCaption.cpp" />
219+ <ClCompile Include="MTFileList.cpp" />
219220 <ClCompile Include="MTFirstPersonCam.cpp" />
220221 <ClCompile Include="MTFont2Bmp.cpp" />
221222 <ClCompile Include="MTFontTexture.cpp" />
@@ -293,6 +294,7 @@
293294 <ClInclude Include="MTDashboard.h" />
294295 <ClInclude Include="MTDashboardLive.h" />
295296 <ClInclude Include="MTDynamicCaption.h" />
297+ <ClInclude Include="MTFileList.h" />
296298 <ClInclude Include="MTFirstPersonCam.h" />
297299 <ClInclude Include="MTFont2Bmp.h" />
298300 <ClInclude Include="MTFontTexture.h" />
--- a/MIDITrail/MIDITrail.vcxproj.filters
+++ b/MIDITrail/MIDITrail.vcxproj.filters
@@ -257,6 +257,9 @@
257257 <ClCompile Include="MTNoteRippleRingLive.cpp">
258258 <Filter>Sources\SceneObject</Filter>
259259 </ClCompile>
260+ <ClCompile Include="MTFileList.cpp">
261+ <Filter>Sources\Utility</Filter>
262+ </ClCompile>
260263 </ItemGroup>
261264 <ItemGroup>
262265 <ClInclude Include="MIDITrailApp.h">
@@ -478,5 +481,8 @@
478481 <ClInclude Include="MTNoteRippleRingLive.h">
479482 <Filter>Sources\SceneObject</Filter>
480483 </ClInclude>
484+ <ClInclude Include="MTFileList.h">
485+ <Filter>Sources\Utility</Filter>
486+ </ClInclude>
481487 </ItemGroup>
482488 </Project>
\ No newline at end of file
--- a/MIDITrail/MIDITrailApp.cpp
+++ b/MIDITrail/MIDITrailApp.cpp
@@ -4,13 +4,14 @@
44 //
55 // MIDITrail アプリケーションクラス
66 //
7-// Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
1111 #include "StdAfx.h"
1212 #include "imagehlp.h"
1313 #include "shellapi.h"
14+#include "shlwapi.h"
1415 #include "YNBaseLib.h"
1516 #include "MTParam.h"
1617 #include "MTConfFile.h"
@@ -26,6 +27,8 @@
2627 #include "MTScenePianoRollRainLive.h"
2728 #include "MTScenePianoRollRain2DLive.h"
2829 #include "MTScenePianoRollRingLive.h"
30+#include <ShObjIdl.h>
31+#include <mbctype.h>
2932
3033 using namespace YNBaseLib;
3134
@@ -65,6 +68,7 @@ MIDITrailApp::MIDITrailApp(void)
6568 //演奏状態
6669 m_PlayStatus = NoData;
6770 m_isRepeat = false;
71+ m_isFolderPlayback = true;
6872 m_isRewind = false;
6973 m_isOpenFileAfterStop = false;
7074 ZeroMemory(&m_SequencerLastMsg, sizeof(MTSequencerLastMsg));
@@ -657,7 +661,22 @@ LRESULT MIDITrailApp::_WndProcImpl(
657661 switch (wmId) {
658662 case IDM_OPEN_FILE:
659663 //ファイルオープン
660- result = _OnMenuFileOpen();
664+ result = _OnMenuOpenFile();
665+ if (result != 0) goto EXIT;
666+ break;
667+ case IDM_OPEN_FOLDER:
668+ //フォルダオープン
669+ result = _OnMenuOpenFolder();
670+ if (result != 0) goto EXIT;
671+ break;
672+ case IDM_PREVIOUS_FILE:
673+ //前ファイル
674+ result = _OnMenuPreviousFile();
675+ if (result != 0) goto EXIT;
676+ break;
677+ case IDM_NEXT_FILE:
678+ //次ファイル
679+ result = _OnMenuNextFile();
661680 if (result != 0) goto EXIT;
662681 break;
663682 case IDM_EXIT:
@@ -679,6 +698,11 @@ LRESULT MIDITrailApp::_WndProcImpl(
679698 result = _OnMenuRepeat();
680699 if (result != 0) goto EXIT;
681700 break;
701+ case IDM_FOLDER_PLAYBACK:
702+ //フォルダ演奏
703+ result = _OnMenuFolderPlayback();
704+ if (result != 0) goto EXIT;
705+ break;
682706 case IDM_SKIP_BACK:
683707 //再生スキップバック
684708 result = _OnMenuSkipBack();
@@ -898,10 +922,10 @@ EXIT:;
898922 //******************************************************************************
899923 // ファイルオープン
900924 //******************************************************************************
901-int MIDITrailApp::_OnMenuFileOpen()
925+int MIDITrailApp::_OnMenuOpenFile()
902926 {
903927 int result = 0;
904- TCHAR filePath[MAX_PATH] = {_T('\0')};
928+ TCHAR filePath[_MAX_PATH] = {_T('\0')};
905929 bool isSelected = false;
906930
907931 ////演奏中はファイルオープンさせない
@@ -916,7 +940,7 @@ int MIDITrailApp::_OnMenuFileOpen()
916940 //演奏中でもファイルオープン可とする
917941
918942 //ファイル選択ダイアログ表示
919- result = _SelectMIDIFile(filePath, MAX_PATH, &isSelected);
943+ result = _SelectMIDIFile(filePath, _MAX_PATH, &isSelected);
920944 if (result != 0) goto EXIT;
921945
922946 //ファイル選択時の処理
@@ -927,12 +951,110 @@ int MIDITrailApp::_OnMenuFileOpen()
927951 if (m_isFullScreen) {
928952 _HideMenu();
929953 }
954+
955+ //ファイルリスト破棄
956+ m_MIDIFileList.Clear();
930957
931958 //演奏/モニタ停止とファイルオープン処理
932959 result = _StopPlaybackAndOpenFile(filePath);
933960 if (result != 0) goto EXIT;
934961 }
935962
963+ //メニュースタイル更新
964+ result = _ChangeMenuStyle();
965+ if (result != 0) goto EXIT;
966+
967+EXIT:;
968+ return result;
969+}
970+
971+//******************************************************************************
972+// フォルダオープン
973+//******************************************************************************
974+int MIDITrailApp::_OnMenuOpenFolder()
975+{
976+ int result = 0;
977+ TCHAR folderPath[_MAX_PATH] = { _T('\0') };
978+ bool isSelected = false;
979+
980+ //演奏中でもフォルダオープン可とする
981+
982+ //フォルダ選択ダイアログ表示
983+ result = _SelectFolder(folderPath, _MAX_PATH, &isSelected);
984+ if (result != 0) goto EXIT;
985+
986+ //フォルダ選択時の処理
987+ if (isSelected) {
988+ //フルスクリーンでメニューからファイル選択した場合
989+ // シーン生成処理でクライアントウィンドウのサイズを参照しているため
990+ // 一時的に表示したメニューを非表示に戻しておく
991+ if (m_isFullScreen) {
992+ _HideMenu();
993+ }
994+
995+ //演奏/モニタ停止とフォルダオープン処理
996+ result = _StopPlaybackAndOpenFolder(folderPath);
997+ if (result != 0) goto EXIT;
998+ }
999+
1000+ //メニュースタイル更新
1001+ result = _ChangeMenuStyle();
1002+ if (result != 0) goto EXIT;
1003+
1004+EXIT:;
1005+ return result;
1006+}
1007+
1008+//******************************************************************************
1009+// 前ファイル
1010+//******************************************************************************
1011+int MIDITrailApp::_OnMenuPreviousFile()
1012+{
1013+ int result = 0;
1014+ bool isExist = false;
1015+ const TCHAR* pFilePath = NULL;
1016+
1017+ //ファイルリストがなければ何もしない
1018+ if (m_MIDIFileList.GetFileCount() == 0) goto EXIT;
1019+
1020+ //前ファイルを選択
1021+ m_MIDIFileList.SelectPreviousFile(&isExist);
1022+
1023+ //前ファイルが存在する場合
1024+ if (isExist) {
1025+ //演奏/モニタ停止とファイルオープン処理
1026+ pFilePath = m_MIDIFileList.GetFilePath(m_MIDIFileList.GetSelectedFileIndex());
1027+ result = _StopPlaybackAndOpenFile(pFilePath);
1028+ if (result != 0) goto EXIT;
1029+ }
1030+
1031+EXIT:;
1032+ return result;
1033+}
1034+
1035+//******************************************************************************
1036+// 次ファイル
1037+//******************************************************************************
1038+int MIDITrailApp::_OnMenuNextFile()
1039+{
1040+ int result = 0;
1041+ bool isExist = false;
1042+ const TCHAR* pFilePath = NULL;
1043+
1044+ //ファイルリストがなければ何もしない
1045+ if (m_MIDIFileList.GetFileCount() == 0) goto EXIT;
1046+
1047+ //次ファイルを選択
1048+ m_MIDIFileList.SelectNextFile(&isExist);
1049+
1050+ //次ファイルが存在する場合
1051+ if (isExist) {
1052+ //演奏/モニタ停止とファイルオープン処理
1053+ pFilePath = m_MIDIFileList.GetFilePath(m_MIDIFileList.GetSelectedFileIndex());
1054+ result = _StopPlaybackAndOpenFile(pFilePath);
1055+ if (result != 0) goto EXIT;
1056+ }
1057+
9361058 EXIT:;
9371059 return result;
9381060 }
@@ -1047,6 +1169,29 @@ EXIT:;
10471169 }
10481170
10491171 //******************************************************************************
1172+// メニュー選択:フォルダ演奏
1173+//******************************************************************************
1174+int MIDITrailApp::_OnMenuFolderPlayback()
1175+{
1176+ int result = 0;
1177+
1178+ //フォルダ演奏切り替え
1179+ if (m_isFolderPlayback) {
1180+ m_isFolderPlayback = false;
1181+ }
1182+ else {
1183+ m_isFolderPlayback = true;
1184+ }
1185+
1186+ //メニュー選択マーク更新
1187+ result = _UpdateMenuCheckmark();
1188+ if (result != 0) goto EXIT;
1189+
1190+EXIT:;
1191+ return result;
1192+}
1193+
1194+//******************************************************************************
10501195 // メニュー選択:スキップバック
10511196 //******************************************************************************
10521197 int MIDITrailApp::_OnMenuSkipBack()
@@ -1193,7 +1338,10 @@ int MIDITrailApp::_OnMenuStartMonitoring()
11931338 //演奏状態変更
11941339 result = _ChangePlayStatus(MonitorON);
11951340 if (result != 0) goto EXIT;
1196-
1341+
1342+ //ウィンドウタイトル更新
1343+ _UpdateWindowTitle(NULL);
1344+
11971345 EXIT:;
11981346 return result;
11991347 }
@@ -1570,6 +1718,7 @@ int MIDITrailApp::_OnRecvSequencerMsg(
15701718 {
15711719 int result = 0;
15721720 SMMsgParser parser;
1721+ bool isExist = false;
15731722
15741723 //シーンにシーケンサメッセージを渡す
15751724 if (m_pScene != NULL) {
@@ -1615,13 +1764,44 @@ int MIDITrailApp::_OnRecvSequencerMsg(
16151764 result = _FileOpenProc(m_NextFilePath);
16161765 if (result != 0) goto EXIT;
16171766 }
1618- //通常の演奏終了の場合は次回の演奏時に巻き戻す
1767+ //通常の演奏終了の場合
16191768 else {
1769+ //通常の演奏終了の場合は次回の演奏時に巻き戻す
16201770 m_isRewind = true;
1621- //リピート有効なら再生開始
1622- if (m_isRepeat) {
1623- result = _OnMenuPlay();
1624- if (result != 0) goto EXIT;
1771+ //ファイルリストなしの場合
1772+ if (m_MIDIFileList.GetFileCount() == 0) {
1773+ //リピート有効なら再生開始
1774+ if (m_isRepeat) {
1775+ result = _OnMenuPlay();
1776+ if (result != 0) goto EXIT;
1777+ }
1778+ }
1779+ //ファイルリストありの場合
1780+ else {
1781+ //フォルダ演奏無効かつリピート有効なら再生開始
1782+ if (!m_isFolderPlayback && m_isRepeat) {
1783+ result = _OnMenuPlay();
1784+ if (result != 0) goto EXIT;
1785+ }
1786+ //フォルダ演奏有効なら次ファイルを自動選択
1787+ else if (m_isFolderPlayback) {
1788+ m_MIDIFileList.SelectNextFile(&isExist);
1789+ if (isExist) {
1790+ //次ファイルが存在する場合は開いて演奏開始
1791+ result = _LoadMIDIFile(m_MIDIFileList.GetFilePath(m_MIDIFileList.GetSelectedFileIndex()));
1792+ if (result != 0) goto EXIT;
1793+ result = _OnMenuPlay();
1794+ if (result != 0) goto EXIT;
1795+ }
1796+ else if (m_isRepeat) {
1797+ //次ファイルが存在しないがリピート有効の場合は先頭ファイルを開いて演奏開始
1798+ m_MIDIFileList.SelectFirstFile();
1799+ result = _LoadMIDIFile(m_MIDIFileList.GetFilePath(m_MIDIFileList.GetSelectedFileIndex()));
1800+ if (result != 0) goto EXIT;
1801+ result = _OnMenuPlay();
1802+ if (result != 0) goto EXIT;
1803+ }
1804+ }
16251805 }
16261806 }
16271807
@@ -1809,7 +1989,22 @@ int MIDITrailApp::_OnKeyDown(
18091989 case 'O':
18101990 if (GetKeyState(VK_CONTROL) & 0x8000) {
18111991 //ファイルオープン
1812- result = _OnMenuFileOpen();
1992+ result = _OnMenuOpenFile();
1993+ if (result != 0) goto EXIT;
1994+ }
1995+ break;
1996+ case 'B':
1997+ case 'P':
1998+ if (GetKeyState(VK_CONTROL) & 0x8000) {
1999+ //前ファイル
2000+ result = _OnMenuPreviousFile();
2001+ if (result != 0) goto EXIT;
2002+ }
2003+ break;
2004+ case 'N':
2005+ if (GetKeyState(VK_CONTROL) & 0x8000) {
2006+ //次ファイル
2007+ result = _OnMenuNextFile();
18132008 if (result != 0) goto EXIT;
18142009 }
18152010 break;
@@ -1877,20 +2072,36 @@ int MIDITrailApp::_OnDropFiles(
18772072 goto EXIT;
18782073 }
18792074
1880- //ファイル拡張子の確認
1881- if (YNPathUtil::IsFileExtMatch(path, _T(".mid"))) {
1882- isMIDIDataFile = true;
1883- }
1884- //rcpcv.dllが有効ならサポート対象ファイルであるか追加確認する
1885- else if (m_RcpConv.IsAvailable() && m_RcpConv.IsSupportFileExt(path)) {
1886- isMIDIDataFile = true;
2075+ //フォルダをドロップされた場合
2076+ if (PathIsDirectory(path)) {
2077+ //演奏/モニタ停止とフォルダオープン処理
2078+ result = _StopPlaybackAndOpenFolder(path);
2079+ if (result != 0) goto EXIT;
18872080 }
2081+ //ファイルをドロップされた場合
2082+ else {
2083+ //ファイル拡張子の確認
2084+ if (YNPathUtil::IsFileExtMatch(path, _T(".mid"))) {
2085+ isMIDIDataFile = true;
2086+ }
2087+ //rcpcv.dllが有効ならサポート対象ファイルであるか追加確認する
2088+ else if (m_RcpConv.IsAvailable() && m_RcpConv.IsSupportFileExt(path)) {
2089+ isMIDIDataFile = true;
2090+ }
18882091
1889- //サポート対象ファイルでなければ何もしない
1890- if (!isMIDIDataFile) goto EXIT;
2092+ //サポート対象ファイルでなければ何もしない
2093+ if (!isMIDIDataFile) goto EXIT;
18912094
1892- //演奏/モニタ停止とファイルオープン処理
1893- result = _StopPlaybackAndOpenFile(path);
2095+ //ファイルリスト破棄
2096+ m_MIDIFileList.Clear();
2097+
2098+ //演奏/モニタ停止とファイルオープン処理
2099+ result = _StopPlaybackAndOpenFile(path);
2100+ if (result != 0) goto EXIT;
2101+ }
2102+
2103+ //メニュースタイル更新
2104+ result = _ChangeMenuStyle();
18942105 if (result != 0) goto EXIT;
18952106
18962107 EXIT:;
@@ -1948,6 +2159,121 @@ EXIT:;
19482159 }
19492160
19502161 //******************************************************************************
2162+// フォルダ選択
2163+//******************************************************************************
2164+int MIDITrailApp::_SelectFolder(
2165+ TCHAR* pFolderPath,
2166+ unsigned long bufSize,
2167+ bool* pIsSelected
2168+ )
2169+{
2170+ int result = 0;
2171+ int apiresult = 0;
2172+ errno_t eresult = 0;
2173+ HRESULT hresult = 0;
2174+ DWORD options = 0;
2175+ IFileOpenDialog* pFileOpenDialog = NULL;
2176+ LPWSTR pFolderPathW = NULL;
2177+ IShellItem* pShellItem = NULL;
2178+ BOOL isUsedDefaultChar = FALSE;
2179+
2180+ if ((pFolderPath == NULL) || (bufSize == 0) || (pIsSelected == NULL)) {
2181+ result = YN_SET_ERR("Program error.", 0, 0);
2182+ goto EXIT;
2183+ }
2184+
2185+ *pIsSelected = false;
2186+
2187+ //ダイアログ生成
2188+ hresult = CoCreateInstance(
2189+ CLSID_FileOpenDialog, //CLSID
2190+ NULL, //アグリゲートオブジェクト
2191+ CLSCTX_INPROC_SERVER, //コンテキスト
2192+ IID_PPV_ARGS(&pFileOpenDialog) //IIDと変数アドレス
2193+ );
2194+ if (FAILED(hresult)) {
2195+ result = YN_SET_ERR("Windows API error.", GetLastError(), hresult);
2196+ goto EXIT;
2197+ }
2198+
2199+ //オプション設定
2200+ pFileOpenDialog->GetOptions(&options);
2201+ pFileOpenDialog->SetOptions(options | FOS_PICKFOLDERS);
2202+
2203+ //ダイアログ表示(フォルダ選択のみ可能)
2204+ // m_hWndを指定すると演奏開始後のダイアログ表示でハングする(原因不明)
2205+ hresult = pFileOpenDialog->Show(NULL);
2206+ if (hresult == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
2207+ //キャンセルされた場合は何もせず終了
2208+ goto EXIT;
2209+ }
2210+ if (FAILED(hresult)) {
2211+ result = YN_SET_ERR("Windows API error.", GetLastError(), hresult);
2212+ goto EXIT;
2213+ }
2214+
2215+ //フォルダ選択された場合はパスを取得
2216+ //ワイド文字列でしか取得できないことに注意
2217+ hresult = pFileOpenDialog->GetResult(&pShellItem);
2218+ if (FAILED(hresult)) {
2219+ result = YN_SET_ERR("Windows API error.", GetLastError(), hresult);
2220+ goto EXIT;
2221+ }
2222+ hresult = pShellItem->GetDisplayName(SIGDN_FILESYSPATH, &pFolderPathW);
2223+ if (FAILED(hresult)) {
2224+ result = YN_SET_ERR("Windows API error.", GetLastError(), hresult);
2225+ goto EXIT;
2226+ }
2227+
2228+#ifdef _UNICODE
2229+
2230+ eresult = wcscpy_s(pFolderPath, bufSize, pFolderPathW);
2231+ if (eresult != 0) {
2232+ result = YN_SET_ERR("Program error.", eresult, 0);
2233+ goto EXIT;
2234+ }
2235+
2236+#else
2237+
2238+ //文字コード変換
2239+ apiresult = WideCharToMultiByte(
2240+ _getmbcp(), //コードページ
2241+ WC_NO_BEST_FIT_CHARS, //マップされない文字の処理方法:変換できない文字をデフォルト文字に変換
2242+ pFolderPathW, //変換元ワイド文字列
2243+ -1, //変換元ワイド文字列の文字数: NULL終端
2244+ pFolderPath, //変換後マルチバイト文字列
2245+ bufSize, //変換後マルチバイト文字列バッファサイズ(バイト単位)
2246+ NULL, //変換できない文字の変換後デフォルト文字:未指定時はシステム既定値を使用
2247+ &isUsedDefaultChar //デフォルト文字に変換した文字の有無
2248+ );
2249+ if (apiresult == 0) {
2250+ result = YN_SET_ERR("Windows API error.", GetLastError(), 0);
2251+ goto EXIT;
2252+ }
2253+ if (isUsedDefaultChar) {
2254+ //マルチバイト文字列に変換できない文字が含まれていた場合はエラーとする
2255+ result = YN_SET_ERR("The folder path contains characters that cannot be code-converted.", 0, 0);
2256+ goto EXIT;
2257+ }
2258+
2259+#endif
2260+
2261+ *pIsSelected = true;
2262+
2263+EXIT:;
2264+ if (pFolderPathW != NULL) {
2265+ CoTaskMemFree(pFolderPathW);
2266+ }
2267+ if (pShellItem != NULL) {
2268+ pShellItem->Release();
2269+ }
2270+ if (pFileOpenDialog != NULL) {
2271+ pFileOpenDialog->Release();
2272+ }
2273+ return result;
2274+}
2275+
2276+//******************************************************************************
19512277 // MIDIファイル読み込み
19522278 //******************************************************************************
19532279 int MIDITrailApp::_LoadMIDIFile(
@@ -1960,6 +2286,10 @@ int MIDITrailApp::_LoadMIDIFile(
19602286 TCHAR smfDumpPath[_MAX_PATH] = {_T('\0')};
19612287 SMFileReader smfReader;
19622288
2289+ //ウィンドウタイトル更新
2290+ //ファイル読み込み前に表示してエラー発生時にファイル名を確認可能とする
2291+ _UpdateWindowTitle(PathFindFileName(pFilePath));
2292+
19632293 //拡張子が*.midの場合
19642294 if (YNPathUtil::IsFileExtMatch(pFilePath, _T(".mid"))) {
19652295 pPath = (TCHAR*)pFilePath;
@@ -1985,6 +2315,9 @@ int MIDITrailApp::_LoadMIDIFile(
19852315 result = smfReader.Load(pPath, &m_SeqData);
19862316 if (result != 0) goto EXIT;
19872317
2318+ //ファイル名登録:SMF変換処理実施前のオリジナルのファイル名を設定
2319+ m_SeqData.SetFileName(PathFindFileName(pFilePath));
2320+
19882321 //ファイル読み込み時に再生スピードを100%に戻す:_CreateSceneでカウンタに反映
19892322 m_PlaySpeedRatio = 100;
19902323
@@ -2007,6 +2340,48 @@ EXIT:;
20072340 }
20082341
20092342 //******************************************************************************
2343+// ウィンドウタイトル更新
2344+//******************************************************************************
2345+void MIDITrailApp::_UpdateWindowTitle(const TCHAR* pFileName)
2346+{
2347+ //ファイル名なしの場合
2348+ if (pFileName == NULL) {
2349+ _stprintf_s(
2350+ m_Title,
2351+ MAX_LOADSTRING,
2352+ MIDITRAIL_WINDOW_TITLE
2353+ );
2354+ }
2355+ else {
2356+ //ファイルリストなしの場合
2357+ if (m_MIDIFileList.GetFileCount() == 0) {
2358+ _stprintf_s(
2359+ m_Title,
2360+ MAX_LOADSTRING,
2361+ MIDITRAIL_WINDOW_TITLE_FILE,
2362+ pFileName
2363+ );
2364+ }
2365+ //ファイルリストありの場合
2366+ else {
2367+ _stprintf_s(
2368+ m_Title,
2369+ MAX_LOADSTRING,
2370+ MIDITRAIL_WINDOW_TITLE_FILES,
2371+ m_MIDIFileList.GetSelectedFileIndex() + 1,
2372+ m_MIDIFileList.GetFileCount(),
2373+ pFileName
2374+ );
2375+ }
2376+ }
2377+
2378+ //ウィンドウタイトル設定
2379+ SetWindowText(m_hWnd, m_Title);
2380+
2381+ return;
2382+}
2383+
2384+//******************************************************************************
20102385 // FPS更新
20112386 //******************************************************************************
20122387 void MIDITrailApp::_UpdateFPS()
@@ -2014,7 +2389,7 @@ void MIDITrailApp::_UpdateFPS()
20142389 unsigned long curTime = 0;
20152390 unsigned long diffTime = 0;
20162391 double fps = 0;
2017- TCHAR title[256];
2392+ TCHAR title[MAX_LOADSTRING];
20182393
20192394 curTime = timeGetTime();
20202395 m_FPSCount += 1;
@@ -2029,7 +2404,7 @@ void MIDITrailApp::_UpdateFPS()
20292404 m_FPSCount = 0;
20302405
20312406 //ウィンドウタイトルに設定
2032- _stprintf_s(title, 256, _T("%s - FPS:%.1f"), m_Title, fps);
2407+ _stprintf_s(title, MAX_LOADSTRING, MIDITRAIL_WINDOW_TITLE_FPS, m_Title, fps);
20332408 SetWindowText(m_hWnd, title);
20342409 }
20352410
@@ -2226,10 +2601,14 @@ int MIDITrailApp::_ChangeMenuStyle()
22262601 //TAG:シーン追加
22272602 unsigned long menuID[MT_MENU_NUM] = {
22282603 IDM_OPEN_FILE,
2604+ IDM_OPEN_FOLDER,
2605+ IDM_PREVIOUS_FILE,
2606+ IDM_NEXT_FILE,
22292607 IDM_EXIT,
22302608 IDM_PLAY,
22312609 IDM_STOP,
22322610 IDM_REPEAT,
2611+ IDM_FOLDER_PLAYBACK,
22332612 IDM_SKIP_BACK,
22342613 IDM_SKIP_FORWARD,
22352614 IDM_PLAY_SPEED_DOWN,
@@ -2262,12 +2641,16 @@ int MIDITrailApp::_ChangeMenuStyle()
22622641
22632642 //メニュースタイル一覧
22642643 unsigned long menuStyle[MT_MENU_NUM][MT_PLAYSTATUS_NUM] = {
2265- //データ無, 停止, 再生中, 一時停止, モニタ停止, モニタ中
2644+ //データ無, 停止, 再生中, 一時停止, モニタ停止, モニタ中
22662645 { MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED }, //IDM_OPEN_FILE
2646+ { MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED }, //IDM_OPEN_FOLDER
2647+ { MF_GRAYED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_GRAYED, MF_GRAYED }, //IDM_PREVIOUS_FILE
2648+ { MF_GRAYED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_GRAYED, MF_GRAYED }, //IDM_NEXT_FILE
22672649 { MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED }, //IDM_EXIT
22682650 { MF_GRAYED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_GRAYED, MF_GRAYED }, //IDM_PLAY
22692651 { MF_GRAYED, MF_GRAYED, MF_ENABLED, MF_ENABLED, MF_GRAYED, MF_GRAYED }, //IDM_STOP
22702652 { MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_GRAYED, MF_GRAYED }, //IDM_REPEAT
2653+ { MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_GRAYED, MF_GRAYED }, //IDM_FOLDER_PLAYBACK
22712654 { MF_GRAYED, MF_GRAYED, MF_ENABLED, MF_GRAYED, MF_GRAYED, MF_GRAYED }, //IDM_SKIP_BACK
22722655 { MF_GRAYED, MF_GRAYED, MF_ENABLED, MF_GRAYED, MF_GRAYED, MF_GRAYED }, //IDM_SKIP_FORWARD
22732656 { MF_GRAYED, MF_ENABLED, MF_ENABLED, MF_ENABLED, MF_GRAYED, MF_GRAYED }, //IDM_PLAY_SPEED_DOWN
@@ -2313,6 +2696,13 @@ int MIDITrailApp::_ChangeMenuStyle()
23132696 EnableMenuItem(GetMenu(m_hWnd), menuID[menuIndex], style);
23142697 }
23152698
2699+ //ファイルリストが存在しない場合"Previous File","Next File"は選択不可
2700+ if (m_MIDIFileList.GetFileCount() == 0) {
2701+ EnableMenuItem(GetMenu(m_hWnd), IDM_PREVIOUS_FILE, MF_GRAYED);
2702+ EnableMenuItem(GetMenu(m_hWnd), IDM_NEXT_FILE, MF_GRAYED);
2703+ EnableMenuItem(GetMenu(m_hWnd), IDM_FOLDER_PLAYBACK, MF_GRAYED);
2704+ }
2705+
23162706 return result;
23172707 }
23182708
@@ -2876,6 +3266,9 @@ int MIDITrailApp::_UpdateMenuCheckmark()
28763266
28773267 //リピート
28783268 _CheckMenuItem(IDM_REPEAT, m_isRepeat);
3269+
3270+ //フォルダ演奏
3271+ _CheckMenuItem(IDM_FOLDER_PLAYBACK, m_isFolderPlayback);
28793272
28803273 //シーン種別選択
28813274 //TAG:シーン追加
@@ -2981,6 +3374,8 @@ int MIDITrailApp::_ParseCmdLine(
29813374 )
29823375 {
29833376 int result = 0;
3377+ DWORD dwResult = 0;
3378+ TCHAR filePath[_MAX_PATH];
29843379
29853380 //コマンドライン解析
29863381 result = m_CmdLineParser.Initialize(pCmdLine);
@@ -2988,9 +3383,20 @@ int MIDITrailApp::_ParseCmdLine(
29883383
29893384 //コマンドラインでファイルを指定されている場合
29903385 if (m_CmdLineParser.GetSwitch(CMDSW_FILE_PATH) == CMDSW_ON) {
3386+ //フルパスに変換
3387+ dwResult = GetFullPathName(
3388+ m_CmdLineParser.GetFilePath(), //変換元ファイル名(相対パス指定可能)
3389+ _MAX_PATH, //フルパス格納先バッファサイズ
3390+ filePath, //フルパス格納先バッファ
3391+ NULL //ファイル名へのポインタ
3392+ );
3393+ if (dwResult == 0) {
3394+ result = YN_SET_ERR("Windows API error.", GetLastError(), 0);
3395+ goto EXIT;
3396+ }
29913397
29923398 //ファイルを開く
2993- result = _LoadMIDIFile(m_CmdLineParser.GetFilePath());
3399+ result = _LoadMIDIFile(filePath);
29943400 if (result != 0) goto EXIT;
29953401
29963402 //再生指定されている場合は再生開始
@@ -3451,7 +3857,7 @@ EXIT:;
34513857 // 演奏/モニタ停止とMIDIファイルオープン処理
34523858 //******************************************************************************
34533859 int MIDITrailApp::_StopPlaybackAndOpenFile(
3454- TCHAR* pFilePath
3860+ const TCHAR* pFilePath
34553861 )
34563862 {
34573863 int result = 0;
@@ -3499,10 +3905,59 @@ EXIT:;
34993905 }
35003906
35013907 //******************************************************************************
3908+// 演奏/モニタ停止とフォルダオープン処理
3909+//******************************************************************************
3910+int MIDITrailApp::_StopPlaybackAndOpenFolder(
3911+ const TCHAR* pFolderPath
3912+ )
3913+{
3914+ int result = 0;
3915+ int apiresult = 0;
3916+ TCHAR fileDirPath[_MAX_PATH] = { _T('\0') };
3917+ TCHAR* pName = NULL;
3918+ MTFileList midiFileList;
3919+ const TCHAR* pFilePath = NULL;
3920+
3921+ //指定ファイルと同じディレクトリに存在するMIDIデータファイルのリストを作成
3922+ //事前確認のためテンポラリのリストオブジェクトを指定
3923+ result = _MakeFileListWithFolder(pFolderPath, &midiFileList);
3924+ if (result != 0) goto EXIT;
3925+
3926+ //MIDIデータファイルが存在しない場合はメッセージを表示して終了
3927+ if (midiFileList.GetFileCount() == 0) {
3928+ //メッセージボックス表示
3929+ apiresult = MessageBox(
3930+ m_hWnd, //オーナーウィンドウ
3931+ MIDITRAIL_MSG_FILE_NOT_FOUND, //メッセージ
3932+ _T("WARNING"), //タイトル
3933+ MB_OK | MB_ICONWARNING //フラグ
3934+ );
3935+ if (apiresult == 0) {
3936+ result = YN_SET_ERR("Windows API error.", GetLastError(), 0);
3937+ goto EXIT;
3938+ }
3939+ goto EXIT;
3940+ }
3941+
3942+ //指定ファイルと同じディレクトリに存在するMIDIデータファイルのリストを作成
3943+ result = _MakeFileListWithFolder(pFolderPath, &m_MIDIFileList);
3944+ if (result != 0) goto EXIT;
3945+
3946+ //ファイルリストの先頭ファイルを選択して開く
3947+ m_MIDIFileList.SelectFirstFile();
3948+ pFilePath = m_MIDIFileList.GetFilePath(m_MIDIFileList.GetSelectedFileIndex());
3949+ result = _StopPlaybackAndOpenFile(pFilePath);
3950+ if (result != 0) goto EXIT;
3951+
3952+EXIT:;
3953+ return result;
3954+}
3955+
3956+//******************************************************************************
35023957 // MIDIファイルオープン処理
35033958 //******************************************************************************
35043959 int MIDITrailApp::_FileOpenProc(
3505- TCHAR* pFilePath
3960+ const TCHAR* pFilePath
35063961 )
35073962 {
35083963 int result = 0;
@@ -3696,3 +4151,27 @@ int MIDITrailApp::_ChangeViewPoint(int step)
36964151 EXIT:;
36974152 return result;
36984153 }
4154+
4155+//******************************************************************************
4156+// フォルダ内ファイルリスト作成
4157+//******************************************************************************
4158+int MIDITrailApp::_MakeFileListWithFolder(
4159+ const TCHAR* pFolderPath,
4160+ MTFileList* pFileList
4161+ )
4162+{
4163+ int result = 0;
4164+
4165+ if ((pFolderPath == NULL) || (pFileList == NULL)) {
4166+ result = YN_SET_ERR("Program Error.", 0, 0);
4167+ goto EXIT;
4168+ }
4169+
4170+ //指定フォルダ直下に存在するMIDIデータファイルのリストを作成
4171+ result = pFileList->MakeFileListWithDirectory(pFolderPath, &m_RcpConv);
4172+ if (result != 0) goto EXIT;
4173+
4174+EXIT:;
4175+ return result;
4176+}
4177+
--- a/MIDITrail/MIDITrailApp.h
+++ b/MIDITrail/MIDITrailApp.h
@@ -4,7 +4,7 @@
44 //
55 // MIDITrail アプリケーションクラス
66 //
7-// Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -24,6 +24,7 @@
2424 #include "MTAboutDlg.h"
2525 #include "MTCmdLineParser.h"
2626 #include "MTGamePadCtrl.h"
27+#include "MTFileList.h"
2728
2829 using namespace YNBaseLib;
2930 using namespace SMIDILib;
@@ -32,7 +33,7 @@ using namespace SMIDILib;
3233 //******************************************************************************
3334 // パラメータ定義
3435 //******************************************************************************
35-#define MAX_LOADSTRING (100)
36+#define MAX_LOADSTRING (256)
3637
3738 //ウィンドウスタイル
3839 // WS_OVERLAPPEDWINDOW から次のスタイルを削ったもの
@@ -44,12 +45,15 @@ using namespace SMIDILib;
4445
4546 //メニュースタイル制御
4647 //TAG:シーン追加
47-#define MT_MENU_NUM (33)
48+#define MT_MENU_NUM (37)
4849 #define MT_PLAYSTATUS_NUM (6)
4950
5051 //デバイスロスト警告メッセージ
5152 #define MIDITRAIL_MSG_DEVICELOST _T("Direct3D device is lost.")
5253
54+//ファイルなし警告メッセージ
55+#define MIDITRAIL_MSG_FILE_NOT_FOUND _T("MIDI file (*.mid) not found.")
56+
5357 //タイマーID
5458 #define MIDITRAIL_TIMER_CHECK_KEY (1)
5559
@@ -59,6 +63,12 @@ using namespace SMIDILib;
5963 //メールスロット名称
6064 #define MIDITRAIL_MAILSLOT _T("\\\\.\\mailslot\\yknk\\MIDITrail")
6165
66+//ウィンドウタイトル ex.: "MIDITrail - file_name.mid - FPS:60.0"
67+#define MIDITRAIL_WINDOW_TITLE _T("MIDITrail")
68+#define MIDITRAIL_WINDOW_TITLE_FILE _T("MIDITrail - %s")
69+#define MIDITRAIL_WINDOW_TITLE_FILES _T("MIDITrail - [%d/%d] %s")
70+#define MIDITRAIL_WINDOW_TITLE_FPS _T("%s - FPS:%.1f")
71+
6272
6373 //******************************************************************************
6474 // MIDITrail アプリケーションクラス
@@ -170,6 +180,7 @@ private:
170180 //演奏状態
171181 PlayStatus m_PlayStatus;
172182 bool m_isRepeat;
183+ bool m_isFolderPlayback;
173184 bool m_isRewind;
174185 bool m_isOpenFileAfterStop;
175186 MTSequencerLastMsg m_SequencerLastMsg;
@@ -235,6 +246,9 @@ private:
235246 //ゲームパッド用視点番号
236247 int m_GamePadViewPointNo;
237248
249+ //MIDIデータファイルリスト
250+ MTFileList m_MIDIFileList;
251+
238252 //----------------------------------------------------------------
239253 //メソッド定義
240254 //----------------------------------------------------------------
@@ -252,10 +266,14 @@ private:
252266 LRESULT _WndProcImpl(const HWND hWnd, const UINT message, const WPARAM wParam, const LPARAM lParam);
253267
254268 //メニューイベント処理
255- int _OnMenuFileOpen();
269+ int _OnMenuOpenFile();
270+ int _OnMenuOpenFolder();
271+ int _OnMenuPreviousFile();
272+ int _OnMenuNextFile();
256273 int _OnMenuPlay();
257274 int _OnMenuStop();
258275 int _OnMenuRepeat();
276+ int _OnMenuFolderPlayback();
259277 int _OnMenuSkipBack();
260278 int _OnMenuSkipForward();
261279 int _OnMenuPlaySpeedDown();
@@ -285,7 +303,9 @@ private:
285303 int _OnDropFiles(WPARAM wParam, LPARAM lParam);
286304
287305 int _SelectMIDIFile(TCHAR* pFilePath, unsigned long bufSize, bool* pIsSelected);
306+ int _SelectFolder(TCHAR* pFolderPath, unsigned long bufSize, bool* pIsSelected);
288307 int _LoadMIDIFile(const TCHAR* pFilePath);
308+ void _UpdateWindowTitle(const TCHAR* pFileName);
289309 void _UpdateFPS();
290310 int _SetPortDev(SMSequencer* pSequencer);
291311 int _SetMonitorPortDev(SMLiveMonitor* pLiveMonitor, MTScene* pScene);
@@ -317,13 +337,15 @@ private:
317337 int _CheckMultipleInstances(bool* pIsExitApp);
318338 int _CreateMailSlot();
319339 int _PostFilePathToFirstMIDITrail(LPTSTR pCmdLine);
320- int _StopPlaybackAndOpenFile(TCHAR* pFilePath);
321- int _FileOpenProc(TCHAR* pFilePath);
340+ int _StopPlaybackAndOpenFile(const TCHAR* pFilePath);
341+ int _StopPlaybackAndOpenFolder(const TCHAR* pFolderPath);
342+ int _FileOpenProc(const TCHAR* pFilePath);
322343 int _ToggleFullScreen();
323344 int _ShowMenu();
324345 int _HideMenu();
325346 int _GamePadProc();
326347 int _ChangeViewPoint(int step);
348+ int _MakeFileListWithFolder(const TCHAR* pFolderPath, MTFileList* pFileList);
327349
328350 };
329351
--- a/MIDITrail/MIDITrailVersion.h
+++ b/MIDITrail/MIDITrailVersion.h
@@ -4,7 +4,7 @@
44 //
55 // MIDITrail バージョン定義
66 //
7-// Copyright (C) 2014-2019 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2014-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -16,10 +16,10 @@
1616 //******************************************************************************
1717
1818 //バージョン文字列
19-#define MIDITRAIL_VERSION_STRING_X86 _T("Version 1.3.1 (32bit)")
20-#define MIDITRAIL_VERSION_STRING_X64 _T("Version 1.3.1 (64bit)")
19+#define MIDITRAIL_VERSION_STRING_X86 _T("Version 1.3.3 (32bit)")
20+#define MIDITRAIL_VERSION_STRING_X64 _T("Version 1.3.3 (64bit)")
2121
2222 //コピーライト
23-#define MIDITRAIL_COPYRIGHT _T("Copyright (C) 2010-2019 WADA Masashi");
23+#define MIDITRAIL_COPYRIGHT _T("Copyright (C) 2010-2021 WADA Masashi");
2424
2525
--- /dev/null
+++ b/MIDITrail/MTFileList.cpp
@@ -0,0 +1,272 @@
1+//******************************************************************************
2+//
3+// MIDITrail / MTFileList
4+//
5+// ファイルリストクラス
6+//
7+// Copyright (C) 2021 WADA Masashi. All Rights Reserved.
8+//
9+//******************************************************************************
10+
11+#include "StdAfx.h"
12+#include "YNBaseLib.h"
13+#include "MTFileList.h"
14+#include "shlwapi.h"
15+
16+using namespace YNBaseLib;
17+
18+
19+//******************************************************************************
20+// コンストラクタ
21+//******************************************************************************
22+MTFileList::MTFileList(void)
23+{
24+ m_TargetDirPath[0] = _T('\0');
25+ m_CurFilePath[0] = _T('\0');
26+ m_SelectedFileIndex = 0;
27+}
28+
29+//******************************************************************************
30+// デストラクタ
31+//******************************************************************************
32+MTFileList::~MTFileList(void)
33+{
34+ Clear();
35+}
36+
37+//******************************************************************************
38+// クリア
39+//******************************************************************************
40+void MTFileList::Clear()
41+{
42+ m_TargetDirPath[0] = _T('\0');
43+ m_CurFilePath[0] = _T('\0');
44+ m_FileNameList.clear();
45+ m_SelectedFileIndex = 0;
46+}
47+
48+//******************************************************************************
49+// ディレクトリ配下ファイルリスト作成
50+//******************************************************************************
51+int MTFileList::MakeFileListWithDirectory(
52+ const TCHAR* pTargetDirPath,
53+ SMRcpConv* pRcpConv
54+ )
55+{
56+ int result = 0;
57+ TCHAR findPath[_MAX_PATH] = {_T('\0')};;
58+ WIN32_FIND_DATA findData;
59+ HANDLE hFind = NULL;
60+ BOOL isFind = true;
61+ bool isMIDIDataFile = false;
62+
63+ if (pTargetDirPath == NULL) {
64+ result = YN_SET_ERR("Program error.", 0, 0);
65+ goto EXIT;
66+ }
67+
68+ if (_tcslen(pTargetDirPath) > (_MAX_PATH - 1)) {
69+ result = YN_SET_ERR("Directory path is too long.", _tcslen(pTargetDirPath), 0);
70+ goto EXIT;
71+ }
72+
73+ Clear();
74+
75+ //ディレクトリパスを保持する
76+ _tcscpy_s(m_TargetDirPath, _MAX_PATH, pTargetDirPath);
77+ if (pTargetDirPath[_tcslen(pTargetDirPath) - 1] != _T('\\')) {
78+ _tcscat_s(m_TargetDirPath, _MAX_PATH, _T("\\"));
79+ }
80+
81+ //ファイル検索用パス作成
82+ findPath[0] = _T('\0');
83+ _tcscat_s(findPath, _MAX_PATH, m_TargetDirPath);
84+ _tcscat_s(findPath, _MAX_PATH, _T("*.*"));
85+
86+ //ファイル検索
87+ hFind = FindFirstFile(findPath, &findData);
88+ if (hFind == INVALID_HANDLE_VALUE) {
89+ //ファイルが見つからない
90+ goto EXIT;
91+ }
92+
93+ //ファイル名リストを作成
94+ while (isFind) {
95+ if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
96+ //ディレクトリは無視する
97+ }
98+ else {
99+ //ファイル拡張子を確認
100+ isMIDIDataFile = false;
101+ if (YNPathUtil::IsFileExtMatch(findData.cFileName, _T(".mid"))) {
102+ isMIDIDataFile = true;
103+ }
104+ else if (pRcpConv->IsAvailable() && pRcpConv->IsSupportFileExt(findData.cFileName)) {
105+ isMIDIDataFile = true;
106+ }
107+ if (isMIDIDataFile) {
108+ //ファイル名をリストに追加
109+ m_FileNameList.push_back(findData.cFileName);
110+ }
111+ }
112+ //次のファイルを検索
113+ isFind = FindNextFile(hFind, &findData);
114+ }
115+
116+ //ファイル名ソート
117+ m_FileNameList.sort();
118+
119+EXIT:;
120+ if (hFind != NULL) FindClose(hFind);
121+ return result;
122+}
123+
124+//******************************************************************************
125+// ファイル数取得
126+//******************************************************************************
127+size_t MTFileList::GetFileCount()
128+{
129+ return m_FileNameList.size();
130+}
131+
132+//******************************************************************************
133+// ファイルパス取得
134+//******************************************************************************
135+const TCHAR* MTFileList::GetFilePath(unsigned long index)
136+{
137+ TCHAR* pFilePath = NULL;
138+ MTFileNameList::iterator itr;
139+
140+ if (m_FileNameList.size() <= index) {
141+ pFilePath = NULL;
142+ }
143+ else {
144+ itr = m_FileNameList.begin();
145+ advance(itr, index);
146+ m_CurFilePath[0] = _T('\0');
147+ _tcscat_s(m_CurFilePath, _MAX_PATH, m_TargetDirPath);
148+ _tcscat_s(m_CurFilePath, _MAX_PATH, (*itr).c_str());
149+ pFilePath = &(m_CurFilePath[0]);
150+ }
151+
152+ return pFilePath;
153+}
154+
155+//******************************************************************************
156+// ファイル名取得
157+//******************************************************************************
158+const TCHAR* MTFileList::GetFileName(unsigned long index)
159+{
160+ const TCHAR* pFilePath = NULL;
161+ const TCHAR* pFileName = NULL;
162+
163+ pFilePath = GetFilePath(index);
164+ if (pFilePath != NULL) {
165+ pFileName = PathFindFileName(pFilePath);
166+ }
167+
168+ return pFileName;
169+}
170+
171+//******************************************************************************
172+// 選択ファイル登録
173+//******************************************************************************
174+int MTFileList::SetSelectedFileName(const TCHAR* pFileName)
175+{
176+ int result = 0;
177+ unsigned long index = 0;
178+ MTFileNameList::iterator itr;
179+
180+ if (pFileName == NULL) {
181+ result = YN_SET_ERR("Program error.", 0, 0);
182+ goto EXIT;
183+ }
184+
185+ m_SelectedFileIndex = 0;
186+
187+ //ファイル名リストから検索(大文字小文字を区別しない)
188+ for (itr = m_FileNameList.begin(); itr != m_FileNameList.end(); itr++) {
189+ if (_tcsicmp((*itr).c_str(), pFileName) == 0) {
190+ m_SelectedFileIndex = index;
191+ break;
192+ }
193+ index++;
194+ }
195+
196+EXIT:;
197+ return result;
198+}
199+
200+//******************************************************************************
201+// 先頭ファイル選択
202+//******************************************************************************
203+void MTFileList::SelectFirstFile()
204+{
205+ m_SelectedFileIndex = 0;
206+}
207+
208+//******************************************************************************
209+// 前ファイル選択
210+//******************************************************************************
211+void MTFileList::SelectPreviousFile(bool* pIsExist)
212+{
213+ bool isExist = false;
214+
215+ //ファイルが存在しない場合
216+ if (m_FileNameList.size() == 0) {
217+ //前ファイルなしで終了
218+ }
219+ //ファイルリスト先頭を選択中の場合
220+ else if (m_SelectedFileIndex == 0) {
221+ //前ファイルなしで終了
222+ }
223+ else {
224+ //前ファイルを選択
225+ m_SelectedFileIndex -= 1;
226+ isExist = true;
227+ }
228+
229+ if (pIsExist != NULL) {
230+ *pIsExist = isExist;
231+ }
232+
233+ return;
234+}
235+
236+//******************************************************************************
237+// 次ファイル選択
238+//******************************************************************************
239+void MTFileList::SelectNextFile(bool* pIsExist)
240+{
241+ bool isExist = false;
242+
243+ //ファイルが存在しない場合
244+ if (m_FileNameList.size() == 0) {
245+ //次ファイルなしで終了
246+ }
247+ //ファイルリスト末尾を選択中の場合
248+ else if (m_SelectedFileIndex >= (m_FileNameList.size() - 1)) {
249+ //次ファイルなしで終了
250+ }
251+ else {
252+ //次ファイルを選択
253+ m_SelectedFileIndex += 1;
254+ isExist = true;
255+ }
256+
257+ if (pIsExist != NULL) {
258+ *pIsExist = isExist;
259+ }
260+
261+ return;
262+}
263+
264+//******************************************************************************
265+// 先頭ファイル選択
266+//******************************************************************************
267+unsigned long MTFileList::GetSelectedFileIndex()
268+{
269+ return m_SelectedFileIndex;
270+}
271+
272+
--- /dev/null
+++ b/MIDITrail/MTFileList.h
@@ -0,0 +1,83 @@
1+//******************************************************************************
2+//
3+// MIDITrail / MTFileList
4+//
5+// ファイルリストクラス
6+//
7+// Copyright (C) 2021 WADA Masashi. All Rights Reserved.
8+//
9+//******************************************************************************
10+
11+#pragma once
12+
13+#include "SMRcpConv.h"
14+#include <list>
15+#include <string>
16+
17+using namespace YNBaseLib;
18+using namespace SMIDILib;
19+
20+
21+//******************************************************************************
22+// ファイルリストクラス
23+//******************************************************************************
24+class MTFileList
25+{
26+public:
27+
28+ //コンストラクタ/デストラクタ
29+ MTFileList(void);
30+ virtual ~MTFileList(void);
31+
32+ //ディレクトリ配下ファイルリスト作成
33+ int MakeFileListWithDirectory(const TCHAR* pTargetDirPath, SMRcpConv* pRcpConv);
34+
35+ //ファイル数
36+ size_t GetFileCount();
37+
38+ //ファイルパス取得
39+ const TCHAR* GetFilePath(unsigned long index);
40+
41+ //ファイル名取得
42+ const TCHAR* GetFileName(unsigned long index);
43+
44+ //クリア
45+ void Clear();
46+
47+ //選択ファイル登録
48+ int SetSelectedFileName(const TCHAR* pFileName);
49+
50+ //先頭ファイル選択
51+ void SelectFirstFile();
52+
53+ //前ファイル選択
54+ void SelectPreviousFile(bool* pExist);
55+
56+ //次ファイル選択
57+ void SelectNextFile(bool* pExist);
58+
59+ //選択ファイルインデックス取得
60+ unsigned long GetSelectedFileIndex();
61+
62+private:
63+
64+ //代入とコピーコンストラクタの禁止
65+ void operator=(const MTFileList&);
66+ MTFileList(const MTFileList&);
67+
68+ TCHAR m_TargetDirPath[_MAX_PATH];
69+ TCHAR m_CurFilePath[_MAX_PATH];
70+
71+#ifdef _UNICODE
72+ typedef std::list<wsting> MTFileNameList;
73+#else
74+ typedef std::list<string> MTFileNameList;
75+#endif
76+
77+ MTFileNameList m_FileNameList;
78+
79+ unsigned long m_SelectedFileIndex;
80+
81+
82+};
83+
--- a/MIDITrail/MTNoteRipple.cpp
+++ b/MIDITrail/MTNoteRipple.cpp
@@ -4,7 +4,7 @@
44 //
55 // ノート波紋描画クラス
66 //
7-// Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -486,9 +486,9 @@ int MTNoteRipple::_SetVertexPosition(
486486 pVertex[5].p = D3DXVECTOR3(center.x, center.y-(rh/2.0f), center.z-(rw/2.0f));
487487
488488 //法線
489- for (i = 0; i < 6; i++) {
490- pVertex[i].n = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
491- }
489+ //for (i = 0; i < 6; i++) {
490+ // pVertex[i].n = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
491+ //}
492492
493493 //透明度を徐々に落とす
494494 alpha = m_pNoteDesign->GetRippleAlpha(elapsedTime);
--- a/MIDITrail/MTNoteRipple.h
+++ b/MIDITrail/MTNoteRipple.h
@@ -4,7 +4,7 @@
44 //
55 // ノート波紋描画クラス
66 //
7-// Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -102,13 +102,12 @@ private:
102102 //頂点バッファ構造体
103103 struct MTNOTERIPPLE_VERTEX {
104104 D3DXVECTOR3 p; //頂点座標
105- D3DXVECTOR3 n; //法線
106105 DWORD c; //ディフューズ色
107106 D3DXVECTOR2 t; //テクスチャ画像位置
108107 };
109108
110109 //頂点バッファFVFフォーマット
111- DWORD _GetFVFFormat(){ return (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1); }
110+ DWORD _GetFVFFormat(){ return (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); }
112111
113112 protected:
114113
--- a/MIDITrail/MTScenePianoRoll3D.cpp
+++ b/MIDITrail/MTScenePianoRoll3D.cpp
@@ -4,7 +4,7 @@
44 //
55 // ピアノロール3Dシーン描画クラス
66 //
7-// Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -278,6 +278,11 @@ int MTScenePianoRoll3D::Draw(
278278 result = m_TimeIndicator.Draw(pD3DDevice);
279279 if (result != 0) goto EXIT;
280280
281+ //ライトを一時的に無効にする
282+ // ノート波紋とダッシュボードの描画色はライトの方向に依存させないため
283+ result = m_DirLight.SetDevice(pD3DDevice, FALSE);
284+ if (result != 0) goto EXIT;
285+
281286 //ノート波紋描画
282287 result = m_NoteRipple.Draw(pD3DDevice);
283288 if (result != 0) goto EXIT;
@@ -286,6 +291,10 @@ int MTScenePianoRoll3D::Draw(
286291 result = m_Dashboard.Draw(pD3DDevice);
287292 if (result != 0) goto EXIT;
288293
294+ //ライトを戻す
295+ result = m_DirLight.SetDevice(pD3DDevice, m_IsEnableLight);
296+ if (result != 0) goto EXIT;
297+
289298 EXIT:;
290299 return result;
291300 }
--- a/MIDITrail/MTScenePianoRoll3DLive.cpp
+++ b/MIDITrail/MTScenePianoRoll3DLive.cpp
@@ -4,7 +4,7 @@
44 //
55 // ライブモニタ用ピアノロール3Dシーン描画クラス
66 //
7-// Copyright (C) 2012-2019 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2012-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -276,6 +276,11 @@ int MTScenePianoRoll3DLive::Draw(
276276 //タイムインジケータ描画
277277 result = m_TimeIndicator.Draw(pD3DDevice);
278278 if (result != 0) goto EXIT;
279+
280+ //ライトを一時的に無効にする
281+ // ノート波紋とダッシュボードの描画色はライトの方向に依存させないため
282+ result = m_DirLight.SetDevice(pD3DDevice, FALSE);
283+ if (result != 0) goto EXIT;
279284
280285 //ノート波紋描画
281286 result = m_NoteRipple.Draw(pD3DDevice);
@@ -285,6 +290,10 @@ int MTScenePianoRoll3DLive::Draw(
285290 result = m_DashboardLive.Draw(pD3DDevice);
286291 if (result != 0) goto EXIT;
287292
293+ //ライトを戻す
294+ result = m_DirLight.SetDevice(pD3DDevice, m_IsEnableLight);
295+ if (result != 0) goto EXIT;
296+
288297 EXIT:;
289298 return result;
290299 }
--- a/MIDITrail/resource.h
+++ b/MIDITrail/resource.h
@@ -71,7 +71,11 @@
7171 #define IDM_VIEWPOINT2 32843
7272 #define IDM_VIEWPOINT3 32844
7373 #define IDM_FULLSCREEN 32849
74-#define IDM_VIEW_PIANOROLLRING 32850
74+#define IDM_VIEW_PIANOROLLRING 32850
75+#define IDM_FOLDER_PLAYBACK 32852
76+#define IDM_OPEN_FOLDER 32855
77+#define IDM_PREVIOUS_FILE 32858
78+#define IDM_NEXT_FILE 32860
7579 #define IDC_STATIC -1
7680
7781 // Next default values for new objects
@@ -80,7 +84,7 @@
8084 #ifndef APSTUDIO_READONLY_SYMBOLS
8185 #define _APS_NO_MFC 1
8286 #define _APS_NEXT_RESOURCE_VALUE 134
83-#define _APS_NEXT_COMMAND_VALUE 32851
87+#define _APS_NEXT_COMMAND_VALUE 32861
8488 #define _APS_NEXT_CONTROL_VALUE 1025
8589 #define _APS_NEXT_SYMED_VALUE 110
8690 #endif
--- a/README.en.txt
+++ b/README.en.txt
@@ -1,8 +1,8 @@
11 ******************************************************************************
22
3- MIDITrail source code Ver.1.3.1 for Windows
3+ MIDITrail source code Ver.1.3.3 for Windows
44
5- Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
5+ Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
66
77 Web : https://osdn.jp/projects/miditrail/
88 Mail: yknk@users.osdn.me
--- a/README.ja.txt
+++ b/README.ja.txt
@@ -1,8 +1,8 @@
11 ******************************************************************************
22
3- MIDITrail ソースコード Ver.1.3.1 for Windows
3+ MIDITrail ソースコード Ver.1.3.3 for Windows
44
5- Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
5+ Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
66
77 Web : https://osdn.jp/projects/miditrail/
88 Mail: yknk@users.osdn.me
--- a/Resources/LICENSE.txt
+++ b/Resources/LICENSE.txt
@@ -1,5 +1,5 @@
11
2-Copyright (c) 2010-2019, WADA Masashi <yknk@users.sourceforge.jp>
2+Copyright (c) 2010-2021, WADA Masashi <yknk@users.osdn.me>
33 All rights reserved.
44
55 Redistribution and use in source and binary forms, with or without
--- a/Resources/README.en.txt
+++ b/Resources/README.en.txt
@@ -2,7 +2,7 @@
22
33 MIDITrail for Windows
44
5- Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
5+ Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
66
77 Web : https://osdn.jp/projects/miditrail/
88 Mail: yknk@users.osdn.me
--- a/Resources/README.ja.txt
+++ b/Resources/README.ja.txt
@@ -2,7 +2,7 @@
22
33 MIDITrail for Windows
44
5- Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
5+ Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
66
77 Web : https://osdn.jp/projects/miditrail/
88 Mail: yknk@users.osdn.me
--- a/Resources/doc/MANUAL.en.html
+++ b/Resources/doc/MANUAL.en.html
@@ -4,7 +4,7 @@
44 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
55 <meta http-equiv="Content-Language" content="en">
66 <link rel="stylesheet" href="Files/doc.css" type="text/css">
7-<title>MIDITrail Ver.1.3.1 for Windows User Manual</title>
7+<title>MIDITrail Ver.1.3.3 for Windows User Manual</title>
88 </head>
99 <body>
1010
@@ -15,10 +15,10 @@
1515 English / <a href="MANUAL.ja.html">Japanese</a>
1616 </div>
1717
18-<h1>MIDITrail Ver.1.3.1 for Windows User Manual</h1>
18+<h1>MIDITrail Ver.1.3.3 for Windows User Manual</h1>
1919
2020 <p>
21-Copyright (c) 2010-2019, WADA Masashi All rights reserved.<br>
21+Copyright (c) 2010-2021, WADA Masashi All rights reserved.<br>
2222 Web: <a href="https://osdn.jp/projects/miditrail/">https://osdn.jp/projects/miditrail/</a><br>
2323 Mail: <img src="Files/mail.png" align="top"><br>
2424 </p>
@@ -130,7 +130,7 @@ RCPCV.DLL <a href="http://www.vector.co.jp/soft/win95/art/se114143.html">http://
130130
131131 <h3>(1) How to open a MIDI file</h3>
132132 <p>
133-Select "Open..." from "File" menu, the Open File dialog will appear. And choose a Standard MIDI File (*.mid).<br>
133+Select "Open File..." from "File" menu, the Open File dialog will appear. And choose a Standard MIDI File (*.mid).<br>
134134 Or you can drag and drop a MIDI file into the window of MIDITrail.
135135 </p>
136136 <p>
@@ -158,7 +158,45 @@ Push the following keys, or use "Playback" menu.
158158 </table>
159159 </p>
160160
161-<h3>(3) How to move viewpoint in 3D space</h3>
161+<h3>(3) Folder Playback</h3>
162+
163+<p>
164+MIDITrail can open MIDI data files stored in folder in sequence.
165+MIDITrail opens the files in ascending order by filename.
166+</p>
167+
168+<h4>1. Folder selection</h4>
169+<p>
170+When you select "Open Folder..." from "File" menu, the folder selection dialog will appear.<br>
171+Here you have to select the folder that contains the Standard MIDI File (*.mid).<br>
172+You can also drag and drop the forlder into the window of MIDITrail.
173+</p>
174+
175+<h4>2. File switching</h4>
176+<p>
177+You can switch the MIDI data file by selecting "Previous File" and "Next File" from "File" menu.<br>
178+You can also use the following keyboard shortcut.<br>
179+</p>
180+<p>
181+<table>
182+ <tr><th>Key</th><th>Action</th></tr>
183+ <tr><td><kbd>CTRL</kbd> + <kbd>B</kbd><br>
184+ <kbd>CTRL</kbd> + <kbd>P</kbd></td>
185+ <td>Open previous file.</td>
186+ </tr>
187+ <tr><td><kbd>CTRL</kbd> + <kbd>N</kbd></td>
188+ <td>Open next file.</td>
189+ </tr>
190+</table>
191+</p>
192+
193+<h4>3. Folder Playback</h4>
194+<p>
195+When you select "Folder Playback" from "Playback" menu,
196+MIDITrail playback the next file after end of playback automatically.
197+</p>
198+
199+<h3>(4) How to move viewpoint in 3D space</h3>
162200 <p>
163201 You can move freely in 3D space, and look at MIDI datasets from all directions
164202 by operation of keyboard and mouse, like FPS (First Person Shooter) game.<br>
@@ -245,7 +283,7 @@ If you use a mouse with your left hand, this one may be convenience.
245283 </table>
246284 </p>
247285
248-<h3>(4) Selection of the viewpoint</h3>
286+<h3>(5) Selection of the viewpoint</h3>
249287
250288 <p>
251289 When you select "Viewpoint 1 / Viewpoint 2 / Viewpoint 3" from "View" menu,
@@ -260,7 +298,7 @@ or when you push following key, you can move to a fixed viewpoint.
260298 </table>
261299 </p>
262300
263-<h3>(5) Change of window size</h3>
301+<h3>(6) Change of window size</h3>
264302 <p>
265303 When you select "Window size..." from "View" menu, the Window size configuration dialog will appear.<br>
266304 Select your favorite window size, and push the OK button.<br>
@@ -275,13 +313,13 @@ If you want to specify any window size, fill in "Width" "Height".<br>
275313 If you want to apply that size to the view area, check "Apply to the view area".
276314 </p>
277315
278-<h3>(6) Full Screen</h3>
316+<h3>(7) Full Screen</h3>
279317 <p>
280318 When you select "Full Screen" from "View" menu, you can switch between window mode and full screen mode.<br>
281319 By F11 key, you can switch the mode too.
282320 </p>
283321
284-<h3>(7) Display counters</h3>
322+<h3>(8) Display counters</h3>
285323
286324 <p>
287325 <img src="Files/Counter.png"><br>
@@ -300,7 +338,7 @@ By F11 key, you can switch the mode too.
300338 </table>
301339 </p>
302340
303-<h3>(8) View mode select</h3>
341+<h3>(9) View mode select</h3>
304342 <p>
305343 You can select the view mode from "View" menu.
306344 You can not change the view mode while playing or pausing.
@@ -309,7 +347,7 @@ You can not change the view mode while playing or pausing.
309347 <img src="Files/ViewMenu-Mode.png"><br>
310348 </p>
311349
312-<h3>(9) Display/Effect switch</h3>
350+<h3>(10) Display/Effect switch</h3>
313351 <p>
314352 You can switch the display/effect at "View" menu.
315353 </p>
@@ -322,7 +360,7 @@ Some MIDI animation works are using pitch bend to shift the piano roll bars with
322360 If the MIDI animation is not displayed correctly, please disable the pitch bend effect to fix the piano roll bars.
323361 </p>
324362
325-<h3>(10) MIDITrail command line interface</h3>
363+<h3>(11) MIDITrail command line interface</h3>
326364 <p>
327365 If you want to start MIDITrail by command line, you can use following arguments.
328366 </p>
@@ -341,7 +379,7 @@ MIDITrail.exe [-p] [-q] ["path\to\file"]
341379 If you drop a MIDI file to the shortcut of MIDITrail, MIDITrail open the file on startup.
342380 </p>
343381
344-<h3>(11) Graphic configuration</h3>
382+<h3>(12) Graphic configuration</h3>
345383 <p>
346384 Select "Graphic..." from "Option" menu, the graphic configuration dialog will appear.<br>
347385 You can not change graphic configuration while playing or pausing.
@@ -366,7 +404,7 @@ You can change a quarter note length of piano roll.<br>
366404 You can specify a value from 0% to 1000%. The default value is 100%.<br>
367405 </p>
368406
369-<h3>(12) MIDI IN Monitor</h3>
407+<h3>(13) MIDI IN Monitor</h3>
370408 <p>
371409 You can view data sets received from MIDI IN device in realtime.<br>
372410 Select "MIDI IN..." from "Option" menu, then "MIDI IN configuration" dialog will appear.<br>
@@ -381,7 +419,7 @@ When you select "Start Monitoring" from "Playback" menu, MIDI IN monitoring will
381419 NOTE: MIDITrail can not record data sets received from MIDI IN.<br>
382420 </p>
383421
384-<h3>(13) Game Controller</h3>
422+<h3>(14) Game Controller</h3>
385423 <p>
386424 You can operate by XInput game controller.<br>
387425 </p>
@@ -782,7 +820,7 @@ MIDITrail is released under the BSD license.
782820 </p>
783821
784822 <pre>
785-Copyright (c) 2010-2019, WADA Masashi &lt;<img src="Files/mail.png" align="top">&gt;
823+Copyright (c) 2010-2021, WADA Masashi &lt;<img src="Files/mail.png" align="top">&gt;
786824 All rights reserved.
787825
788826 Redistribution and use in source and binary forms, with or without
@@ -952,6 +990,13 @@ This version was released with MIDITrail for Mac OS X.<br>
952990 #39735 Fixed bug (Assertion occurs in _controlfp_s when x64 debug configuration)<br>
953991 #39736 Fixed bug (Exception occurs in "How to view" dialog when x64 debug configuration)<br>
954992 </td></tr>
993+ <tr><td>2021/05/16</td><td>Ver.1.3.3</td><td>
994+#42233 Added Folder Playback feature<br>
995+#42234 Added support for Standard MIDI File with illegal chunk size<br>
996+#42235 Added support for RIFF-based MIDI File<br>
997+#42236 Added sending "All Sound Off" messeage when pause/stop/skip<br>
998+#42237 Fixed bug (The color of the ripples becomes dark in Piano Roll 3D)<br>
999+ </td></tr>
9551000 </table>
9561001 </p>
9571002
--- a/Resources/doc/MANUAL.ja.html
+++ b/Resources/doc/MANUAL.ja.html
@@ -4,7 +4,7 @@
44 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
55 <meta http-equiv="Content-Language" content="ja">
66 <link rel="stylesheet" href="Files/doc.css" type="text/css">
7-<title>MIDITrail Ver.1.3.1 for Windows ユーザーマニュアル</title>
7+<title>MIDITrail Ver.1.3.3 for Windows ユーザーマニュアル</title>
88 </head>
99 <body>
1010
@@ -14,10 +14,10 @@
1414 <a href="MANUAL.en.html">English</a> / Japanese
1515 </div>
1616
17-<h1>MIDITrail Ver.1.3.1 for Windows ユーザーマニュアル</h1>
17+<h1>MIDITrail Ver.1.3.3 for Windows ユーザーマニュアル</h1>
1818
1919 <p>
20-Copyright (c) 2010-2019, WADA Masashi All rights reserved.<br>
20+Copyright (c) 2010-2021, WADA Masashi All rights reserved.<br>
2121 Web: <a href="https://osdn.jp/projects/miditrail/">https://osdn.jp/projects/miditrail/</a><br>
2222 Mail: <img src="Files/mail.png" align="top"><br>
2323 </p>
@@ -126,7 +126,7 @@ RCPCV.DLL <a href="http://www.vector.co.jp/soft/win95/art/se114143.html">http://
126126
127127 <h3>(1) 標準MIDIファイルの読み込み</h3>
128128 <p>
129-「File」メニューから「Open...」を選択すると、ファイル選択ダイアログが表示されます。
129+「File」メニューから「Open File...」を選択すると、ファイル選択ダイアログが表示されます。
130130 ここで標準MIDIファイル(*.mid)を選択してください。<br>
131131 また、標準MIDIファイル(*.mid)をMIDITrailのウィンドウにドラッグ&ドロップすることにより、
132132 ファイルを読み込むことができます。
@@ -156,8 +156,46 @@ RCPCV.DLLを導入している場合は、レコンポーザのデータファ
156156 </table>
157157 </p>
158158
159+<h3>(3) フォルダ演奏</h3>
159160
160-<h3>(3) 三次元空間内の視点移動</h3>
161+<p>
162+MIDITrailは、フォルダに格納されているMIDIデータファイルを順番に開くことができます。<br>
163+ファイルを開く順番は、ファイル名の昇順です。<br>
164+</p>
165+
166+<h4>1.フォルダの選択</h4>
167+<p>
168+「File」メニューの「Open Folder...」を選択すると、フォルダ選択ダイアログが表示されます。<br>
169+ここで標準MIDIファイル(*.mid)が格納されているフォルダを選択してください。<br>
170+フォルダをMIDITrailのウィンドウにドラッグ&ドロップすることもできます。<br>
171+</p>
172+
173+<h4>2. ファイルの切替</h4>
174+<p>
175+「File」メニューから「Previous File」「Next File」を選択すると、ファイルを切り替えることができます。<br>
176+次のショートカットキーも利用できます。<br>
177+</p>
178+<p>
179+<table>
180+ <tr><th>キー</th><th>動作</th></tr>
181+ <tr><td><kbd>CTRL</kbd> + <kbd>B</kbd><br>
182+ <kbd>CTRL</kbd> + <kbd>P</kbd></td>
183+ <td>前のファイルを開く</td>
184+ </tr>
185+ <tr><td><kbd>CTRL</kbd> + <kbd>N</kbd></td>
186+ <td>次のファイルを開く</td>
187+ </tr>
188+</table>
189+</p>
190+
191+<h4>3.フォルダ演奏</h4>
192+<p>
193+「Playback」メニューの「Foler Playback」を選択すると、
194+MIDITrailは演奏終了後、自動的に次のファイルを開いて演奏を開始します。
195+</p>
196+
197+
198+<h3>(4) 三次元空間内の視点移動</h3>
161199 <p>
162200 MIDIファイルを読み込んだ直後、および演奏中に、三次元空間内を移動して、
163201 あらゆる方向からMIDIデータを眺めることができます。<br>
@@ -243,7 +281,7 @@ FPS(一人称シューティング)ゲームでおなじみの操作で、
243281 </table>
244282 </p>
245283
246-<h3>(4) 視点の選択</h3>
284+<h3>(5) 視点の選択</h3>
247285 <p>
248286 Viewメニューから「Viewpoint 1 / Viewpoint 2 / Viewpoint 3」を選択するか、次のキーを押すと、
249287 あらかじめ固定された視点に移動することができます。
@@ -257,7 +295,7 @@ Viewメニューから「Viewpoint 1 / Viewpoint 2 / Viewpoint 3」を選択す
257295 </table>
258296 </p>
259297
260-<h3>(5) ウィンドウサイズの変更</h3>
298+<h3>(6) ウィンドウサイズの変更</h3>
261299 <p>
262300 「View」メニューから「Window size...」を選択すると、ウィンドウサイズ設定ダイアログが表示されます。<br>
263301 お好みのウィンドウサイズを選択してOKボタンを押してください。<br>
@@ -272,14 +310,14 @@ Viewメニューから「Viewpoint 1 / Viewpoint 2 / Viewpoint 3」を選択す
272310 「Aplly to the view area」を選択すると、設定値が画像領域のサイズに反映されます。<br>
273311 </p>
274312
275-<h3>(6) フルスクリーン表示</h3>
313+<h3>(7) フルスクリーン表示</h3>
276314 <p>
277315 「View」メニューから「Full Screen」を選択すると、ウィンドウ表示とフルスクリーン表示を
278316 切り替えることができます。<br>
279317 F11キーを押すことで、表示を切り替えることも可能です。
280318 </p>
281319
282-<h3>(7) 表示カウンタの種類</h3>
320+<h3>(8) 表示カウンタの種類</h3>
283321 <p>
284322 <img src="Files/Counter.png"><br>
285323 </p>
@@ -297,7 +335,7 @@ F11キーを押すことで、表示を切り替えることも可能です。
297335 </table>
298336 </p>
299337
300-<h3>(8) ビューモード選択</h3>
338+<h3>(9) ビューモード選択</h3>
301339 <p>
302340 「View」メニューでビューモードを選択することができます。
303341 演奏中/一時停止中にビューモードの変更はできません。
@@ -306,7 +344,7 @@ F11キーを押すことで、表示を切り替えることも可能です。
306344 <img src="Files/ViewMenu-Mode.png"><br>
307345 </p>
308346
309-<h3>(9) 表示/エフェクト選択</h3>
347+<h3>(10) 表示/エフェクト選択</h3>
310348 <p>
311349 「View」メニューで表示/エフェクトの有無を切り替えることができます。
312350 </p>
@@ -321,7 +359,7 @@ MIDIアニメ作品が正常に表示されない場合は、バーの表示位
321359 ピッチベンドのエフェクトをOFFにしてください。
322360 </p>
323361
324-<h3>(10) MIDITrailコマンドラインインターフェース</h3>
362+<h3>(11) MIDITrailコマンドラインインターフェース</h3>
325363 <p>
326364 コマンドラインからMIDITrailを起動する場合は、以下の引数を指定できます。
327365 </p>
@@ -340,7 +378,7 @@ MIDITrail.exe [-p] [-q] ["path\to\file"]
340378 MIDITrailのショートカットにMIDIファイルをドロップすると、MIDITrail起動時にファイルを開くことができます。
341379 </p>
342380
343-<h3>(11) グラフィック設定</h3>
381+<h3>(12) グラフィック設定</h3>
344382 <p>
345383 「Option」メニューから「Graphic...」を選択すると、グラフィック設定ダイアログが表示されます。<br>
346384 演奏中/一時停止中にグラフィック設定の変更はできません。
@@ -365,7 +403,7 @@ PCがアンチエイリアシングに対応していない場合は「Not suppo
365403 0%から1000%を指定できます。デフォルトは100%です。
366404 </p>
367405
368-<h3>(12) MIDI IN モニタ</h3>
406+<h3>(13) MIDI IN モニタ</h3>
369407 <p>
370408 MIDI INデバイスで受信したデータをリアルタイム表示することができます。<br>
371409 「Option」メニューから「MIDI IN...」を選択すると、MIDI IN設定ダイアログが表示されます。<br>
@@ -380,7 +418,7 @@ MIDI INで受信したデータをそのままMIDI OUTに出力する場合は
380418 なお、MIDITrailはMIDI INで受信したデータを保存することはできません。<br>
381419 </p>
382420
383-<h3>(13) ゲームコントローラー</h3>
421+<h3>(14) ゲームコントローラー</h3>
384422 <p>
385423 XInput対応のゲームコントローラーを用いて操作することができます。<br>
386424 </p>
@@ -772,7 +810,7 @@ MIDITrailは修正BSDライセンスを適用して公開しています。
772810 </p>
773811
774812 <pre>
775-Copyright (c) 2010-2019, WADA Masashi &lt;<img src="Files/mail.png" align="top">&gt;
813+Copyright (c) 2010-2021, WADA Masashi &lt;<img src="Files/mail.png" align="top">&gt;
776814 All rights reserved.
777815
778816 Redistribution and use in source and binary forms, with or without
@@ -942,6 +980,13 @@ MIDITrail for Mac OS Xと同時にリリース<br>
942980 #39735 バグ修正:x64デバッグ構成のとき_controlfp_sでアサーション発生<br>
943981 #39736 バグ修正:x64デバッグ構成のときHow to viewダイアログで例外発生<br>
944982 </td></tr>
983+ <tr><td>2021/05/16</td><td>Ver.1.3.3</td><td>
984+#42233 機能追加:フォルダ演奏対応<br>
985+#42234 機能追加:チャンクサイズ不正の標準MIDIファイル読み込み対応<br>
986+#42235 機能追加:RIFF形式MIDIデータファイルの読み込み対応<br>
987+#42236 機能追加:演奏一時停止時にサウンドオフメッセージを送信<br>
988+#42237 バグ修正:Piano Roll 3Dで波紋の色が暗くなる<br>
989+ </td></tr>
945990 </table>
946991 </p>
947992
--- a/SMIDILib/SMFileReader.cpp
+++ b/SMIDILib/SMFileReader.cpp
@@ -4,7 +4,7 @@
44 //
55 // 標準MIDIファイル読み込みクラス
66 //
7-// Copyright (C) 2010-2013 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -102,6 +102,10 @@ int SMFileReader::Load(
102102 goto EXIT;
103103 }
104104
105+ //RIFFヘッダ読み飛ばし
106+ result = _SkipRIFFHeader(hFile);
107+ if (result != 0 ) goto EXIT;
108+
105109 //ヘッダ読み込み
106110 result = _ReadChunkHeader(hFile, &chunkTypeSection, &chunkDataSection);
107111 if (result != 0 ) goto EXIT;
@@ -162,6 +166,61 @@ EXIT:;
162166 }
163167
164168 //******************************************************************************
169+// RIFFヘッダ読み飛ばし
170+//******************************************************************************
171+int SMFileReader::_SkipRIFFHeader(
172+ HMMIO hFile
173+ )
174+{
175+ int result = 0;
176+ long apiresult = 0;
177+ SMFRIFFChunkHeader chunkHeader;
178+ SMFRIFFSubChunkHeader subChunkHeader;
179+
180+ //RIFFチャンクの読み込み
181+ apiresult = mmioRead(hFile, (HPSTR)&chunkHeader, sizeof(SMFRIFFChunkHeader));
182+ if (apiresult != sizeof(SMFRIFFChunkHeader)) {
183+ result = YN_SET_ERR("File read error.", GetLastError(), apiresult);
184+ goto EXIT;
185+ }
186+
187+ //識別子チェック
188+ if (memcmp(chunkHeader.chunkID, "RIFF", 4) != 0) {
189+ //RIFFではないため読み取り位置を先頭に戻して正常終了
190+ apiresult = mmioSeek(hFile, 0, SEEK_SET);
191+ if (apiresult == -1) {
192+ result = YN_SET_ERR("File read error.", GetLastError(), apiresult);
193+ goto EXIT;
194+ }
195+ goto EXIT;
196+ }
197+
198+ //フォーマットチェック
199+ if (memcmp(chunkHeader.format, "RMID", 4) != 0) {
200+ //RIFFであるがMIDIデータではないためファイル異常とみなす
201+ result = YN_SET_ERR("Invalid data found.", 0, 0);
202+ goto EXIT;
203+ }
204+
205+ //RIFFサブチャンクの読み込み
206+ apiresult = mmioRead(hFile, (HPSTR)&subChunkHeader, sizeof(SMFRIFFSubChunkHeader));
207+ if (apiresult != sizeof(SMFRIFFSubChunkHeader)) {
208+ result = YN_SET_ERR("File read error.", GetLastError(), apiresult);
209+ goto EXIT;
210+ }
211+
212+ //フォーマットチェック
213+ // LISTチャンクには対応しない
214+ if (memcmp(subChunkHeader.chunkID, "data", 4) != 0) {
215+ result = YN_SET_ERR("Invalid data found.", 0, 0);
216+ goto EXIT;
217+ }
218+
219+EXIT:;
220+ return result;
221+}
222+
223+//******************************************************************************
165224 // SMFヘッダ読み込み
166225 //******************************************************************************
167226 int SMFileReader::_ReadChunkHeader(
@@ -268,6 +327,7 @@ int SMFileReader::_ReadTrackEvents(
268327 )
269328 {
270329 int result = 0;
330+ long apiresult = 0;
271331 unsigned long readSize = 0;
272332 unsigned long deltaTime = 0;
273333 unsigned long offset = 0;
@@ -315,10 +375,15 @@ int SMFileReader::_ReadTrackEvents(
315375
316376 //トラック終端
317377 if (isEndOfTrack) {
318- if (readSize != chunkSize) {
319- //データ不正
320- result = YN_SET_ERR("Invalid data found.", readSize, chunkSize);
321- goto EXIT;
378+ //指定されたチャンクサイズまでスキップする(念のため)
379+ if (readSize < chunkSize) {
380+ offset = chunkSize - readSize;
381+ apiresult = mmioSeek(hFile, offset, SEEK_CUR);
382+ if (apiresult == -1) {
383+ result = YN_SET_ERR("File read error.", GetLastError(), apiresult);
384+ goto EXIT;
385+ }
386+ readSize += offset;
322387 }
323388 break;
324389 }
@@ -640,7 +705,7 @@ int SMFileReader::_ReadEventMeta(
640705 break;
641706 }
642707
643- if (status == 0x2F) {
708+ if (type == 0x2F) {
644709 *pIsEndOfTrack = true;
645710 }
646711
--- a/SMIDILib/SMFileReader.h
+++ b/SMIDILib/SMFileReader.h
@@ -4,7 +4,7 @@
44 //
55 // 標準MIDIファイル読み込みクラス
66 //
7-// Copyright (C) 2010 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -51,17 +51,32 @@ private:
5151
5252 #pragma pack(push,1)
5353
54+ //SMFチャンクタイプ
5455 typedef struct {
5556 unsigned char chunkType[4]; //チャンクタイプ MThd/MTrk
5657 unsigned long chunkSize; //チャンクサイズ
5758 } SMFChunkTypeSection;
5859
60+ //SMFチャンクデータ
5961 typedef struct {
6062 unsigned short format; //フォーマット 0,1,2
6163 unsigned short ntracks; //トラック数
6264 unsigned short timeDivision; //4分音符あたりの分解能
6365 } SMFChunkDataSection;
6466
67+ //RIFFチャンク
68+ typedef struct {
69+ unsigned char chunkID[4]; //チャンクID
70+ unsigned long chunkSize; //チャンクサイズ
71+ unsigned char format[4]; //フォーマット
72+ } SMFRIFFChunkHeader;
73+
74+ //RIFFサブチャンク
75+ typedef struct {
76+ unsigned char chunkID[4]; //チャンクID
77+ unsigned long chunkSize; //チャンクサイズ
78+ } SMFRIFFSubChunkHeader;
79+
6580 #pragma pack(pop)
6681
6782 private:
@@ -72,6 +87,10 @@ private:
7287 FILE* m_pLogFile;
7388 bool m_IsLogOut;
7489
90+ int _SkipRIFFHeader(
91+ HMMIO hFile
92+ );
93+
7594 int _ReadChunkHeader(
7695 HMMIO hFile,
7796 SMFChunkTypeSection* pChunkTypeSection,
--- a/SMIDILib/SMOutDevCtrl.cpp
+++ b/SMIDILib/SMOutDevCtrl.cpp
@@ -4,7 +4,7 @@
44 //
55 // MIDI出力デバイス制御クラス
66 //
7-// Copyright (C) 2010-2014 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -447,5 +447,37 @@ EXIT:;
447447 return result;
448448 }
449449
450+//******************************************************************************
451+// 全ポートサウンドオフ
452+//******************************************************************************
453+int SMOutDevCtrl::SoundOffAll()
454+{
455+ int result = 0;
456+ int i = 0;
457+ UINT apiresult = 0;
458+ unsigned long msg = 0;
459+ unsigned char portNo = 0;
460+
461+ for (portNo = 0; portNo < SM_MIDIOUT_PORT_NUM_MAX; portNo++) {
462+
463+ //ポートとデバイスが存在しなければスキップ
464+ if (!m_PortInfo[portNo].isExist) continue;
465+ if (m_PortInfo[portNo].hMIDIOut == NULL) continue;
466+
467+ //全トラックサウンドオフ
468+ for (i = 0; i < 16; i++) {
469+ msg = (0x78 << 8) | (0xB0 | i);
470+ apiresult = midiOutShortMsg(m_PortInfo[portNo].hMIDIOut, msg);
471+ if (apiresult != MMSYSERR_NOERROR) {
472+ result = YN_SET_ERR("MIDI OUT device output error.", apiresult, portNo);
473+ goto EXIT;
474+ }
475+ }
476+ }
477+
478+EXIT:;
479+ return result;
480+}
481+
450482 } // end of namespace
451483
--- a/SMIDILib/SMOutDevCtrl.h
+++ b/SMIDILib/SMOutDevCtrl.h
@@ -4,7 +4,7 @@
44 //
55 // MIDI出力デバイス制御クラス
66 //
7-// Copyright (C) 2010 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -67,6 +67,7 @@ public:
6767 int SendShortMsg(unsigned char portNo, unsigned long msg);
6868 int SendLongMsg(unsigned char portNo, unsigned char* pMsg, unsigned long size);
6969 int NoteOffAll();
70+ int SoundOffAll();
7071
7172 private:
7273
--- a/SMIDILib/SMSequencer.cpp
+++ b/SMIDILib/SMSequencer.cpp
@@ -4,7 +4,7 @@
44 //
55 // シーケンサクラス
66 //
7-// Copyright (C) 2010-2013 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -824,6 +824,10 @@ int SMSequencer::_ProcUserRequest(
824824 result = _AllTrackNoteOff();
825825 if (result != 0) goto EXIT;
826826
827+ //全トラックサウンドオフ
828+ result = _AllTrackSoundOff();
829+ if (result != 0) goto EXIT;
830+
827831 *pIsContinue = false;
828832
829833 //一時停止を要求された場合
@@ -866,6 +870,20 @@ EXIT:;
866870 }
867871
868872 //******************************************************************************
873+// 全トラックサウンドオフ
874+//******************************************************************************
875+int SMSequencer::_AllTrackSoundOff()
876+{
877+ int result = 0;
878+
879+ result = m_OutDevCtrl.SoundOffAll();
880+ if (result != 0) goto EXIT;
881+
882+EXIT:;
883+ return result;
884+}
885+
886+//******************************************************************************
869887 // 現在時刻取得(ナノ秒)
870888 //******************************************************************************
871889 unsigned long long SMSequencer::_GetCurTimeInNano()
--- a/SMIDILib/SMSequencer.h
+++ b/SMIDILib/SMSequencer.h
@@ -4,7 +4,7 @@
44 //
55 // シーケンサクラス
66 //
7-// Copyright (C) 2010-2013 WADA Masashi. All Rights Reserved.
7+// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
88 //
99 //******************************************************************************
1010
@@ -174,6 +174,7 @@ private:
174174 int _SendSysExEvent(unsigned char portNo, SMEventSysEx* pSysExEvent);
175175 int _SendMetaEvent(unsigned char portNo, SMEventMeta* pMetaEvent);
176176 int _AllTrackNoteOff();
177+ int _AllTrackSoundOff();
177178
178179 //その他
179180 int _ProcUserRequest(BOOL* pIsContinue);