├── .gitattributes ├── .gitignore ├── CREDITS.md ├── Common.props ├── LICENSE ├── OutProcess ├── App.cpp ├── App.h ├── App_Waveform.cpp ├── CacheManager.cpp ├── CacheManager.h ├── Design.cpp ├── Design.h ├── MainDialog.cpp ├── MainDialog.h ├── MainWindow.cpp ├── MainWindow.h ├── MainWindow_Config.cpp ├── MainWindow_Layout.cpp ├── MainWindow_Mouse.cpp ├── MainWindow_OpenGL.cpp ├── MainWindow_Paint.cpp ├── Mode.cpp ├── Mode.h ├── Mode_BottomUp.cpp ├── Mode_Center.cpp ├── Mode_RMS.cpp ├── Mode_TopDown.cpp ├── OutProcess.cpp ├── OutProcess.h ├── OutProcess.rc ├── OutProcess.vcxproj ├── OutProcess.vcxproj.filters ├── ReaderManager.cpp ├── ReaderManager.h ├── WaiterManager.cpp ├── WaiterManager.h ├── framework.h ├── pch.cpp ├── pch.h ├── resource.h └── targetver.h ├── README.md ├── ReaderProcess ├── App.h ├── Calc │ ├── Hive.h │ └── Worker.h ├── Plugin.cpp ├── Plugin.h ├── ReaderProcess.cpp ├── ReaderProcess.vcxproj ├── ReaderProcess.vcxproj.filters ├── framework.h ├── pch.cpp ├── pch.h └── targetver.h ├── ShowWaveform.sln └── ShowWaveform ├── App.cpp ├── App.h ├── FileCache.cpp ├── FileCache.h ├── ItemCache.cpp ├── ItemCache.h ├── MainDialog.cpp ├── MainDialog.h ├── Share.h ├── ShowWaveform.cpp ├── ShowWaveform.def ├── ShowWaveform.h ├── ShowWaveform.rc ├── ShowWaveform.vcxproj ├── ShowWaveform.vcxproj.filters ├── SubProcess.cpp ├── SubProcess.h ├── SubThread.cpp ├── SubThread.h ├── pch.cpp ├── pch.h └── resource.h /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | _bin/ 36 | _obj/ 37 | 38 | # Visual Studio 2015/2017 cache/options directory 39 | .vs/ 40 | # Uncomment if you have tasks that create the project's static files in wwwroot 41 | #wwwroot/ 42 | 43 | # Visual Studio 2017 auto generated files 44 | Generated\ Files/ 45 | 46 | # MSTest test Results 47 | [Tt]est[Rr]esult*/ 48 | [Bb]uild[Ll]og.* 49 | 50 | # NUnit 51 | *.VisualState.xml 52 | TestResult.xml 53 | nunit-*.xml 54 | 55 | # Build Results of an ATL Project 56 | [Dd]ebugPS/ 57 | [Rr]eleasePS/ 58 | dlldata.c 59 | 60 | # Benchmark Results 61 | BenchmarkDotNet.Artifacts/ 62 | 63 | # .NET Core 64 | project.lock.json 65 | project.fragment.lock.json 66 | artifacts/ 67 | 68 | # ASP.NET Scaffolding 69 | ScaffoldingReadMe.txt 70 | 71 | # StyleCop 72 | StyleCopReport.xml 73 | 74 | # Files built by Visual Studio 75 | *_i.c 76 | *_p.c 77 | *_h.h 78 | *.ilk 79 | *.meta 80 | *.obj 81 | *.iobj 82 | *.pch 83 | *.pdb 84 | *.ipdb 85 | *.pgc 86 | *.pgd 87 | *.rsp 88 | *.sbr 89 | *.tlb 90 | *.tli 91 | *.tlh 92 | *.tmp 93 | *.tmp_proj 94 | *_wpftmp.csproj 95 | *.log 96 | *.vspscc 97 | *.vssscc 98 | .builds 99 | *.pidb 100 | *.svclog 101 | *.scc 102 | 103 | # Chutzpah Test files 104 | _Chutzpah* 105 | 106 | # Visual C++ cache files 107 | ipch/ 108 | *.aps 109 | *.ncb 110 | *.opendb 111 | *.opensdf 112 | *.sdf 113 | *.cachefile 114 | *.VC.db 115 | *.VC.VC.opendb 116 | 117 | # Visual Studio profiler 118 | *.psess 119 | *.vsp 120 | *.vspx 121 | *.sap 122 | 123 | # Visual Studio Trace Files 124 | *.e2e 125 | 126 | # TFS 2012 Local Workspace 127 | $tf/ 128 | 129 | # Guidance Automation Toolkit 130 | *.gpState 131 | 132 | # ReSharper is a .NET coding add-in 133 | _ReSharper*/ 134 | *.[Rr]e[Ss]harper 135 | *.DotSettings.user 136 | 137 | # TeamCity is a build add-in 138 | _TeamCity* 139 | 140 | # DotCover is a Code Coverage Tool 141 | *.dotCover 142 | 143 | # AxoCover is a Code Coverage Tool 144 | .axoCover/* 145 | !.axoCover/settings.json 146 | 147 | # Coverlet is a free, cross platform Code Coverage Tool 148 | coverage*.json 149 | coverage*.xml 150 | coverage*.info 151 | 152 | # Visual Studio code coverage results 153 | *.coverage 154 | *.coveragexml 155 | 156 | # NCrunch 157 | _NCrunch_* 158 | .*crunch*.local.xml 159 | nCrunchTemp_* 160 | 161 | # MightyMoose 162 | *.mm.* 163 | AutoTest.Net/ 164 | 165 | # Web workbench (sass) 166 | .sass-cache/ 167 | 168 | # Installshield output folder 169 | [Ee]xpress/ 170 | 171 | # DocProject is a documentation generator add-in 172 | DocProject/buildhelp/ 173 | DocProject/Help/*.HxT 174 | DocProject/Help/*.HxC 175 | DocProject/Help/*.hhc 176 | DocProject/Help/*.hhk 177 | DocProject/Help/*.hhp 178 | DocProject/Help/Html2 179 | DocProject/Help/html 180 | 181 | # Click-Once directory 182 | publish/ 183 | 184 | # Publish Web Output 185 | *.[Pp]ublish.xml 186 | *.azurePubxml 187 | # Note: Comment the next line if you want to checkin your web deploy settings, 188 | # but database connection strings (with potential passwords) will be unencrypted 189 | *.pubxml 190 | *.publishproj 191 | 192 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 193 | # checkin your Azure Web App publish settings, but sensitive information contained 194 | # in these scripts will be unencrypted 195 | PublishScripts/ 196 | 197 | # NuGet Packages 198 | *.nupkg 199 | # NuGet Symbol Packages 200 | *.snupkg 201 | # The packages folder can be ignored because of Package Restore 202 | **/[Pp]ackages/* 203 | # except build/, which is used as an MSBuild target. 204 | !**/[Pp]ackages/build/ 205 | # Uncomment if necessary however generally it will be regenerated when needed 206 | #!**/[Pp]ackages/repositories.config 207 | # NuGet v3's project.json files produces more ignorable files 208 | *.nuget.props 209 | *.nuget.targets 210 | 211 | # Microsoft Azure Build Output 212 | csx/ 213 | *.build.csdef 214 | 215 | # Microsoft Azure Emulator 216 | ecf/ 217 | rcf/ 218 | 219 | # Windows Store app package directories and files 220 | AppPackages/ 221 | BundleArtifacts/ 222 | Package.StoreAssociation.xml 223 | _pkginfo.txt 224 | *.appx 225 | *.appxbundle 226 | *.appxupload 227 | 228 | # Visual Studio cache files 229 | # files ending in .cache can be ignored 230 | *.[Cc]ache 231 | # but keep track of directories ending in .cache 232 | !?*.[Cc]ache/ 233 | 234 | # Others 235 | ClientBin/ 236 | ~$* 237 | *~ 238 | *.dbmdl 239 | *.dbproj.schemaview 240 | *.jfm 241 | *.pfx 242 | *.publishsettings 243 | orleans.codegen.cs 244 | 245 | # Including strong name files can present a security risk 246 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 247 | #*.snk 248 | 249 | # Since there are multiple workflows, uncomment next line to ignore bower_components 250 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 251 | #bower_components/ 252 | 253 | # RIA/Silverlight projects 254 | Generated_Code/ 255 | 256 | # Backup & report files from converting an old project file 257 | # to a newer Visual Studio version. Backup files are not needed, 258 | # because we have git ;-) 259 | _UpgradeReport_Files/ 260 | Backup*/ 261 | UpgradeLog*.XML 262 | UpgradeLog*.htm 263 | ServiceFabricBackup/ 264 | *.rptproj.bak 265 | 266 | # SQL Server files 267 | *.mdf 268 | *.ldf 269 | *.ndf 270 | 271 | # Business Intelligence projects 272 | *.rdl.data 273 | *.bim.layout 274 | *.bim_*.settings 275 | *.rptproj.rsuser 276 | *- [Bb]ackup.rdl 277 | *- [Bb]ackup ([0-9]).rdl 278 | *- [Bb]ackup ([0-9][0-9]).rdl 279 | 280 | # Microsoft Fakes 281 | FakesAssemblies/ 282 | 283 | # GhostDoc plugin setting file 284 | *.GhostDoc.xml 285 | 286 | # Node.js Tools for Visual Studio 287 | .ntvs_analysis.dat 288 | node_modules/ 289 | 290 | # Visual Studio 6 build log 291 | *.plg 292 | 293 | # Visual Studio 6 workspace options file 294 | *.opt 295 | 296 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 297 | *.vbw 298 | 299 | # Visual Studio LightSwitch build output 300 | **/*.HTMLClient/GeneratedArtifacts 301 | **/*.DesktopClient/GeneratedArtifacts 302 | **/*.DesktopClient/ModelManifest.xml 303 | **/*.Server/GeneratedArtifacts 304 | **/*.Server/ModelManifest.xml 305 | _Pvt_Extensions 306 | 307 | # Paket dependency manager 308 | .paket/paket.exe 309 | paket-files/ 310 | 311 | # FAKE - F# Make 312 | .fake/ 313 | 314 | # CodeRush personal settings 315 | .cr/personal 316 | 317 | # Python Tools for Visual Studio (PTVS) 318 | __pycache__/ 319 | *.pyc 320 | 321 | # Cake - Uncomment if you are using it 322 | # tools/** 323 | # !tools/packages.config 324 | 325 | # Tabs Studio 326 | *.tss 327 | 328 | # Telerik's JustMock configuration file 329 | *.jmconfig 330 | 331 | # BizTalk build output 332 | *.btp.cs 333 | *.btm.cs 334 | *.odx.cs 335 | *.xsd.cs 336 | 337 | # OpenCover UI analysis results 338 | OpenCover/ 339 | 340 | # Azure Stream Analytics local run output 341 | ASALocalRun/ 342 | 343 | # MSBuild Binary and Structured Log 344 | *.binlog 345 | 346 | # NVidia Nsight GPU debugger configuration file 347 | *.nvuser 348 | 349 | # MFractors (Xamarin productivity tool) working folder 350 | .mfractor/ 351 | 352 | # Local History for Visual Studio 353 | .localhistory/ 354 | 355 | # BeatPulse healthcheck temp database 356 | healthchecksdb 357 | 358 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 359 | MigrationBackup/ 360 | 361 | # Ionide (cross platform F# VS Code tools) working folder 362 | .ionide/ 363 | 364 | # Fody - auto-generated XML schema 365 | FodyWeavers.xsd -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hebiiro/AviUtl-Plugin-ShowWaveform/ada292c648f8d941588c9261710214e157c187ef/CREDITS.md -------------------------------------------------------------------------------- /Common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $(UserProfile)\source 6 | $(my_source)\packages 7 | 8 | 9 | $(SolutionDir)_bin\ 10 | $(SolutionDir)_obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ 11 | 12 | 13 | 14 | $(IntDir) 15 | 16 | 17 | 18 | 19 | $(IntDir) 20 | $(my_packages)\detours.4.0.1;$(my_packages)\glad.2.0.4;$(my_packages)\nanovg.rgb2hsv;$(my_packages)\aviutl_exedit_sdk;$(my_packages)\my;%(AdditionalIncludeDirectories) 21 | 22 | 23 | $(my_packages)\detours.4.0.1;$(my_packages)\nanovg.rgb2hsv;%(AdditionalLibraryDirectories) 24 | 25 | 26 | 27 | 28 | $(my_source) 29 | 30 | 31 | $(my_packages) 32 | 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 hebiiro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /OutProcess/App.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "App.h" 3 | #include "Common/Tracer2.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | App theApp; 8 | Shared shared; 9 | 10 | //-------------------------------------------------------------------- 11 | 12 | BOOL App::getShowBPM() 13 | { 14 | return mainWindow.getShowBPM(); 15 | } 16 | 17 | BOOL App::setShowBPM(BOOL newShowBPM) 18 | { 19 | if (!mainWindow.setShowBPM(newShowBPM)) 20 | return FALSE; 21 | 22 | mainDialog.ignoreNotification(TRUE); 23 | mainDialog.setShowBPM(mainWindow.getShowBPM()); 24 | mainDialog.ignoreNotification(FALSE); 25 | 26 | return TRUE; 27 | } 28 | 29 | int App::getOrig() 30 | { 31 | return mainWindow.getOrig(); 32 | } 33 | 34 | BOOL App::setOrig(int newOrig) 35 | { 36 | if (!mainWindow.setOrig(newOrig)) 37 | return FALSE; 38 | 39 | mainDialog.ignoreNotification(TRUE); 40 | mainDialog.setOrig(mainWindow.getOrig()); 41 | mainDialog.ignoreNotification(FALSE); 42 | 43 | return TRUE; 44 | } 45 | 46 | int App::getBPM() 47 | { 48 | return mainWindow.getBPM(); 49 | } 50 | 51 | BOOL App::setBPM(int newBPM) 52 | { 53 | if (!mainWindow.setBPM(newBPM)) 54 | return FALSE; 55 | 56 | mainDialog.ignoreNotification(TRUE); 57 | mainDialog.setBPM(mainWindow.getBPM()); 58 | mainDialog.ignoreNotification(FALSE); 59 | 60 | return TRUE; 61 | } 62 | 63 | int App::getAbove() 64 | { 65 | return mainWindow.getAbove(); 66 | } 67 | 68 | BOOL App::setAbove(int newAbove) 69 | { 70 | if (!mainWindow.setAbove(newAbove)) 71 | return FALSE; 72 | 73 | mainDialog.ignoreNotification(TRUE); 74 | mainDialog.setAbove(mainWindow.getAbove()); 75 | mainDialog.ignoreNotification(FALSE); 76 | 77 | return TRUE; 78 | } 79 | 80 | int App::getBelow() 81 | { 82 | return mainWindow.getBelow(); 83 | } 84 | 85 | BOOL App::setBelow(int newBelow) 86 | { 87 | if (!mainWindow.setBelow(newBelow)) 88 | return FALSE; 89 | 90 | mainDialog.ignoreNotification(TRUE); 91 | mainDialog.setBelow(mainWindow.getBelow()); 92 | mainDialog.ignoreNotification(FALSE); 93 | 94 | return TRUE; 95 | } 96 | 97 | int App::getLimitVolume() 98 | { 99 | return mainWindow.getLimitVolume(); 100 | } 101 | 102 | BOOL App::setLimitVolume(int newLimitVolume) 103 | { 104 | if (!mainWindow.setLimitVolume(newLimitVolume)) 105 | return FALSE; 106 | 107 | mainDialog.ignoreNotification(TRUE); 108 | mainDialog.setLimitVolume(mainWindow.getLimitVolume()); 109 | mainDialog.ignoreNotification(FALSE); 110 | 111 | return TRUE; 112 | } 113 | 114 | int App::getBaseVolume() 115 | { 116 | return mainWindow.getBaseVolume(); 117 | } 118 | 119 | BOOL App::setBaseVolume(int newBaseVolume) 120 | { 121 | if (!mainWindow.setBaseVolume(newBaseVolume)) 122 | return FALSE; 123 | 124 | mainDialog.ignoreNotification(TRUE); 125 | mainDialog.setBaseVolume(mainWindow.getBaseVolume()); 126 | mainDialog.ignoreNotification(FALSE); 127 | 128 | return TRUE; 129 | } 130 | 131 | int App::getMinRMS() 132 | { 133 | return mainWindow.getMinRMS(); 134 | } 135 | 136 | BOOL App::setMinRMS(int newMinRMS) 137 | { 138 | if (!mainWindow.setMinRMS(newMinRMS)) 139 | return FALSE; 140 | 141 | mainDialog.ignoreNotification(TRUE); 142 | mainDialog.setMinRMS(mainWindow.getMinRMS()); 143 | mainDialog.ignoreNotification(FALSE); 144 | 145 | return TRUE; 146 | } 147 | 148 | int App::getMaxRMS() 149 | { 150 | return mainWindow.getMaxRMS(); 151 | } 152 | 153 | BOOL App::setMaxRMS(int newMaxRMS) 154 | { 155 | if (!mainWindow.setMaxRMS(newMaxRMS)) 156 | return FALSE; 157 | 158 | mainDialog.ignoreNotification(TRUE); 159 | mainDialog.setMaxRMS(mainWindow.getMaxRMS()); 160 | mainDialog.ignoreNotification(FALSE); 161 | 162 | return TRUE; 163 | } 164 | 165 | int App::getBaseRMS() 166 | { 167 | return mainWindow.getBaseRMS(); 168 | } 169 | 170 | BOOL App::setBaseRMS(int newBaseRMS) 171 | { 172 | if (!mainWindow.setBaseRMS(newBaseRMS)) 173 | return FALSE; 174 | 175 | mainDialog.ignoreNotification(TRUE); 176 | mainDialog.setBaseRMS(mainWindow.getBaseRMS()); 177 | mainDialog.ignoreNotification(FALSE); 178 | 179 | return TRUE; 180 | } 181 | 182 | int App::getZoom() 183 | { 184 | return mainWindow.getZoom(); 185 | } 186 | 187 | BOOL App::setZoom(int newZoom) 188 | { 189 | if (!mainWindow.setZoom(newZoom)) 190 | return FALSE; 191 | 192 | mainDialog.ignoreNotification(TRUE); 193 | mainDialog.setZoom(mainWindow.getZoom()); 194 | mainDialog.ignoreNotification(FALSE); 195 | 196 | return TRUE; 197 | } 198 | 199 | //-------------------------------------------------------------------- 200 | 201 | void CALLBACK App::timerProc(HWND hwnd, UINT message, UINT_PTR timerId, DWORD time) 202 | { 203 | if (!::IsWindow(theApp.windowContainer)) 204 | { 205 | MY_TRACE(_T("コンテナウィンドウが無効になりました\n")); 206 | 207 | ::PostQuitMessage(0); 208 | } 209 | } 210 | 211 | int APIENTRY App::WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow) 212 | { 213 | struct Initializer 214 | { 215 | Initializer() 216 | { 217 | _tsetlocale(LC_ALL, _T("")); 218 | trace_init(0, 0, TRUE); 219 | ::OleInitialize(0); 220 | } 221 | 222 | ~Initializer() 223 | { 224 | trace_term(); 225 | ::OleUninitialize(); 226 | } 227 | 228 | } initializer; 229 | 230 | MY_TRACE(_T("WinMain()\n")); 231 | 232 | windowContainer = (HWND)_tcstoull(::GetCommandLine(), 0, 0); 233 | MY_TRACE_HEX(windowContainer); 234 | 235 | dialogContainer = (HWND)::GetProp(windowContainer, PROP_NAME_DIALOG_CONTAINER); 236 | MY_TRACE_HEX(dialogContainer); 237 | 238 | if (!shared.init(windowContainer)) 239 | { 240 | ::MessageBox(windowContainer, _T("共有メモリの初期化に失敗しました"), _T("ShowWaveform.OutProcess"), MB_OK); 241 | return -1; 242 | } 243 | 244 | if (!mainWindow.create(instance, windowContainer)) 245 | { 246 | ::MessageBox(windowContainer, _T("メインウィンドウの作成に失敗しました"), _T("ShowWaveform.OutProcess"), MB_OK); 247 | return -1; 248 | } 249 | 250 | MY_TRACE_HWND((HWND)mainWindow); 251 | 252 | if (!mainDialog.create(instance, dialogContainer)) 253 | { 254 | ::MessageBox(windowContainer, _T("メインダイアログの作成に失敗しました"), _T("ShowWaveform.OutProcess"), MB_OK); 255 | return -1; 256 | } 257 | 258 | MY_TRACE_HWND((HWND)mainDialog); 259 | 260 | // InProcess にウィンドウハンドルを渡す。 261 | ::PostMessage(windowContainer, WM_AVIUTL_FILTER_INIT, (WPARAM)(HWND)mainWindow, 0); 262 | ::PostMessage(dialogContainer, WM_AVIUTL_FILTER_INIT, (WPARAM)(HWND)mainDialog, 0); 263 | 264 | // InProcess を監視するタイマーを作成する。 265 | // メインウィンドウは削除されるかもしれないので WM_TIMER は使用できない。 266 | ::SetTimer(0, 0, 1000, timerProc); 267 | 268 | MSG msg = {}; 269 | while (::GetMessage(&msg, 0, 0, 0)) 270 | { 271 | ::TranslateMessage(&msg); 272 | ::DispatchMessage(&msg); 273 | } 274 | 275 | shared.term(); 276 | 277 | MY_TRACE(_T("プロセスが正常終了しました\n")); 278 | 279 | return 0; 280 | } 281 | 282 | LRESULT App::onAviUtlFilterSend(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 283 | { 284 | MY_TRACE(_T("onAviUtlFilterSend(0x%08X, 0x%08X)\n"), wParam, lParam); 285 | 286 | switch (wParam) 287 | { 288 | case SendID::requestCache: 289 | { 290 | SenderBottlePtr bottle = shared.getSenderBottle(); 291 | if (bottle) 292 | { 293 | CachePtr cache = cacheManager.getCache(bottle->fileName); 294 | if (cache) 295 | { 296 | // キャッシュが作成済みならメインプロセスに通知する。 297 | sendCache(cache); 298 | } 299 | else 300 | { 301 | // キャッシュが存在しないので新規作成する。 302 | // (1) ファイル名からウェイターを作成する。 303 | // (2) ウェイターからリーダーを作成する。 304 | // (3) リーダーからキャッシュを作成する。 305 | 306 | // ウェイターを作成する。 307 | WaiterPtr waiter = waiterManager.createWaiter(bottle->fileName); 308 | 309 | // 可能であれば、ウェイターを消化する。 310 | waiterManager.digestWaiterQueue(readerManager); 311 | } 312 | } 313 | 314 | break; 315 | } 316 | case SendID::notifyProjectChanged: 317 | { 318 | ProjectParamsPtr params = shared.getProjectParams(); 319 | if (params) 320 | setProjectParams(params); 321 | 322 | break; 323 | } 324 | case SendID::notifyItemChanged: 325 | { 326 | AudioParamsPtr params = shared.getAudioParams(); 327 | if (params) 328 | setAudioParams(params); 329 | 330 | break; 331 | } 332 | case SendID::notifyTotalsChanged: 333 | { 334 | TotalsParamsPtr params = shared.getSenderTotalsParams(); 335 | if (params) 336 | setTotalsParams(params); 337 | 338 | break; 339 | } 340 | } 341 | 342 | return 0; 343 | } 344 | 345 | LRESULT App::onAviUtlFilterReceive(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 346 | { 347 | MY_TRACE(_T("onAviUtlFilterReceive(0x%08X, 0x%08X)\n"), wParam, lParam); 348 | 349 | DWORD id = (DWORD)wParam; 350 | MY_TRACE_INT(id); 351 | 352 | // リーダーを取得する。 353 | ReaderPtr reader = readerManager.getReader(id); 354 | if (reader) 355 | { 356 | // キャッシュを作成する。 357 | CachePtr cache = cacheManager.createCache(reader); 358 | if (cache) 359 | { 360 | // キャッシュを作成できた場合はメインプロセスに通知する。 361 | sendCache(cache); 362 | 363 | // このリーダーは不要になったので削除する。 364 | readerManager.eraseReader(id); 365 | 366 | // リーダーの空きができたので次の読み込みを開始する。 367 | waiterManager.digestWaiterQueue(readerManager); 368 | } 369 | } 370 | 371 | return 0; 372 | } 373 | 374 | LRESULT App::onAviUtlFilterClear(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 375 | { 376 | MY_TRACE(_T("onAviUtlFilterClear(0x%08X, 0x%08X)\n"), wParam, lParam); 377 | 378 | cacheManager.clear(); 379 | 380 | return 0; 381 | } 382 | 383 | LRESULT App::onAviUtlFilterRedraw(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 384 | { 385 | MY_TRACE(_T("onAviUtlFilterRedraw(0x%08X, 0x%08X)\n"), wParam, lParam); 386 | 387 | if (::IsWindowVisible(mainWindow)) 388 | { 389 | // 全体の音声波形を再計算する。 390 | recalcTotals(); 391 | } 392 | 393 | return 0; 394 | } 395 | 396 | //-------------------------------------------------------------------- 397 | 398 | int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow) 399 | { 400 | return theApp.WinMain(instance, prevInstance, cmdLine, cmdShow); 401 | } 402 | 403 | //-------------------------------------------------------------------- 404 | -------------------------------------------------------------------------------- /OutProcess/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CacheManager.h" 4 | #include "ReaderManager.h" 5 | #include "WaiterManager.h" 6 | #include "MainWindow.h" 7 | #include "MainDialog.h" 8 | 9 | //-------------------------------------------------------------------- 10 | 11 | typedef std::map AudioParamsMap; 12 | 13 | struct Total { 14 | float level; 15 | float rms; 16 | }; 17 | 18 | typedef std::vector Totals; 19 | 20 | //-------------------------------------------------------------------- 21 | 22 | extern Shared shared; 23 | 24 | //-------------------------------------------------------------------- 25 | 26 | struct App { 27 | HINSTANCE instance = 0; 28 | HWND windowContainer = 0; 29 | HWND dialogContainer = 0; 30 | CacheManager cacheManager; 31 | ReaderManager readerManager; 32 | WaiterManager waiterManager; 33 | MainWindow mainWindow; 34 | MainDialog mainDialog; 35 | 36 | BOOL getShowBPM(); 37 | BOOL setShowBPM(BOOL newShowBPM); 38 | int getOrig(); 39 | BOOL setOrig(int newOrig); 40 | int getBPM(); 41 | BOOL setBPM(int newBPM); 42 | int getAbove(); 43 | BOOL setAbove(int newAbove); 44 | int getBelow(); 45 | BOOL setBelow(int newBelow); 46 | 47 | int getLimitVolume(); 48 | BOOL setLimitVolume(int newLimitVolume); 49 | int getBaseVolume(); 50 | BOOL setBaseVolume(int newBaseVolume); 51 | int getMinRMS(); 52 | BOOL setMinRMS(int newMinRMS); 53 | int getMaxRMS(); 54 | BOOL setMaxRMS(int newMaxRMS); 55 | int getBaseRMS(); 56 | BOOL setBaseRMS(int newBaseRMS); 57 | int getZoom(); 58 | BOOL setZoom(int newZoom); 59 | 60 | static void CALLBACK timerProc(HWND hwnd, UINT message, UINT_PTR timerId, DWORD time); 61 | int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow); 62 | LRESULT onAviUtlFilterSend(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 63 | LRESULT onAviUtlFilterReceive(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 64 | LRESULT onAviUtlFilterClear(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 65 | LRESULT onAviUtlFilterRedraw(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 66 | 67 | // App_Waveform 68 | 69 | Totals totals; 70 | ProjectParamsPtr projectParams; 71 | AudioParamsMap audioParamsMap; 72 | 73 | BOOL sendCache(const CachePtr& cache); 74 | BOOL recalcTotals(); 75 | BOOL setProjectParams(const ProjectParamsPtr& params); 76 | BOOL setAudioParams(const AudioParamsPtr& params); 77 | BOOL setTotalsParams(const TotalsParamsPtr& params); 78 | }; 79 | 80 | extern App theApp; 81 | 82 | //-------------------------------------------------------------------- 83 | -------------------------------------------------------------------------------- /OutProcess/App_Waveform.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "App.h" 3 | 4 | //-------------------------------------------------------------------- 5 | 6 | // キャッシュをボトルに詰めてからメインプロセスに送る。(受け取るように促す) 7 | BOOL App::sendCache(const CachePtr& cache) 8 | { 9 | MY_TRACE(_T("App::sendCache(%hs)\n"), cache->fileName.c_str()); 10 | 11 | ReceiverBottle* shared = ::shared.receiverBottle.getBuffer(); 12 | MY_TRACE_HEX(shared); 13 | if (!shared) return FALSE; 14 | 15 | ::StringCbCopyA(shared->fileName, sizeof(shared->fileName), cache->fileName.c_str()); 16 | 17 | shared->volumeCount = (int32_t)cache->volumes.size(); 18 | MY_TRACE_INT(shared->volumeCount); 19 | memcpy(shared->volumes, cache->volumes.data(), sizeof(Volume) * cache->volumes.size()); 20 | 21 | MY_TRACE_HEX(windowContainer); 22 | ::SendMessage(windowContainer, WM_AVIUTL_FILTER_RECEIVE, 0, 0); 23 | 24 | return TRUE; 25 | } 26 | 27 | BOOL App::recalcTotals() 28 | { 29 | MY_TRACE(_T("App::recalcTotals()\n")); 30 | 31 | // プロジェクトパラメータが有効かどうかチェックする。 32 | if (!projectParams) return FALSE; 33 | if (projectParams->frameNumber <= 0) return FALSE; 34 | 35 | // 全てのアイテムのキャッシュが作成済みかチェックする。 36 | for (auto pair : audioParamsMap) 37 | { 38 | const AudioParamsPtr& params = pair.second; 39 | if (params->sceneSet != projectParams->sceneIndex) continue; 40 | const CachePtr& cache = cacheManager.getCache(params->fileName); 41 | if (!cache) return FALSE; 42 | } 43 | 44 | // バッファを確保する。 45 | totals.resize(projectParams->frameNumber); 46 | memset(totals.data(), 0, sizeof(totals[0]) * totals.size()); 47 | 48 | float scale = (float)Volume::Resolution * projectParams->video_scale / projectParams->video_rate; 49 | MY_TRACE_REAL(scale); 50 | 51 | for (auto pair : audioParamsMap) 52 | { 53 | const AudioParamsPtr& params = pair.second; 54 | if (params->sceneSet != projectParams->sceneIndex) continue; 55 | if (params->layerFlag & (uint32_t)ExEdit::LayerSetting::Flag::UnDisp) continue; 56 | const CachePtr& cache = cacheManager.getCache(params->fileName); 57 | if (!cache) continue; 58 | 59 | // 現在のフレームレートでの1フレーム毎の音量に変換する。 60 | 61 | int32_t frameBegin = params->frameBegin; 62 | int32_t frameEnd = std::min(params->frameEnd + 1, projectParams->frameNumber); 63 | int32_t frameRange = frameEnd - frameBegin; 64 | for (int32_t i = 0; i < frameRange; i++) 65 | { 66 | float temp1 = scale * params->playSpeed * i; 67 | float temp2 = scale * params->playBegin; 68 | int32_t src = (int32_t)(temp1 + temp2); 69 | int32_t dst = i + frameBegin; 70 | 71 | if (src < 0 || src >= (int32_t)cache->volumes.size()) 72 | break; 73 | 74 | if (dst < 0 || dst >= (int32_t)totals.size()) 75 | break; 76 | 77 | totals[dst].level += cache->volumes[src].level * params->volume; 78 | } 79 | } 80 | 81 | int c = (int)totals.size(); 82 | MY_TRACE_INT(c); 83 | for (int i = 0; i < c; i++) 84 | { 85 | totals[i].rms = 20 * log10f(totals[i].level); 86 | 87 | // MY_TRACE(_T("%d : %f, %f\n"), i, totals[i].level, totals[i].rms); 88 | } 89 | 90 | mainWindow.recalcLayout(); 91 | mainWindow.outputFrames(); 92 | mainWindow.redraw(); 93 | 94 | return TRUE; 95 | } 96 | 97 | BOOL App::setProjectParams(const ProjectParamsPtr& params) 98 | { 99 | MY_TRACE(_T("App::setProjectParams()\n")); 100 | 101 | if (projectParams && 102 | projectParams->video_scale == params->video_scale && 103 | projectParams->video_rate == params->video_rate && 104 | projectParams->frameNumber == params->frameNumber && 105 | projectParams->sceneIndex == params->sceneIndex) 106 | { 107 | MY_TRACE_INT(params->currentFrame); 108 | 109 | // カレントフレームが異なる場合は 110 | if (projectParams->currentFrame != params->currentFrame) 111 | { 112 | MY_TRACE(_T("カレントフレームが異なるので再描画します\n")); 113 | 114 | // カレントフレームを更新し、 115 | projectParams->currentFrame = params->currentFrame; 116 | 117 | // 再描画する。 118 | mainWindow.redraw(); 119 | 120 | // カレントフレームをステータスボックスに出力する。 121 | mainWindow.outputFrames(); 122 | } 123 | 124 | return FALSE; 125 | } 126 | 127 | projectParams = params; 128 | MY_TRACE_INT(projectParams->video_scale); 129 | MY_TRACE_INT(projectParams->video_rate); 130 | MY_TRACE_INT(projectParams->frameNumber); 131 | MY_TRACE_INT(projectParams->sceneIndex); 132 | MY_TRACE_INT(projectParams->currentFrame); 133 | 134 | if (::IsWindowVisible(mainWindow)) 135 | { 136 | // 全体の音声波形を再計算する。 137 | recalcTotals(); 138 | } 139 | 140 | return TRUE; 141 | } 142 | 143 | BOOL App::setAudioParams(const AudioParamsPtr& params) 144 | { 145 | MY_TRACE(_T("App::setAudioParams()\n")); 146 | 147 | MY_TRACE_STR(params->fileName); 148 | MY_TRACE_HEX(params->id); 149 | MY_TRACE_HEX(params->flag); 150 | MY_TRACE_INT(params->frameBegin); 151 | MY_TRACE_INT(params->frameEnd); 152 | MY_TRACE_INT(params->sceneSet); 153 | MY_TRACE_REAL(params->volume); 154 | MY_TRACE_INT(params->playBegin); 155 | MY_TRACE_REAL(params->playSpeed); 156 | 157 | if (params->flag & (uint32_t)ExEdit::Object::Flag::Exist) 158 | audioParamsMap[params->id] = params; 159 | else 160 | audioParamsMap.erase(params->id); 161 | 162 | if (::IsWindowVisible(mainWindow)) 163 | { 164 | // 全体の音声波形を再計算する。 165 | recalcTotals(); 166 | } 167 | 168 | return TRUE; 169 | } 170 | 171 | BOOL App::setTotalsParams(const TotalsParamsPtr& params) 172 | { 173 | MY_TRACE(_T("App::setTotalsParams()\n")); 174 | 175 | MY_TRACE_INT(params->showBPM); 176 | MY_TRACE_INT(params->tempo.orig); 177 | MY_TRACE_INT(params->tempo.bpm); 178 | MY_TRACE_INT(params->tempo.above); 179 | MY_TRACE_INT(params->tempo.below); 180 | 181 | setShowBPM(params->showBPM); 182 | setOrig(params->tempo.orig); 183 | setBPM(params->tempo.bpm); 184 | setAbove(params->tempo.above); 185 | setBelow(params->tempo.below); 186 | mainWindow.updateShared(); 187 | 188 | if (::IsWindowVisible(mainWindow)) 189 | { 190 | // 全体の音声波形を再描画する。 191 | mainWindow.redraw(); 192 | } 193 | 194 | return TRUE; 195 | } 196 | 197 | //-------------------------------------------------------------------- 198 | -------------------------------------------------------------------------------- /OutProcess/CacheManager.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "CacheManager.h" 3 | #include "App.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | CachePtr CacheManager::getCache(LPCSTR fileName) 8 | { 9 | MY_TRACE(_T("CacheManager::getCache(%hs)\n"), fileName); 10 | 11 | auto it = cacheMap.find(fileName); 12 | if (it == cacheMap.end()) return 0; 13 | return it->second; 14 | } 15 | 16 | // リーダーがボトルに詰め込んだ音量からキャッシュを作成する。 17 | CachePtr CacheManager::createCache(const ReaderPtr& reader) 18 | { 19 | MY_TRACE(_T("CacheManager::createCache()\n")); 20 | 21 | ReaderBottle* shared = reader->getBottle(); 22 | if (!shared) return 0; 23 | 24 | MY_TRACE_STR(shared->fileName); 25 | 26 | CachePtr cache = std::make_shared(); 27 | cache->fileName = shared->fileName; 28 | cache->volumes.insert(cache->volumes.end(), 29 | shared->volumes, shared->volumes + shared->volumeCount); 30 | cacheMap[cache->fileName] = cache; 31 | return cache; 32 | } 33 | 34 | void CacheManager::clear() 35 | { 36 | cacheMap.clear(); 37 | } 38 | 39 | //-------------------------------------------------------------------- 40 | -------------------------------------------------------------------------------- /OutProcess/CacheManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "OutProcess.h" 4 | #include "ReaderManager.h" 5 | 6 | //-------------------------------------------------------------------- 7 | 8 | struct Cache { 9 | std::string fileName; 10 | std::vector volumes; 11 | }; 12 | 13 | typedef std::shared_ptr CachePtr; 14 | typedef std::map CacheMap; 15 | 16 | //-------------------------------------------------------------------- 17 | 18 | struct CacheManager { 19 | CacheMap cacheMap; 20 | 21 | CachePtr getCache(LPCSTR fileName); 22 | CachePtr createCache(const ReaderPtr& reader); 23 | void clear(); 24 | }; 25 | 26 | //-------------------------------------------------------------------- 27 | -------------------------------------------------------------------------------- /OutProcess/Design.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "OutProcess.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | struct XYWHRect 8 | { 9 | int x, y, w, h; 10 | 11 | XYWHRect() 12 | { 13 | x = y = w = h = 0; 14 | } 15 | 16 | XYWHRect(int x, int y, int w, int h) 17 | { 18 | this->x = x; 19 | this->y = y; 20 | this->w = w; 21 | this->h = h; 22 | } 23 | 24 | XYWHRect(const RECT& rc) 25 | { 26 | operator=(rc); 27 | } 28 | 29 | XYWHRect& operator=(const RECT& rc) 30 | { 31 | this->x = rc.left; 32 | this->y = rc.top; 33 | this->w = getWidth(rc); 34 | this->h = getHeight(rc); 35 | 36 | return *this; 37 | } 38 | }; 39 | 40 | struct MyColor : public NVGcolor 41 | { 42 | MyColor() 43 | { 44 | } 45 | 46 | MyColor(DWORD color) 47 | { 48 | this->r = GetRValue(color) / 255.0f; 49 | this->g = GetGValue(color) / 255.0f; 50 | this->b = GetBValue(color) / 255.0f; 51 | this->a = GetAValue(color) / 255.0f; 52 | } 53 | 54 | operator DWORD() 55 | { 56 | BYTE r = (BYTE)roundf(this->r * 255.0f); 57 | BYTE g = (BYTE)roundf(this->g * 255.0f); 58 | BYTE b = (BYTE)roundf(this->b * 255.0f); 59 | BYTE a = (BYTE)roundf(this->a * 255.0f); 60 | 61 | return getDWORD(r, g, b, a); 62 | } 63 | 64 | MyColor& operator=(const NVGcolor& color) 65 | { 66 | ((NVGcolor&)*this) = color; 67 | 68 | return *this; 69 | } 70 | 71 | static BYTE GetAValue(DWORD color) 72 | { 73 | return LOBYTE(color >> 24); 74 | } 75 | 76 | static COLORREF getCOLORREF(DWORD rgba) 77 | { 78 | return (rgba & 0x00FFFFFF); 79 | } 80 | 81 | static DWORD getDWORD(BYTE r, BYTE g, BYTE b, BYTE a) 82 | { 83 | return r | ((WORD)g << 8) | ((DWORD)b << 16) | ((DWORD)a << 24); 84 | } 85 | 86 | static DWORD getDWORD(COLORREF color, DWORD rgba) 87 | { 88 | return (color & 0x00FFFFFF) | (rgba & 0xFF000000); 89 | } 90 | }; 91 | 92 | struct StringU8 93 | { 94 | char m_buffer[MAX_PATH] = {}; 95 | 96 | StringU8() 97 | { 98 | } 99 | 100 | StringU8(LPCWSTR x) 101 | { 102 | operator=(x); 103 | } 104 | 105 | StringU8& operator=(LPCWSTR x) 106 | { 107 | ::WideCharToMultiByte(CP_UTF8, 0, x, -1, m_buffer, MAX_PATH, 0, 0); 108 | return *this; 109 | } 110 | 111 | operator LPCSTR() const 112 | { 113 | return m_buffer; 114 | } 115 | }; 116 | 117 | //-------------------------------------------------------------------- 118 | 119 | struct Design 120 | { 121 | struct AlignX { 122 | static const int left = 0; 123 | static const int right = 1; 124 | static const int center = 2; 125 | static const Label labels[]; 126 | }; 127 | 128 | struct AlignY { 129 | static const int top = 0; 130 | static const int bottom = 1; 131 | static const int center = 2; 132 | static const Label labels[]; 133 | }; 134 | 135 | struct ScaleMode { 136 | static const int normal = 0; 137 | static const int fit = 1; 138 | static const int crop = 2; 139 | static const Label labels[]; 140 | }; 141 | 142 | struct LineStyle { 143 | static const Label labels[]; 144 | }; 145 | 146 | struct Fill { 147 | MyColor color; 148 | }; 149 | 150 | struct GradientFill { 151 | MyColor color1; 152 | MyColor color2; 153 | }; 154 | 155 | struct Stroke { 156 | int style; 157 | int width; 158 | MyColor color; 159 | }; 160 | 161 | struct Text { 162 | int height; 163 | MyColor color; 164 | struct Shadow { 165 | float dilate; 166 | float blur; 167 | POINT offset; 168 | MyColor color; 169 | } shadow; 170 | }; 171 | 172 | struct Marker { 173 | Stroke stroke; 174 | }; 175 | 176 | _bstr_t fontDefault; 177 | _bstr_t fontDefault2; 178 | struct Image { 179 | _bstr_t fileName; 180 | POINT offset; 181 | POINT align; 182 | int scaleMode; 183 | float scale; 184 | float angle; 185 | float alpha; 186 | } image; 187 | struct Background { 188 | GradientFill fill; 189 | } background; 190 | struct Body { 191 | struct Margin { 192 | int x; 193 | int y; 194 | } margin; 195 | Stroke stroke; 196 | } body; 197 | struct Scale { 198 | struct Horz { 199 | int minUnitWidth; 200 | struct Primary { 201 | int height; 202 | Stroke stroke; 203 | Text text; 204 | } primary; 205 | struct Secondary { 206 | int height; 207 | Stroke stroke; 208 | } secondary; 209 | } horz; 210 | struct Vert { 211 | int width; 212 | Text text; 213 | Stroke stroke; 214 | struct Base { 215 | Stroke stroke; 216 | } base; 217 | } vert; 218 | } scale; 219 | struct BPM { 220 | struct Primary { 221 | Stroke stroke; 222 | Text text; 223 | } primary; 224 | struct Secondary { 225 | Stroke stroke; 226 | } secondary; 227 | } bpm; 228 | struct Graph { 229 | GradientFill fill; 230 | Stroke stroke; 231 | Marker current; 232 | Marker hot; 233 | Marker last; 234 | } graph; 235 | 236 | Design(); 237 | ~Design(); 238 | 239 | void load(LPCWSTR fileName); 240 | void save(LPCWSTR fileName); 241 | }; 242 | 243 | extern Design g_design; 244 | 245 | //-------------------------------------------------------------------- 246 | -------------------------------------------------------------------------------- /OutProcess/MainDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MainDialog.h" 3 | #include "App.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | BOOL MainDialog::getShowBPM() 8 | { 9 | HWND showBPM = ::GetDlgItem(*this, IDC_SHOW_BPM); 10 | return Button_GetCheck(showBPM) == BST_CHECKED; 11 | } 12 | 13 | BOOL MainDialog::setShowBPM(BOOL newShowBPM) 14 | { 15 | HWND showBPM = ::GetDlgItem(*this, IDC_SHOW_BPM); 16 | Button_SetCheck(showBPM, newShowBPM ? BST_CHECKED : BST_UNCHECKED); 17 | return TRUE; 18 | } 19 | 20 | int MainDialog::getOrig() 21 | { 22 | return ::GetDlgItemInt(*this, IDC_ORIG, 0, TRUE); 23 | } 24 | 25 | BOOL MainDialog::setOrig(int newOrig) 26 | { 27 | return ::SetDlgItemInt(*this, IDC_ORIG, newOrig, TRUE); 28 | } 29 | 30 | int MainDialog::getBPM() 31 | { 32 | return ::GetDlgItemInt(*this, IDC_BPM, 0, TRUE); 33 | } 34 | 35 | BOOL MainDialog::setBPM(int newBPM) 36 | { 37 | return ::SetDlgItemInt(*this, IDC_BPM, newBPM, TRUE); 38 | } 39 | 40 | int MainDialog::getAbove() 41 | { 42 | return ::GetDlgItemInt(*this, IDC_ABOVE, 0, TRUE); 43 | } 44 | 45 | BOOL MainDialog::setAbove(int newAbove) 46 | { 47 | return ::SetDlgItemInt(*this, IDC_ABOVE, newAbove, TRUE); 48 | } 49 | 50 | int MainDialog::getBelow() 51 | { 52 | return ::GetDlgItemInt(*this, IDC_BELOW, 0, TRUE); 53 | } 54 | 55 | BOOL MainDialog::setBelow(int newBelow) 56 | { 57 | return ::SetDlgItemInt(*this, IDC_BELOW, newBelow, TRUE); 58 | } 59 | 60 | int MainDialog::getLimitVolume() 61 | { 62 | return ::GetDlgItemInt(*this, IDC_LIMIT_VOLUME, 0, TRUE); 63 | } 64 | 65 | BOOL MainDialog::setLimitVolume(int newLimitVolume) 66 | { 67 | return ::SetDlgItemInt(*this, IDC_LIMIT_VOLUME, newLimitVolume, TRUE); 68 | } 69 | 70 | int MainDialog::getBaseVolume() 71 | { 72 | return ::GetDlgItemInt(*this, IDC_BASE_VOLUME, 0, TRUE); 73 | } 74 | 75 | BOOL MainDialog::setBaseVolume(int newBaseVolume) 76 | { 77 | return ::SetDlgItemInt(*this, IDC_BASE_VOLUME, newBaseVolume, TRUE); 78 | } 79 | 80 | int MainDialog::getMinRMS() 81 | { 82 | return ::GetDlgItemInt(*this, IDC_MIN_RMS, 0, TRUE); 83 | } 84 | 85 | BOOL MainDialog::setMinRMS(int newMinRMS) 86 | { 87 | return ::SetDlgItemInt(*this, IDC_MIN_RMS, newMinRMS, TRUE); 88 | } 89 | 90 | int MainDialog::getMaxRMS() 91 | { 92 | return ::GetDlgItemInt(*this, IDC_MAX_RMS, 0, TRUE); 93 | } 94 | 95 | BOOL MainDialog::setMaxRMS(int newMaxRMS) 96 | { 97 | return ::SetDlgItemInt(*this, IDC_MAX_RMS, newMaxRMS, TRUE); 98 | } 99 | 100 | int MainDialog::getBaseRMS() 101 | { 102 | return ::GetDlgItemInt(*this, IDC_BASE_RMS, 0, TRUE); 103 | } 104 | 105 | BOOL MainDialog::setBaseRMS(int newBaseRMS) 106 | { 107 | return ::SetDlgItemInt(*this, IDC_BASE_RMS, newBaseRMS, TRUE); 108 | } 109 | 110 | int MainDialog::getZoom() 111 | { 112 | return ::GetDlgItemInt(*this, IDC_ZOOM, 0, TRUE); 113 | } 114 | 115 | BOOL MainDialog::setZoom(int newZoom) 116 | { 117 | return ::SetDlgItemInt(*this, IDC_ZOOM, newZoom, TRUE); 118 | } 119 | 120 | //-------------------------------------------------------------------- 121 | 122 | BOOL MainDialog::create(HINSTANCE instance, HWND parent) 123 | { 124 | MY_TRACE(_T("MainDialog::create()\n")); 125 | 126 | // メインダイアログを作成する。 127 | 128 | if (!Dialog::create(instance, MAKEINTRESOURCE(IDD_CONFIG_DIALOG), parent)) 129 | { 130 | ::MessageBox(parent, _T("メインダイアログの作成に失敗しました"), _T("ShowWaveform"), MB_OK); 131 | 132 | return FALSE; 133 | } 134 | 135 | // コントロールを初期化する。 136 | 137 | ignoreNotification(TRUE); 138 | 139 | setShowBPM(theApp.getShowBPM()); 140 | setOrig(theApp.getOrig()); 141 | setBPM(theApp.getBPM()); 142 | setAbove(theApp.getAbove()); 143 | setBelow(theApp.getBelow()); 144 | 145 | setLimitVolume(theApp.getLimitVolume()); 146 | setBaseVolume(theApp.getBaseVolume()); 147 | setMinRMS(theApp.getMinRMS()); 148 | setMaxRMS(theApp.getMaxRMS()); 149 | setBaseRMS(theApp.getBaseRMS()); 150 | setZoom(theApp.getZoom()); 151 | 152 | ignoreNotification(FALSE); 153 | 154 | return TRUE; 155 | } 156 | 157 | void MainDialog::ignoreNotification(BOOL ignoreNotification) 158 | { 159 | m_ignoreNotification = ignoreNotification; 160 | } 161 | 162 | INT_PTR MainDialog::onDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 163 | { 164 | switch (message) 165 | { 166 | case WM_COMMAND: 167 | { 168 | MY_TRACE(_T("MainDialog::onDlgProc(WM_COMMAND, 0x%08X, 0x%08X)\n"), wParam, lParam); 169 | 170 | // App のセッターを使用するとダイアログが再更新されてしまうので 171 | // メインウィンドウのセッターを使用する。 172 | 173 | UINT code = HIWORD(wParam); 174 | UINT id = LOWORD(wParam); 175 | HWND sender = (HWND)lParam; 176 | 177 | switch (id) 178 | { 179 | case IDC_SHOW_BPM: 180 | { 181 | theApp.mainWindow.setShowBPM(getShowBPM()); 182 | 183 | break; 184 | } 185 | case IDC_ORIG: 186 | { 187 | if (code == EN_UPDATE && !m_ignoreNotification) 188 | theApp.mainWindow.setOrig(getOrig()); 189 | 190 | break; 191 | } 192 | case IDC_BPM: 193 | { 194 | if (code == EN_UPDATE && !m_ignoreNotification) 195 | theApp.mainWindow.setBPM(getBPM()); 196 | 197 | break; 198 | } 199 | case IDC_ABOVE: 200 | { 201 | if (code == EN_UPDATE && !m_ignoreNotification) 202 | theApp.mainWindow.setAbove(getAbove()); 203 | 204 | break; 205 | } 206 | case IDC_BELOW: 207 | { 208 | if (code == EN_UPDATE && !m_ignoreNotification) 209 | theApp.mainWindow.setBelow(getBelow()); 210 | 211 | break; 212 | } 213 | case IDC_LIMIT_VOLUME: 214 | { 215 | if (code == EN_UPDATE && !m_ignoreNotification) 216 | theApp.mainWindow.setLimitVolume(getLimitVolume()); 217 | 218 | break; 219 | } 220 | case IDC_BASE_VOLUME: 221 | { 222 | if (code == EN_UPDATE && !m_ignoreNotification) 223 | theApp.mainWindow.setBaseVolume(getBaseVolume()); 224 | 225 | break; 226 | } 227 | case IDC_MIN_RMS: 228 | { 229 | if (code == EN_UPDATE && !m_ignoreNotification) 230 | theApp.mainWindow.setMinRMS(getMinRMS()); 231 | 232 | break; 233 | } 234 | case IDC_MAX_RMS: 235 | { 236 | if (code == EN_UPDATE && !m_ignoreNotification) 237 | theApp.mainWindow.setMaxRMS(getMaxRMS()); 238 | 239 | break; 240 | } 241 | case IDC_BASE_RMS: 242 | { 243 | if (code == EN_UPDATE && !m_ignoreNotification) 244 | theApp.mainWindow.setBaseRMS(getBaseRMS()); 245 | 246 | break; 247 | } 248 | case IDC_ZOOM: 249 | { 250 | if (code == EN_UPDATE && !m_ignoreNotification) 251 | theApp.mainWindow.setZoom(getZoom()); 252 | 253 | break; 254 | } 255 | } 256 | 257 | break; 258 | } 259 | case WM_NOTIFY: 260 | { 261 | MY_TRACE(_T("MainDialog::onDlgProc(WM_NOTIFY, 0x%08X, 0x%08X)\n"), wParam, lParam); 262 | 263 | NMHDR* header = (NMHDR*)lParam; 264 | if (header->code == UDN_DELTAPOS) 265 | { 266 | int value = ::GetDlgItemInt(hwnd, header->idFrom - 1, 0, TRUE); 267 | 268 | NM_UPDOWN* nm = (NM_UPDOWN*)header; 269 | if (nm->iDelta < 0) 270 | { 271 | value += 1; 272 | } 273 | else 274 | { 275 | value -= 1; 276 | } 277 | 278 | ::SetDlgItemInt(hwnd, header->idFrom - 1, value, TRUE); 279 | } 280 | 281 | break; 282 | } 283 | } 284 | 285 | if (message == WM_AVIUTL_FILTER_RESIZE) return onAviUtlFilterResize(hwnd, message, wParam, lParam); 286 | 287 | return Dialog::onDlgProc(hwnd, message, wParam, lParam); 288 | } 289 | 290 | LRESULT MainDialog::onAviUtlFilterResize(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 291 | { 292 | MY_TRACE(_T("onAviUtlFilterResize(0x%08X, 0x%08X)\n"), wParam, lParam); 293 | 294 | HWND parent = ::GetParent(hwnd); 295 | RECT rc; ::GetClientRect(parent, &rc); 296 | MY_TRACE_RECT2(rc); 297 | ::SetWindowPos(hwnd, 0, rc.left, rc.top, getWidth(rc), getHeight(rc), SWP_NOZORDER); 298 | 299 | return 0; 300 | } 301 | 302 | //-------------------------------------------------------------------- 303 | -------------------------------------------------------------------------------- /OutProcess/MainDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Resource.h" 3 | 4 | struct MainDialog : public Tools::Dialog 5 | { 6 | BOOL m_ignoreNotification = FALSE; 7 | 8 | BOOL getShowBPM(); 9 | BOOL setShowBPM(BOOL newShowBPM); 10 | int getOrig(); 11 | BOOL setOrig(int newOrig); 12 | int getBPM(); 13 | BOOL setBPM(int newBPM); 14 | int getAbove(); 15 | BOOL setAbove(int newAbove); 16 | int getBelow(); 17 | BOOL setBelow(int newBelow); 18 | 19 | int getLimitVolume(); 20 | BOOL setLimitVolume(int newLimitVolume); 21 | int getBaseVolume(); 22 | BOOL setBaseVolume(int newBaseVolume); 23 | int getMinRMS(); 24 | BOOL setMinRMS(int newMinRMS); 25 | int getMaxRMS(); 26 | BOOL setMaxRMS(int newMaxRMS); 27 | int getBaseRMS(); 28 | BOOL setBaseRMS(int newBaseRMS); 29 | int getZoom(); 30 | BOOL setZoom(int newZoom); 31 | 32 | BOOL create(HINSTANCE instance, HWND parent); 33 | void ignoreNotification(BOOL ignoreNotification); 34 | virtual INT_PTR onDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 35 | LRESULT onAviUtlFilterResize(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 36 | }; 37 | -------------------------------------------------------------------------------- /OutProcess/MainWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "OutProcess.h" 4 | #include "Design.h" 5 | #include "Mode.h" 6 | 7 | //-------------------------------------------------------------------- 8 | 9 | struct MakeCurrent 10 | { 11 | HDC m_prevDC = 0; 12 | HGLRC m_prevRC = 0; 13 | 14 | MakeCurrent(HDC dc, HGLRC rc) 15 | { 16 | m_prevDC = wglGetCurrentDC(); 17 | m_prevRC = wglGetCurrentContext(); 18 | 19 | wglMakeCurrent(dc, rc); 20 | } 21 | 22 | ~MakeCurrent() 23 | { 24 | wglMakeCurrent(m_prevDC, m_prevRC); 25 | } 26 | }; 27 | 28 | struct LayoutContext { 29 | RECT rc; 30 | int x, y, w, h; 31 | int hScroll; 32 | struct Graph { 33 | int x, y, w, h; 34 | int left, right, top, bottom; 35 | } graph; 36 | int padding; 37 | double zoomScale; 38 | }; 39 | 40 | //-------------------------------------------------------------------- 41 | 42 | struct MainWindow 43 | { 44 | struct CommandID { 45 | struct Mode { 46 | static const UINT rms = 1000; 47 | static const UINT center = 1001; 48 | static const UINT bottomUp = 1002; 49 | static const UINT topDown = 1003; 50 | }; 51 | struct HorzScale { 52 | struct VisibleStyle { 53 | static const UINT both = 2000; 54 | static const UINT top = 2001; 55 | static const UINT bottom = 2002; 56 | }; 57 | struct LineStyle { 58 | static const UINT side = 2100; 59 | static const UINT straight = 2101; 60 | }; 61 | }; 62 | struct VertScale { 63 | struct VisibleStyle { 64 | static const UINT both = 3000; 65 | static const UINT left = 3001; 66 | static const UINT right = 3002; 67 | }; 68 | struct LineStyle { 69 | static const UINT side = 3100; 70 | static const UINT straight = 3101; 71 | }; 72 | }; 73 | static const UINT showMainDialog = 4000; 74 | }; 75 | 76 | struct TimerID { 77 | static const UINT checkConfig = 1000; 78 | }; 79 | 80 | struct Mode { 81 | static const int rms = 0; 82 | static const int center = 1; 83 | static const int bottomUp = 2; 84 | static const int topDown = 3; 85 | static const Label labels[]; 86 | }; 87 | 88 | struct HorzScaleSettings { 89 | struct VisibleStyle { 90 | static const int both = 0; 91 | static const int top = 1; 92 | static const int bottom = 2; 93 | static const Label labels[]; 94 | }; 95 | struct LineStyle { 96 | static const int side = 0; 97 | static const int straight = 1; 98 | static const Label labels[]; 99 | }; 100 | int visibleStyle; 101 | int lineStyle; 102 | }; 103 | 104 | struct VertScaleSettings { 105 | struct VisibleStyle { 106 | static const int both = 0; 107 | static const int left = 1; 108 | static const int right = 2; 109 | static const Label labels[]; 110 | }; 111 | struct LineStyle { 112 | static const int side = 0; 113 | static const int straight = 1; 114 | static const Label labels[]; 115 | }; 116 | int visibleStyle; 117 | int lineStyle; 118 | }; 119 | 120 | struct HitTest { 121 | static const int None = 0; 122 | static const int HorzScale = 1; 123 | static const int VertScaleMin = 2; 124 | static const int VertScaleMax = 3; 125 | }; 126 | 127 | int m_limitVolume = 100; 128 | int m_baseVolume = 50; 129 | int m_minRMS = -33; 130 | int m_maxRMS = 14; 131 | int m_baseRMS = 0; 132 | int m_zoom = 0; // グラフの論理幅を増加させる。 133 | HorzScaleSettings m_horzScaleSettings = { 134 | HorzScaleSettings::VisibleStyle::both, 135 | HorzScaleSettings::LineStyle::side, 136 | }; 137 | VertScaleSettings m_vertScaleSettings = { 138 | VertScaleSettings::VisibleStyle::both, 139 | VertScaleSettings::LineStyle::straight, 140 | }; 141 | TotalsParams m_totalsParams; 142 | ModePtr m_mode = std::make_shared(); 143 | 144 | int m_hotFrame = 0; 145 | struct Drag { 146 | int ht = HitTest::None; 147 | POINT origPoint = {}; 148 | int origValue = 0; 149 | } drag; 150 | 151 | BOOL getShowBPM(); 152 | BOOL setShowBPM(BOOL newShowBPM); 153 | int getOrig(); 154 | BOOL setOrig(int newOrig); 155 | int getBPM(); 156 | BOOL setBPM(int newBPM); 157 | int getAbove(); 158 | BOOL setAbove(int newAbove); 159 | int getBelow(); 160 | BOOL setBelow(int newBelow); 161 | 162 | int getLimitVolume(); 163 | BOOL setLimitVolume(int newLimitVolume); 164 | int getBaseVolume(); 165 | BOOL setBaseVolume(int newBaseVolume); 166 | int getMinRMS(); 167 | BOOL setMinRMS(int newMinRMS); 168 | int getMaxRMS(); 169 | BOOL setMaxRMS(int newMaxRMS); 170 | int getBaseRMS(); 171 | BOOL setBaseRMS(int newBaseRMS); 172 | int getZoom(); 173 | BOOL setZoom(int newZoom); 174 | ModePtr getMode(); 175 | int getHotFrame(); 176 | BOOL setHotFrame(int newHotFrame); 177 | BOOL updateShared(); 178 | 179 | // Layout 180 | 181 | double getZoomScale(); 182 | BOOL getLayoutContext(LayoutContext& context); 183 | BOOL getLayoutContext(LayoutContext& context, const RECT& rc); 184 | void recalcLayout(); 185 | int hitTest(POINT point); 186 | int client2frame(int x); 187 | int client2frame(const LayoutContext& context, int x); 188 | int frame2client(int frame); 189 | int frame2client(const LayoutContext& context, int frame); 190 | int sec2frame(double sec); 191 | double frame2sec(int frame); 192 | static int sec2px(double zoomScale, double sec); 193 | static double px2sec(double zoomScale, int px); 194 | static double getUnitSec(double zoomScale); 195 | void outputFrames(); 196 | 197 | // Config 198 | 199 | FileUpdateCheckerPtr m_configFileChecker; 200 | BOOL initConfig(); 201 | BOOL termConfig(); 202 | void reloadConfig(); 203 | void recalcConfig(); 204 | void recalcConfigInternal(); 205 | LRESULT onTimerCheckConfig(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 206 | void load(LPCWSTR fileName); 207 | void save(LPCWSTR fileName); 208 | 209 | // OpenGL & NanoVG 210 | 211 | HGLRC m_rc = 0; 212 | NVGcontext* m_vg = 0; 213 | int m_fontDefault = 0; 214 | int m_fontDefault2 = 0; 215 | int m_image = 0; 216 | static BOOL setupPixelFormat(HDC dc); 217 | BOOL initOpenGL(); 218 | BOOL termOpenGL(); 219 | void doPaint(HDC dc, const RECT& rc); 220 | void doPaint(const RECT& rc); 221 | 222 | // Window 223 | 224 | HWND m_hwnd = 0; 225 | operator HWND() const { return m_hwnd; } 226 | void redraw(); 227 | BOOL create(HINSTANCE instance, HWND parent); 228 | LRESULT onCreate(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 229 | LRESULT onDestroy(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 230 | LRESULT onSize(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 231 | LRESULT onHScroll(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 232 | LRESULT onTimer(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 233 | LRESULT onPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 234 | LRESULT onContextMenu(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 235 | LRESULT onSetCursor(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 236 | LRESULT onMouseMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 237 | LRESULT onMouseWheel(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 238 | LRESULT onLButtonDown(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 239 | LRESULT onLButtonUp(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 240 | LRESULT onAviUtlFilterExit(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 241 | LRESULT onAviUtlFilterResize(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 242 | static LRESULT CALLBACK wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 243 | }; 244 | 245 | //-------------------------------------------------------------------- 246 | -------------------------------------------------------------------------------- /OutProcess/MainWindow_Config.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MainWindow.h" 3 | #include "App.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | const Label MainWindow::HorzScaleSettings::VisibleStyle::labels[] = { 8 | { both, L"both" }, 9 | { top, L"top" }, 10 | { bottom, L"bottom" }, 11 | }; 12 | 13 | const Label MainWindow::HorzScaleSettings::LineStyle::labels[] = { 14 | { side, L"side" }, 15 | { straight, L"straight" }, 16 | }; 17 | 18 | const Label MainWindow::VertScaleSettings::VisibleStyle::labels[] = { 19 | { both, L"both" }, 20 | { left, L"left" }, 21 | { right, L"right" }, 22 | }; 23 | 24 | const Label MainWindow::VertScaleSettings::LineStyle::labels[] = { 25 | { side, L"side" }, 26 | { straight, L"straight" }, 27 | }; 28 | 29 | const Label MainWindow::Mode::labels[] = { 30 | { rms, L"rms" }, 31 | { center, L"center" }, 32 | { bottomUp, L"bottomUp" }, 33 | { topDown, L"topDown" }, 34 | }; 35 | 36 | //-------------------------------------------------------------------- 37 | 38 | BOOL MainWindow::initConfig() 39 | { 40 | MY_TRACE(_T("MainWindow::initConfig()\n")); 41 | 42 | WCHAR fileName[MAX_PATH] = {}; 43 | ::GetModuleFileNameW(theApp.instance, fileName, MAX_PATH); 44 | ::PathRemoveFileSpecW(fileName); 45 | ::PathAppendW(fileName, _T("Config.ini")); 46 | MY_TRACE_WSTR(fileName); 47 | 48 | m_configFileChecker = std::make_shared(fileName); 49 | ::SetTimer(m_hwnd, TimerID::checkConfig, 1000, 0); // 1 秒に 1 回コンフィグファイルをチェックする。 50 | reloadConfig(); 51 | 52 | return TRUE; 53 | } 54 | 55 | BOOL MainWindow::termConfig() 56 | { 57 | MY_TRACE(_T("MainWindow::termConfig()\n")); 58 | 59 | ::KillTimer(m_hwnd, TimerID::checkConfig); 60 | 61 | save(m_configFileChecker->getFilePath()); 62 | 63 | return TRUE; 64 | } 65 | 66 | void MainWindow::reloadConfig() 67 | { 68 | MY_TRACE(_T("MainWindow::reloadConfig()\n")); 69 | 70 | load(m_configFileChecker->getFilePath()); 71 | 72 | recalcConfig(); 73 | } 74 | 75 | void MainWindow::recalcConfig() 76 | { 77 | MY_TRACE(_T("MainWindow::recalcConfig()\n")); 78 | 79 | ClientDC dc(m_hwnd); 80 | MakeCurrent makeCurrent(dc, m_rc); 81 | 82 | recalcConfigInternal(); 83 | } 84 | 85 | void MainWindow::recalcConfigInternal() 86 | { 87 | MY_TRACE(_T("MainWindow::recalcConfigInternal()\n")); 88 | 89 | MY_TRACE_WSTR((BSTR)g_design.fontDefault); 90 | m_fontDefault = nvgCreateFont(m_vg, "default", StringU8(g_design.fontDefault)); 91 | MY_TRACE_INT(m_fontDefault); 92 | 93 | MY_TRACE_WSTR((BSTR)g_design.fontDefault2); 94 | m_fontDefault2 = nvgCreateFont(m_vg, "default2", StringU8(g_design.fontDefault2)); 95 | MY_TRACE_INT(m_fontDefault2); 96 | 97 | nvgAddFallbackFontId(m_vg, m_fontDefault, m_fontDefault2); 98 | 99 | if (m_image) nvgDeleteImage(m_vg, m_image); 100 | m_image = nvgCreateImage(m_vg, g_design.image.fileName, NVG_IMAGE_NEAREST); 101 | MY_TRACE_INT(m_image); 102 | } 103 | 104 | LRESULT MainWindow::onTimerCheckConfig(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 105 | { 106 | if (m_configFileChecker->isFileUpdated()) 107 | { 108 | reloadConfig(); 109 | redraw(); 110 | } 111 | 112 | return 0; 113 | } 114 | 115 | void MainWindow::load(LPCWSTR fileName) 116 | { 117 | MY_TRACE(_T("MainWindow::load(%ws)\n"), fileName); 118 | 119 | int mode = m_mode->getID(); 120 | 121 | getPrivateProfileInt(fileName, L"Config", L"maxReaderCount", theApp.readerManager.maxReaderCount); 122 | getPrivateProfileInt(fileName, L"Config", L"limitVolume", m_limitVolume); 123 | getPrivateProfileInt(fileName, L"Config", L"baseVolume", m_baseVolume); 124 | getPrivateProfileInt(fileName, L"Config", L"minRMS", m_minRMS); 125 | getPrivateProfileInt(fileName, L"Config", L"maxRMS", m_maxRMS); 126 | getPrivateProfileInt(fileName, L"Config", L"baseRMS", m_baseRMS); 127 | getPrivateProfileInt(fileName, L"Config", L"zoom", m_zoom); 128 | getPrivateProfileLabel(fileName, L"Config", L"mode", mode, Mode::labels); 129 | getPrivateProfileLabel(fileName, L"Config", L"horzScaleSettings.visibleStyle", m_horzScaleSettings.visibleStyle, HorzScaleSettings::VisibleStyle::labels); 130 | getPrivateProfileLabel(fileName, L"Config", L"horzScaleSettings.lineStyle", m_horzScaleSettings.lineStyle, HorzScaleSettings::LineStyle::labels); 131 | getPrivateProfileLabel(fileName, L"Config", L"vertScaleSettings.visibleStyle", m_vertScaleSettings.visibleStyle, VertScaleSettings::VisibleStyle::labels); 132 | getPrivateProfileLabel(fileName, L"Config", L"vertScaleSettings.lineStyle", m_vertScaleSettings.lineStyle, VertScaleSettings::LineStyle::labels); 133 | 134 | switch (mode) 135 | { 136 | case Mode::rms: m_mode = std::make_shared(); break; 137 | case Mode::center: m_mode = std::make_shared(); break; 138 | case Mode::bottomUp: m_mode = std::make_shared(); break; 139 | case Mode::topDown: m_mode = std::make_shared(); break; 140 | } 141 | 142 | g_design.load(fileName); 143 | } 144 | 145 | void MainWindow::save(LPCWSTR fileName) 146 | { 147 | MY_TRACE(_T("MainWindow::save(%ws)\n"), fileName); 148 | 149 | int mode = m_mode->getID(); 150 | 151 | setPrivateProfileInt(fileName, L"Config", L"maxReaderCount", theApp.readerManager.maxReaderCount); 152 | setPrivateProfileInt(fileName, L"Config", L"limitVolume", m_limitVolume); 153 | setPrivateProfileInt(fileName, L"Config", L"baseVolume", m_baseVolume); 154 | setPrivateProfileInt(fileName, L"Config", L"minRMS", m_minRMS); 155 | setPrivateProfileInt(fileName, L"Config", L"maxRMS", m_maxRMS); 156 | setPrivateProfileInt(fileName, L"Config", L"baseRMS", m_baseRMS); 157 | setPrivateProfileInt(fileName, L"Config", L"zoom", m_zoom); 158 | setPrivateProfileLabel(fileName, L"Config", L"mode", mode, Mode::labels); 159 | setPrivateProfileLabel(fileName, L"Config", L"horzScaleSettings.visibleStyle", m_horzScaleSettings.visibleStyle, HorzScaleSettings::VisibleStyle::labels); 160 | setPrivateProfileLabel(fileName, L"Config", L"horzScaleSettings.lineStyle", m_horzScaleSettings.lineStyle, HorzScaleSettings::LineStyle::labels); 161 | setPrivateProfileLabel(fileName, L"Config", L"vertScaleSettings.visibleStyle", m_vertScaleSettings.visibleStyle, VertScaleSettings::VisibleStyle::labels); 162 | setPrivateProfileLabel(fileName, L"Config", L"vertScaleSettings.lineStyle", m_vertScaleSettings.lineStyle, VertScaleSettings::LineStyle::labels); 163 | 164 | g_design.save(fileName); 165 | } 166 | 167 | //-------------------------------------------------------------------- 168 | -------------------------------------------------------------------------------- /OutProcess/MainWindow_Layout.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MainWindow.h" 3 | #include "App.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | /* 8 | ズーム値からズーム倍率を計算して返す。 9 | 10 | ズーム値は px 単位で、マイナスになることもあるが、 11 | ズーム倍率は 0.0 より大きい数値になる。 12 | */ 13 | double MainWindow::getZoomScale() 14 | { 15 | return std::pow(2.0, (double)m_zoom / g_design.scale.horz.minUnitWidth); 16 | } 17 | 18 | BOOL MainWindow::getLayoutContext(LayoutContext& context) 19 | { 20 | RECT rc; ::GetClientRect(m_hwnd, &rc); 21 | return getLayoutContext(context, rc); 22 | } 23 | 24 | BOOL MainWindow::getLayoutContext(LayoutContext& context, const RECT& rc) 25 | { 26 | context.rc = rc; 27 | context.x = rc.left; 28 | context.y = rc.top; 29 | context.w = getWidth(rc); 30 | context.h = getHeight(rc); 31 | 32 | if (context.w <= 0 || context.h <= 0) return FALSE; 33 | 34 | context.hScroll = ::GetScrollPos(m_hwnd, SB_HORZ); 35 | 36 | switch (m_vertScaleSettings.visibleStyle) 37 | { 38 | case VertScaleSettings::VisibleStyle::left: 39 | { 40 | context.graph.x = (int)(context.x + g_design.body.margin.x); 41 | context.graph.w = (int)(context.w - g_design.body.margin.x); 42 | break; 43 | } 44 | case VertScaleSettings::VisibleStyle::right: 45 | { 46 | context.graph.x = (int)(context.x); 47 | context.graph.w = (int)(context.w - g_design.body.margin.x); 48 | break; 49 | } 50 | case VertScaleSettings::VisibleStyle::both: 51 | { 52 | context.graph.x = (int)(context.x + g_design.body.margin.x); 53 | context.graph.w = (int)(context.w - g_design.body.margin.x * 2); 54 | break; 55 | } 56 | } 57 | 58 | switch (m_horzScaleSettings.visibleStyle) 59 | { 60 | case HorzScaleSettings::VisibleStyle::top: 61 | { 62 | context.graph.y = (int)(context.y + g_design.body.margin.y); 63 | context.graph.h = (int)(context.h - g_design.body.margin.y); 64 | break; 65 | } 66 | case HorzScaleSettings::VisibleStyle::bottom: 67 | { 68 | context.graph.y = (int)(context.y); 69 | context.graph.h = (int)(context.h - g_design.body.margin.y); 70 | break; 71 | } 72 | case HorzScaleSettings::VisibleStyle::both: 73 | { 74 | context.graph.y = (int)(context.y + g_design.body.margin.y); 75 | context.graph.h = (int)(context.h - g_design.body.margin.y * 2); 76 | break; 77 | } 78 | } 79 | 80 | context.graph.left = context.graph.x; 81 | context.graph.right = context.graph.x + context.graph.w; 82 | context.graph.top = context.graph.y; 83 | context.graph.bottom = context.graph.y + context.graph.h; 84 | context.padding = 10; 85 | 86 | if (context.graph.w <= 0 || context.graph.h <= 0) return FALSE; 87 | 88 | context.zoomScale = getZoomScale(); 89 | 90 | return TRUE; 91 | } 92 | 93 | //-------------------------------------------------------------------- 94 | 95 | void MainWindow::recalcLayout() 96 | { 97 | MY_TRACE(_T("MainWindow::recalcLayout()\n")); 98 | 99 | int c = (int)theApp.totals.size(); 100 | if (c <= 1) return; 101 | 102 | LayoutContext context = {}; 103 | if (!getLayoutContext(context)) return; 104 | 105 | double sec = frame2sec(c - 1); 106 | int logicalWidth = sec2px(context.zoomScale, sec); 107 | 108 | SCROLLINFO si = { sizeof(si) }; 109 | si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; 110 | ::GetScrollInfo(m_hwnd, SB_HORZ, &si); 111 | 112 | double pos = 0.0; 113 | int div = si.nMax - std::max((int)si.nPage - 1, 0); 114 | if (div) 115 | pos = (double)si.nPos / div; 116 | 117 | si.nPos = (int)(pos * (logicalWidth - context.graph.w)); 118 | si.nMin = 0; 119 | si.nMax = logicalWidth; 120 | si.nPage = context.graph.w + 1; 121 | ::SetScrollInfo(m_hwnd, SB_HORZ, &si, TRUE); 122 | } 123 | 124 | int MainWindow::hitTest(POINT point) 125 | { 126 | RECT rc; ::GetClientRect(*this, &rc); 127 | int cy = getCenterY(rc); 128 | 129 | if (m_horzScaleSettings.visibleStyle != HorzScaleSettings::VisibleStyle::bottom) 130 | { 131 | if (point.y < rc.top + g_design.body.margin.y) 132 | return HitTest::HorzScale; 133 | } 134 | 135 | if (m_horzScaleSettings.visibleStyle != HorzScaleSettings::VisibleStyle::top) 136 | { 137 | if (point.y > rc.bottom - g_design.body.margin.y) 138 | return HitTest::HorzScale; 139 | } 140 | 141 | if (m_vertScaleSettings.visibleStyle != VertScaleSettings::VisibleStyle::right) 142 | { 143 | if (point.x < rc.left + g_design.body.margin.x) 144 | return (point.y > cy) ? HitTest::VertScaleMin : HitTest::VertScaleMax; 145 | } 146 | 147 | if (m_vertScaleSettings.visibleStyle != VertScaleSettings::VisibleStyle::left) 148 | { 149 | if (point.x > rc.right - g_design.body.margin.x) 150 | return (point.y > cy) ? HitTest::VertScaleMin : HitTest::VertScaleMax; 151 | } 152 | 153 | return HitTest::None; 154 | } 155 | 156 | int MainWindow::client2frame(int x) 157 | { 158 | LayoutContext context = {}; 159 | if (!getLayoutContext(context)) return 0; 160 | 161 | return client2frame(context, x); 162 | } 163 | 164 | /* 165 | クライアント座標の x からフレーム番号を取得する。 166 | ・グラフの X 座標が影響する。 167 | ・水平スクロールが影響する。 168 | */ 169 | int MainWindow::client2frame(const LayoutContext& context, int x) 170 | { 171 | double sec = px2sec(context.zoomScale, x + context.hScroll - context.graph.x); 172 | return sec2frame(sec); 173 | } 174 | 175 | int MainWindow::frame2client(int frame) 176 | { 177 | LayoutContext context = {}; 178 | if (!getLayoutContext(context)) return 0; 179 | 180 | return frame2client(context, frame); 181 | } 182 | 183 | /* 184 | フレーム番号からクライアント座標を取得する。 185 | ・グラフの X 座標が影響する。 186 | ・水平スクロールが影響する。 187 | */ 188 | int MainWindow::frame2client(const LayoutContext& context, int frame) 189 | { 190 | double sec = frame2sec(frame); 191 | return sec2px(context.zoomScale, sec) - context.hScroll + context.graph.x; 192 | } 193 | 194 | int MainWindow::sec2frame(double sec) 195 | { 196 | if (!theApp.projectParams) return 0; 197 | 198 | int video_rate = theApp.projectParams->video_rate; 199 | int video_scale = theApp.projectParams->video_scale; 200 | 201 | if (video_rate == 0 || video_scale == 0) 202 | return 0; 203 | 204 | return (int)(sec * video_rate / video_scale); 205 | } 206 | 207 | double MainWindow::frame2sec(int frame) 208 | { 209 | if (!theApp.projectParams) return 0; 210 | 211 | int video_rate = theApp.projectParams->video_rate; 212 | int video_scale = theApp.projectParams->video_scale; 213 | 214 | if (video_rate == 0 || video_scale == 0) 215 | return 0; 216 | 217 | return (double)frame * video_scale / video_rate; 218 | } 219 | 220 | int MainWindow::sec2px(double zoomScale, double sec) 221 | { 222 | return (int)(sec * g_design.scale.horz.minUnitWidth * zoomScale); 223 | } 224 | 225 | double MainWindow::px2sec(double zoomScale, int px) 226 | { 227 | return (double)px / g_design.scale.horz.minUnitWidth / zoomScale; 228 | } 229 | 230 | double MainWindow::getUnitSec(double zoomScale) 231 | { 232 | double secMinWidth = px2sec(zoomScale, g_design.scale.horz.minUnitWidth); 233 | double sec = 1.0; 234 | 235 | if (zoomScale > 1.0) 236 | { 237 | // 単位秒は 1 より小さい。 238 | 239 | while (1) 240 | { 241 | const double list[] = 242 | { 243 | 2.0, 244 | 3.0, 245 | 4.0, 246 | 5.0, 247 | 10.0, 248 | }; 249 | 250 | double prev = sec; 251 | 252 | for (int i = 0; i < _countof(list); i++) 253 | { 254 | double temp = sec / list[i]; 255 | 256 | if (temp < secMinWidth) 257 | return prev; 258 | 259 | prev = temp; 260 | } 261 | 262 | sec /= 10.0; 263 | } 264 | } 265 | else 266 | { 267 | // 単位秒は 1 より大きい。 268 | 269 | while (1) 270 | { 271 | const double list[] = 272 | { 273 | 1.0, 274 | 2.0, 275 | 3.0, 276 | 4.0, 277 | 5.0, 278 | 6.0, 279 | }; 280 | 281 | for (int i = 0; i < _countof(list); i++) 282 | { 283 | double temp = sec * list[i]; 284 | 285 | if (temp >= secMinWidth) 286 | return temp; 287 | } 288 | 289 | sec *= 10.0; 290 | } 291 | } 292 | 293 | return sec; 294 | } 295 | 296 | //-------------------------------------------------------------------- 297 | 298 | void MainWindow::outputFrames() 299 | { 300 | MY_TRACE(_T("outputFrames()\n")); 301 | 302 | if (!theApp.projectParams) return; 303 | 304 | TCHAR text[1024] = {}; 305 | 306 | int c = (int)theApp.totals.size(); 307 | int currentFrame = theApp.projectParams->currentFrame; 308 | int hotFrame = getHotFrame(); 309 | 310 | if (currentFrame >= 0 && currentFrame < c) 311 | { 312 | FormatText subText(_T("現在位置 : %.2fdB @%d\r\n"), theApp.totals[currentFrame].rms, currentFrame); 313 | ::StringCbCat(text, sizeof(text), subText); 314 | } 315 | 316 | if (hotFrame >= 0 && hotFrame < c) 317 | { 318 | FormatText subText(_T("マウス位置 : %.2fdB @%d\r\n"), theApp.totals[hotFrame].rms, hotFrame); 319 | ::StringCbCat(text, sizeof(text), subText); 320 | } 321 | 322 | ::SetDlgItemText(theApp.mainDialog, IDC_STATUS, text); 323 | } 324 | 325 | //-------------------------------------------------------------------- 326 | 327 | LRESULT MainWindow::onSize(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 328 | { 329 | MY_TRACE(_T("MainWindow::onSize(0x%08X, 0x%08X)\n"), wParam, lParam); 330 | 331 | recalcLayout(); 332 | 333 | return ::DefWindowProc(hwnd, message, wParam, lParam); 334 | } 335 | 336 | LRESULT MainWindow::onHScroll(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 337 | { 338 | UINT sb = LOWORD(wParam); 339 | // int thumbPos = HIWORD(wParam); 340 | HWND scrollBar = (HWND)lParam; 341 | 342 | SCROLLINFO si = { sizeof(si) }; 343 | si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE | SIF_TRACKPOS; 344 | ::GetScrollInfo(hwnd, SB_HORZ, &si); 345 | 346 | MY_TRACE(_T("MainWindow::onHScroll(%d, %d, 0x%08X)\n"), sb, si.nTrackPos, scrollBar); 347 | 348 | int pos = si.nPos; 349 | 350 | switch (sb) 351 | { 352 | case SB_LEFT: pos = si.nMin; break; 353 | case SB_RIGHT: pos = si.nMax; break; 354 | case SB_LINELEFT: pos = si.nPos - 1; break; 355 | case SB_LINERIGHT: pos = si.nPos + 1; break; 356 | case SB_PAGELEFT: pos = si.nPos - 100; break; 357 | case SB_PAGERIGHT: pos = si.nPos + 100; break; 358 | case SB_THUMBPOSITION: 359 | case SB_THUMBTRACK: pos = si.nTrackPos; break; 360 | } 361 | 362 | int min = 0; 363 | int max = si.nMax - std::max(si.nPage - 1, 0); 364 | 365 | pos = std::max(pos, min); 366 | pos = std::min(pos, max); 367 | 368 | if (si.nPos != pos) 369 | { 370 | si.nPos = pos; 371 | ::SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); 372 | ::InvalidateRect(hwnd, 0, FALSE); 373 | 374 | return TRUE; 375 | } 376 | 377 | return ::DefWindowProc(hwnd, message, wParam, lParam); 378 | } 379 | 380 | //-------------------------------------------------------------------- 381 | -------------------------------------------------------------------------------- /OutProcess/MainWindow_Mouse.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MainWindow.h" 3 | #include "App.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | LRESULT MainWindow::onSetCursor(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 8 | { 9 | // MY_TRACE(_T("MainWindow::onSetCursor(0x%08X, 0x%08X)\n"), wParam, lParam); 10 | 11 | HWND cursorHolder = (HWND)wParam; 12 | 13 | if (cursorHolder == hwnd && LOWORD(lParam) == HTCLIENT) 14 | { 15 | POINT point; ::GetCursorPos(&point); 16 | ::MapWindowPoints(0, hwnd, &point, 1); 17 | 18 | int ht = hitTest(point); 19 | 20 | switch (ht) 21 | { 22 | case HitTest::HorzScale: ::SetCursor(::LoadCursor(0, IDC_SIZEWE)); return TRUE; 23 | case HitTest::VertScaleMin: 24 | case HitTest::VertScaleMax: ::SetCursor(::LoadCursor(0, IDC_SIZENS)); return TRUE; 25 | } 26 | } 27 | 28 | return ::DefWindowProc(hwnd, message, wParam, lParam); 29 | } 30 | 31 | LRESULT MainWindow::onMouseMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 32 | { 33 | // MY_TRACE(_T("MainWindow::onMouseMove(0x%08X, 0x%08X)\n"), wParam, lParam); 34 | 35 | POINT point = LP2PT(lParam); 36 | 37 | if (::GetCapture() == hwnd) 38 | { 39 | // ※ダイアログも更新しないといけないので App のセッターを使用する。 40 | 41 | switch (drag.ht) 42 | { 43 | case MainWindow::HitTest::HorzScale: 44 | { 45 | // zoom をドラッグして変更する。 46 | 47 | int offset = point.x - drag.origPoint.x; 48 | 49 | theApp.setZoom(drag.origValue + offset); 50 | 51 | break; 52 | } 53 | case MainWindow::HitTest::VertScaleMin: 54 | case MainWindow::HitTest::VertScaleMax: 55 | { 56 | // minRMS, maxRMS, limitVolume をドラッグして変更する。 57 | 58 | int offset = (point.y - drag.origPoint.y) / 2; 59 | 60 | switch (getMode()->getID()) 61 | { 62 | case Mode::rms: 63 | { 64 | if (drag.ht == MainWindow::HitTest::VertScaleMin) 65 | theApp.setMinRMS(drag.origValue + offset); 66 | else 67 | theApp.setMaxRMS(drag.origValue + offset); 68 | 69 | break; 70 | } 71 | case Mode::center: 72 | { 73 | if (drag.ht == MainWindow::HitTest::VertScaleMin) 74 | theApp.setLimitVolume(drag.origValue - offset); 75 | else 76 | theApp.setLimitVolume(drag.origValue + offset); 77 | 78 | break; 79 | } 80 | case Mode::bottomUp: 81 | { 82 | theApp.setLimitVolume(drag.origValue + offset); 83 | 84 | break; 85 | } 86 | case Mode::topDown: 87 | { 88 | theApp.setLimitVolume(drag.origValue - offset); 89 | 90 | break; 91 | } 92 | } 93 | 94 | break; 95 | } 96 | } 97 | } 98 | else 99 | { 100 | // MY_TRACE(_T("ホットフレームを更新します\n")); 101 | 102 | int newHotFrame = client2frame(point.x); 103 | 104 | setHotFrame(newHotFrame); 105 | outputFrames(); 106 | } 107 | 108 | return ::DefWindowProc(hwnd, message, wParam, lParam); 109 | } 110 | 111 | LRESULT MainWindow::onMouseWheel(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 112 | { 113 | int delta = (short)HIWORD(wParam); 114 | POINT point = LP2PT(lParam); 115 | ::MapWindowPoints(0, hwnd, &point, 1); 116 | 117 | MY_TRACE(_T("MainWindow::onMouseWheel(%d, %d, %d)\n"), delta, point.x, point.y); 118 | 119 | int newZoom = getZoom(); 120 | 121 | if (delta > 0) 122 | { 123 | newZoom += 10; 124 | } 125 | else 126 | { 127 | newZoom -= 10; 128 | } 129 | 130 | theApp.setZoom(newZoom); 131 | 132 | return ::DefWindowProc(hwnd, message, wParam, lParam); 133 | } 134 | 135 | LRESULT MainWindow::onLButtonDown(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 136 | { 137 | MY_TRACE(_T("MainWindow::onLButtonDown(0x%08X, 0x%08X)\n"), wParam, lParam); 138 | 139 | POINT point = LP2PT(lParam); 140 | 141 | drag.ht = hitTest(point); 142 | 143 | switch (drag.ht) 144 | { 145 | case HitTest::HorzScale: 146 | { 147 | // zoom のドラッグを開始する。 148 | 149 | ::SetCapture(hwnd); 150 | drag.origPoint = point; 151 | drag.origValue = getZoom(); 152 | 153 | break; 154 | } 155 | case HitTest::VertScaleMin: 156 | { 157 | // minRMS, limitVolume をドラッグを開始する。 158 | 159 | ::SetCapture(hwnd); 160 | drag.origPoint = point; 161 | drag.origValue = (getMode()->getID() == Mode::rms) ? getMinRMS() : getLimitVolume(); 162 | 163 | break; 164 | } 165 | case HitTest::VertScaleMax: 166 | { 167 | // maxRMS, limitVolume をドラッグを開始する。 168 | 169 | ::SetCapture(hwnd); 170 | drag.origPoint = point; 171 | drag.origValue = (getMode()->getID() == Mode::rms) ? getMaxRMS() : getLimitVolume(); 172 | 173 | break; 174 | } 175 | default: 176 | { 177 | // カレントフレームを変更する。 178 | 179 | int32_t frame = client2frame(point.x); 180 | 181 | ::PostMessage(theApp.windowContainer, WM_AVIUTL_FILTER_CHANGE_FRAME, (WPARAM)frame, 0); 182 | 183 | break; 184 | } 185 | } 186 | 187 | return ::DefWindowProc(hwnd, message, wParam, lParam); 188 | } 189 | 190 | LRESULT MainWindow::onLButtonUp(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 191 | { 192 | MY_TRACE(_T("MainWindow::onLButtonUp(0x%08X, 0x%08X)\n"), wParam, lParam); 193 | 194 | ::ReleaseCapture(); 195 | 196 | return ::DefWindowProc(hwnd, message, wParam, lParam); 197 | } 198 | 199 | //-------------------------------------------------------------------- 200 | -------------------------------------------------------------------------------- /OutProcess/MainWindow_OpenGL.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MainWindow.h" 3 | 4 | #define NANOVG_GL3_IMPLEMENTATION 5 | #include "NanoVG/nanovg_gl.h" 6 | 7 | //-------------------------------------------------------------------- 8 | 9 | BOOL MainWindow::setupPixelFormat(HDC dc) 10 | { 11 | MY_TRACE(_T("MainWindow::setupPixelFormat(0x%08X)\n"), dc); 12 | 13 | PIXELFORMATDESCRIPTOR pfd = 14 | { 15 | sizeof(pfd), 16 | 1, 17 | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 18 | PFD_TYPE_RGBA, 19 | 24, 20 | 0, 0, 0, 0, 0, 0, 21 | 0, 22 | 0, 23 | 0, 24 | 0, 0, 0, 0, 25 | 32, 26 | 1, 27 | 0, 28 | PFD_MAIN_PLANE, 29 | 0, 30 | 0, 0, 0 31 | }; 32 | 33 | int pixelFormat = ::ChoosePixelFormat(dc, &pfd); 34 | MY_TRACE_INT(pixelFormat); 35 | 36 | if (!pixelFormat) 37 | { 38 | MY_TRACE(_T("::ChoosePixelFormat() が失敗しました\n")); 39 | 40 | return FALSE; 41 | } 42 | 43 | if (!::SetPixelFormat(dc, pixelFormat, &pfd)) 44 | { 45 | MY_TRACE(_T("::SetPixelFormat() が失敗しました\n")); 46 | 47 | return FALSE; 48 | } 49 | 50 | return TRUE; 51 | } 52 | 53 | BOOL MainWindow::initOpenGL() 54 | { 55 | MY_TRACE(_T("MainWindow::initOpenGL()\n")); 56 | 57 | // OpenGL を初期化する。 58 | 59 | ClientDC dc(m_hwnd); 60 | 61 | setupPixelFormat(dc); 62 | 63 | m_rc = wglCreateContext(dc); 64 | MY_TRACE_HEX(m_rc); 65 | 66 | if (!m_rc) 67 | { 68 | MY_TRACE(_T("wglCreateContext() が失敗しました\n")); 69 | 70 | return -1; 71 | } 72 | 73 | MakeCurrent makeCurrent(dc, m_rc); 74 | 75 | { 76 | // glad を初期化する。 77 | 78 | int result = gladLoaderLoadGL(); 79 | 80 | MY_TRACE_INT(result); 81 | } 82 | 83 | // NanoVG を初期化する。 84 | 85 | m_vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES); 86 | // m_vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG); 87 | MY_TRACE_HEX(m_vg); 88 | 89 | return TRUE; 90 | } 91 | 92 | BOOL MainWindow::termOpenGL() 93 | { 94 | MY_TRACE(_T("MainWindow::termOpenGL()\n")); 95 | 96 | nvgDeleteGL3(m_vg), m_vg = 0; 97 | 98 | wglDeleteContext(m_rc), m_rc = 0; 99 | 100 | return TRUE; 101 | } 102 | 103 | //-------------------------------------------------------------------- 104 | -------------------------------------------------------------------------------- /OutProcess/MainWindow_Paint.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MainWindow.h" 3 | #include "App.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | void MainWindow::doPaint(HDC dc, const RECT& rc) 8 | { 9 | MY_TRACE(_T("MainWindow::doPaint(0x%08X)\n"), dc); 10 | 11 | MakeCurrent makeCurrent(dc, m_rc); 12 | int w = getWidth(rc); 13 | int h = getHeight(rc); 14 | 15 | glViewport(0, 0, w, h); 16 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 17 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 18 | 19 | nvgBeginFrame(m_vg, (float)w, (float)h, 1.0f); 20 | nvgSave(m_vg); 21 | 22 | nvgFontFaceId(m_vg, m_fontDefault); 23 | 24 | doPaint(rc); 25 | 26 | nvgRestore(m_vg); 27 | nvgEndFrame(m_vg); 28 | 29 | ::SwapBuffers(dc); 30 | } 31 | 32 | void MainWindow::doPaint(const RECT& rc) 33 | { 34 | if (!theApp.projectParams) return; 35 | 36 | LayoutContext context = {}; 37 | if (!getLayoutContext(context, rc)) return; 38 | 39 | m_mode->drawBackground(*this, context); 40 | m_mode->drawScale(*this, context); 41 | m_mode->drawBody(*this, context); 42 | m_mode->drawGraph(*this, context); 43 | } 44 | 45 | //-------------------------------------------------------------------- 46 | 47 | LRESULT MainWindow::onPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 48 | { 49 | PaintDC dc(hwnd); 50 | RECT rc = dc.m_ps.rcPaint; 51 | doPaint(dc, rc); 52 | 53 | return 0; 54 | } 55 | 56 | //-------------------------------------------------------------------- 57 | -------------------------------------------------------------------------------- /OutProcess/Mode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "OutProcess.h" 4 | #include "Design.h" 5 | 6 | //-------------------------------------------------------------------- 7 | 8 | struct MainWindow; 9 | struct LayoutContext; 10 | 11 | //-------------------------------------------------------------------- 12 | 13 | struct Mode 14 | { 15 | virtual int getID() const = 0; 16 | 17 | static NVGpaint nvgVertGradient(NVGcontext* vg, const XYWHRect& rc, const Design::GradientFill& design); 18 | static void nvgStrokeDesign(NVGcontext* vg, const Design::Stroke& stroke); 19 | static void nvgXYWHRect(NVGcontext* vg, const XYWHRect& rc); 20 | static void drawImage(NVGcontext* vg, int image, const XYWHRect& rc, const Design::Image& design); 21 | static void drawLine(NVGcontext* vg, float mx, float my, float lx, float ly, const Design::Stroke& stroke); 22 | static void drawText(NVGcontext* vg, LPCSTR text, float x, float y, const Design::Text& design); 23 | static void drawMarker(MainWindow& window, const LayoutContext& context, int frame, const Design::Marker& marker); 24 | 25 | virtual void drawBackground(MainWindow& window, const LayoutContext& context); 26 | virtual void drawBody(MainWindow& window, const LayoutContext& context); 27 | virtual void drawScale(MainWindow& window, const LayoutContext& context); 28 | virtual void drawHorzScale(MainWindow& window, const LayoutContext& context); 29 | virtual void drawVertScale(MainWindow& window, const LayoutContext& context); 30 | virtual void drawGraph(MainWindow& window, const LayoutContext& context); 31 | 32 | struct PointF { float x, y; }; 33 | 34 | void drawBPM(MainWindow& window, const LayoutContext& context); 35 | void drawMarkers(MainWindow& window, const LayoutContext& context); 36 | void drawVertScaleLine(MainWindow& window, const LayoutContext& context, float y); 37 | void drawPoints(MainWindow& window, const LayoutContext& context, const std::vector& points); 38 | }; 39 | 40 | struct RMSMode : public Mode 41 | { 42 | virtual int getID() const; 43 | 44 | virtual void drawVertScale(MainWindow& window, const LayoutContext& context); 45 | virtual void drawGraph(MainWindow& window, const LayoutContext& context); 46 | }; 47 | 48 | struct CenterMode : public Mode 49 | { 50 | virtual int getID() const; 51 | 52 | virtual void drawVertScale(MainWindow& window, const LayoutContext& context); 53 | virtual void drawGraph(MainWindow& window, const LayoutContext& context); 54 | }; 55 | 56 | struct BottomUpMode : public Mode 57 | { 58 | virtual int getID() const; 59 | 60 | virtual void drawVertScale(MainWindow& window, const LayoutContext& context); 61 | virtual void drawGraph(MainWindow& window, const LayoutContext& context); 62 | }; 63 | 64 | struct TopDownMode : public Mode 65 | { 66 | virtual int getID() const; 67 | 68 | virtual void drawVertScale(MainWindow& window, const LayoutContext& context); 69 | virtual void drawGraph(MainWindow& window, const LayoutContext& context); 70 | }; 71 | 72 | typedef std::shared_ptr ModePtr; 73 | 74 | //-------------------------------------------------------------------- 75 | -------------------------------------------------------------------------------- /OutProcess/Mode_BottomUp.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Mode.h" 3 | #include "MainWindow.h" 4 | #include "App.h" 5 | 6 | //-------------------------------------------------------------------- 7 | 8 | int BottomUpMode::getID() const 9 | { 10 | return MainWindow::Mode::bottomUp; 11 | } 12 | 13 | //-------------------------------------------------------------------- 14 | 15 | void BottomUpMode::drawVertScale(MainWindow& window, const LayoutContext& context) 16 | { 17 | // 垂直目盛りを左右に描画する。 18 | 19 | if (window.m_limitVolume <= 0) return; 20 | 21 | NVGcontext* vg = window.m_vg; 22 | const LayoutContext::Graph& graph = context.graph; 23 | 24 | nvgScissor(vg, (float)context.x, (float)graph.y, (float)context.w, (float)graph.h); 25 | 26 | int textPadding = 4; 27 | int textHeight = g_design.scale.vert.text.height + textPadding * 2; 28 | 29 | int prev = -(textHeight + 1); 30 | for (int i = 0; i <= 10; i++) 31 | { 32 | int oy = graph.h * i / 10; 33 | if (oy - prev < textHeight) continue; 34 | prev = oy; 35 | 36 | float fy = (float)(graph.bottom - oy); 37 | 38 | drawVertScaleLine(window, context, fy); 39 | 40 | char text[MAX_PATH] = {}; 41 | ::StringCbPrintfA(text, sizeof(text), "%d", window.m_limitVolume * i / 10); 42 | 43 | { 44 | nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM); 45 | 46 | float tx = (float)(graph.left - textPadding); 47 | float ty = (float)(fy - textPadding); 48 | 49 | drawText(vg, text, tx, ty, g_design.scale.vert.text); 50 | } 51 | 52 | { 53 | nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_BOTTOM); 54 | 55 | float tx = (float)(graph.right + textPadding); 56 | float ty = (float)(fy - textPadding); 57 | 58 | drawText(vg, text, tx, ty, g_design.scale.vert.text); 59 | } 60 | } 61 | 62 | { 63 | // 基準音量を描画する。 64 | 65 | int y = graph.bottom - graph.h * window.m_baseVolume / window.m_limitVolume; 66 | 67 | if (y > graph.top && y < graph.bottom) 68 | { 69 | float fy = (float)y; 70 | float mx = (float)context.rc.left; 71 | float lx = (float)context.rc.right; 72 | 73 | drawLine(vg, mx, fy, lx, fy, g_design.scale.vert.base.stroke); 74 | } 75 | } 76 | 77 | nvgResetScissor(vg); 78 | } 79 | 80 | void BottomUpMode::drawGraph(MainWindow& window, const LayoutContext& context) 81 | { 82 | int c = (int)theApp.totals.size(); 83 | 84 | if (c <= 0) return; 85 | if (window.m_limitVolume <= 0) return; 86 | 87 | NVGcontext* vg = window.m_vg; 88 | const LayoutContext::Graph& graph = context.graph; 89 | 90 | nvgScissor(vg, (float)graph.x, (float)graph.y, (float)graph.w, (float)graph.h); 91 | 92 | int ox = graph.x - context.hScroll; // 描画範囲の X 座標。 93 | int lh = graph.h * 100 / window.m_limitVolume; 94 | 95 | // グラフを描画する。 96 | 97 | std::vector points; 98 | 99 | { 100 | // まず、描画に必要な座標をすべて取得する。 101 | 102 | for (int i = 0; i < c; i++) 103 | { 104 | float level = theApp.totals[i].level; 105 | float x = (float)window.frame2client(i); 106 | float y = (float)graph.bottom - lh * level; 107 | 108 | points.emplace_back(x, y); 109 | } 110 | } 111 | 112 | { 113 | // グラフを塗りつぶす。 114 | 115 | nvgBeginPath(vg); 116 | nvgMoveTo(vg, (float)graph.left, (float)(graph.bottom + context.padding)); 117 | 118 | for (const auto& point : points) 119 | nvgLineTo(vg, point.x, point.y); 120 | 121 | nvgLineTo(vg, (float)graph.right, (float)(graph.bottom + context.padding)); 122 | 123 | NVGpaint paint = nvgLinearGradient(vg, 124 | (float)graph.left, (float)graph.top, 125 | (float)graph.left, (float)graph.bottom, 126 | g_design.graph.fill.color1, g_design.graph.fill.color2); 127 | nvgFillPaint(vg, paint); 128 | nvgFill(vg); 129 | } 130 | 131 | { 132 | // グラフのストロークを描画する。 133 | 134 | nvgBeginPath(vg); 135 | nvgMoveTo(vg, (float)graph.left, (float)graph.bottom); 136 | 137 | for (const auto& point : points) 138 | nvgLineTo(vg, point.x, point.y); 139 | 140 | nvgStrokeWidth(vg, (float)g_design.graph.stroke.width); 141 | nvgStrokeColor(vg, g_design.graph.stroke.color); 142 | nvgStroke(vg); 143 | } 144 | 145 | nvgResetScissor(vg); 146 | 147 | Mode::drawGraph(window, context); 148 | } 149 | 150 | //-------------------------------------------------------------------- 151 | -------------------------------------------------------------------------------- /OutProcess/Mode_Center.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Mode.h" 3 | #include "MainWindow.h" 4 | #include "App.h" 5 | 6 | //-------------------------------------------------------------------- 7 | 8 | int CenterMode::getID() const 9 | { 10 | return MainWindow::Mode::center; 11 | } 12 | 13 | //-------------------------------------------------------------------- 14 | 15 | void CenterMode::drawVertScale(MainWindow& window, const LayoutContext& context) 16 | { 17 | // 垂直目盛りを左右に描画する。 18 | 19 | if (window.m_limitVolume <= 0) return; 20 | 21 | NVGcontext* vg = window.m_vg; 22 | const LayoutContext::Graph& graph = context.graph; 23 | 24 | nvgScissor(vg, (float)context.x, (float)graph.y, (float)context.w, (float)graph.h); 25 | 26 | int textPadding = 4; 27 | int textHeight = g_design.scale.vert.text.height + textPadding * 2; 28 | int cy = graph.y + graph.h / 2; 29 | 30 | int prev = -(textHeight + 1); 31 | for (int i = 0; i <= 10; i++) 32 | { 33 | int oy = graph.h * i / 10; 34 | if (oy - prev < textHeight) continue; 35 | prev = oy; 36 | 37 | int y[2] = { cy - oy, cy + oy }; 38 | int c = (y[0] == y[1]) ? 1 : 2; 39 | 40 | for (int j = 0; j < c; j++) 41 | { 42 | drawVertScaleLine(window, context, (float)y[j]); 43 | 44 | char text[MAX_PATH] = {}; 45 | ::StringCbPrintfA(text, sizeof(text), "%d", window.m_limitVolume * i / 10); 46 | 47 | { 48 | nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM); 49 | 50 | float tx = (float)(graph.left - textPadding); 51 | float ty = (float)(y[j] - textPadding); 52 | 53 | drawText(vg, text, tx, ty, g_design.scale.vert.text); 54 | } 55 | 56 | { 57 | nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_BOTTOM); 58 | 59 | float tx = (float)(graph.right + textPadding); 60 | float ty = (float)(y[j] - textPadding); 61 | 62 | drawText(vg, text, tx, ty, g_design.scale.vert.text); 63 | } 64 | } 65 | } 66 | 67 | { 68 | // 基準音量を描画する。 69 | 70 | int oy = graph.h * window.m_baseVolume / window.m_limitVolume; 71 | 72 | for (int j = 0; j < 2; j++) 73 | { 74 | int y[2] = { cy - oy, cy + oy }; 75 | 76 | if (y[j] > graph.top && y[j] < graph.bottom) 77 | { 78 | float fy = (float)y[j]; 79 | float mx = (float)context.rc.left; 80 | float lx = (float)context.rc.right; 81 | 82 | drawLine(vg, mx, fy, lx, fy, g_design.scale.vert.base.stroke); 83 | } 84 | } 85 | } 86 | 87 | nvgResetScissor(vg); 88 | } 89 | 90 | void CenterMode::drawGraph(MainWindow& window, const LayoutContext& context) 91 | { 92 | int c = (int)theApp.totals.size(); 93 | 94 | if (c <= 0) return; 95 | if (window.m_limitVolume <= 0) return; 96 | 97 | NVGcontext* vg = window.m_vg; 98 | const LayoutContext::Graph& graph = context.graph; 99 | 100 | nvgScissor(vg, (float)graph.x, (float)graph.y, (float)graph.w, (float)graph.h); 101 | 102 | int ox = graph.x - context.hScroll; // 描画範囲の X 座標。 103 | int lh = graph.h * 100 / window.m_limitVolume; 104 | int cy = graph.y + graph.h / 2; 105 | 106 | // グラフを描画する。 107 | 108 | std::vector points; 109 | 110 | { 111 | // まず、描画に必要な座標をすべて取得する。 112 | 113 | for (int i = 0; i < c; i++) 114 | { 115 | float level = theApp.totals[i].level; 116 | float x = (float)window.frame2client(i); 117 | float y = (float)lh * level; 118 | 119 | points.emplace_back(x, y); 120 | } 121 | } 122 | 123 | { 124 | // グラフを塗りつぶす。 125 | 126 | nvgBeginPath(vg); 127 | nvgMoveTo(vg, (float)graph.left, (float)cy); 128 | 129 | for (const auto& point : points) 130 | nvgLineTo(vg, point.x, cy - point.y); 131 | 132 | int c = (int)points.size(); 133 | for (int i = c - 1; i >= 0; i--) 134 | nvgLineTo(vg, points[i].x, cy + points[i].y); 135 | 136 | NVGpaint paint = nvgLinearGradient(vg, 137 | (float)graph.left, (float)graph.top, 138 | (float)graph.left, (float)graph.bottom, 139 | g_design.graph.fill.color1, g_design.graph.fill.color2); 140 | nvgFillPaint(vg, paint); 141 | nvgFill(vg); 142 | } 143 | 144 | { 145 | // グラフのストロークを描画する。 146 | 147 | nvgBeginPath(vg); 148 | nvgMoveTo(vg, (float)graph.left, (float)cy); 149 | 150 | for (const auto& point : points) 151 | nvgLineTo(vg, point.x, cy - point.y); 152 | 153 | int c = (int)points.size(); 154 | for (int i = c - 1; i >= 0; i--) 155 | nvgLineTo(vg, points[i].x, cy + points[i].y); 156 | 157 | nvgStrokeWidth(vg, (float)g_design.graph.stroke.width); 158 | nvgStrokeColor(vg, g_design.graph.stroke.color); 159 | nvgStroke(vg); 160 | } 161 | 162 | nvgResetScissor(vg); 163 | 164 | Mode::drawGraph(window, context); 165 | } 166 | 167 | //-------------------------------------------------------------------- 168 | -------------------------------------------------------------------------------- /OutProcess/Mode_RMS.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Mode.h" 3 | #include "MainWindow.h" 4 | #include "App.h" 5 | 6 | //-------------------------------------------------------------------- 7 | 8 | int RMSMode::getID() const 9 | { 10 | return MainWindow::Mode::rms; 11 | } 12 | 13 | //-------------------------------------------------------------------- 14 | 15 | void RMSMode::drawVertScale(MainWindow& window, const LayoutContext& context) 16 | { 17 | // 垂直目盛りを左右に描画する。 18 | 19 | NVGcontext* vg = window.m_vg; 20 | const LayoutContext::Graph& graph = context.graph; 21 | 22 | nvgScissor(vg, (float)context.x, (float)graph.y, (float)context.w, (float)graph.h); 23 | 24 | int textPadding = 4; 25 | int textHeight = g_design.scale.vert.text.height + textPadding * 2; 26 | 27 | int minRMS = window.getMinRMS(); 28 | int maxRMS = window.getMaxRMS(); 29 | int baseRMS = window.getBaseRMS(); 30 | 31 | float range = (float)(maxRMS - minRMS); 32 | MY_TRACE_REAL(range); 33 | int freq = (int)(range * textHeight / graph.h) + 1; 34 | MY_TRACE_INT(freq); 35 | 36 | for (int i = maxRMS; i > minRMS - freq; i--) 37 | { 38 | if (i % freq) continue; 39 | 40 | float relativeLevel = (float)(i - minRMS); 41 | int y = (int)(graph.y + graph.h * (1.0f - relativeLevel / range)); 42 | float fy = (float)y; 43 | 44 | drawVertScaleLine(window, context, fy); 45 | 46 | char text[MAX_PATH] = {}; 47 | ::StringCbPrintfA(text, sizeof(text), "%+d", i); 48 | 49 | { 50 | nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM); 51 | 52 | float tx = (float)(graph.left - textPadding); 53 | float ty = (float)(y - textPadding); 54 | 55 | drawText(vg, text, tx, ty, g_design.scale.vert.text); 56 | } 57 | 58 | { 59 | nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_BOTTOM); 60 | 61 | float tx = (float)(graph.right + textPadding); 62 | float ty = (float)(y - textPadding); 63 | 64 | drawText(vg, text, tx, ty, g_design.scale.vert.text); 65 | } 66 | } 67 | 68 | { 69 | // 基準 RMS を描画する。 70 | 71 | float relativeLevel = (float)(baseRMS - minRMS); 72 | int y = (int)(graph.top + graph.h * (1.0f - relativeLevel / range)); 73 | 74 | if (y > graph.top && y < graph.bottom) 75 | { 76 | float fy = (float)y; 77 | float mx = (float)context.rc.left; 78 | float lx = (float)context.rc.right; 79 | 80 | drawLine(vg, mx, fy, lx, fy, g_design.scale.vert.base.stroke); 81 | } 82 | } 83 | 84 | nvgResetScissor(vg); 85 | } 86 | 87 | void RMSMode::drawGraph(MainWindow& window, const LayoutContext& context) 88 | { 89 | int c = (int)theApp.totals.size(); 90 | 91 | if (c <= 0) return; 92 | 93 | NVGcontext* vg = window.m_vg; 94 | const LayoutContext::Graph& graph = context.graph; 95 | 96 | nvgScissor(vg, (float)graph.x, (float)graph.y, (float)graph.w, (float)graph.h); 97 | 98 | int ox = graph.x - context.hScroll; // 描画範囲の X 座標。 99 | int minRMS = window.getMinRMS(); 100 | int maxRMS = window.getMaxRMS(); 101 | 102 | // グラフを描画する。 103 | 104 | std::vector points; 105 | 106 | { 107 | // まず、描画に必要な座標をすべて取得する。 108 | 109 | for (int i = 0; i < c; i++) 110 | { 111 | float level = (theApp.totals[i].rms - minRMS) / (maxRMS - minRMS); 112 | float x = (float)window.frame2client(i); 113 | float y = std::min((float)graph.bottom, (float)graph.bottom - graph.h * level); 114 | 115 | points.emplace_back(x, y); 116 | } 117 | } 118 | 119 | { 120 | // グラフを塗りつぶす。 121 | 122 | nvgBeginPath(vg); 123 | nvgMoveTo(vg, (float)graph.left, (float)(graph.bottom + context.padding)); 124 | 125 | for (const auto& point : points) 126 | nvgLineTo(vg, point.x, point.y); 127 | 128 | nvgLineTo(vg, (float)graph.right, (float)(graph.bottom + context.padding)); 129 | // nvgClosePath(vg); 130 | // nvgPathWinding(vg, NVG_SOLID); 131 | 132 | NVGpaint paint = nvgLinearGradient(vg, 133 | (float)graph.left, (float)graph.top, 134 | (float)graph.left, (float)graph.bottom, 135 | g_design.graph.fill.color1, g_design.graph.fill.color2); 136 | nvgFillPaint(vg, paint); 137 | nvgFill(vg); 138 | } 139 | 140 | { 141 | // グラフのストロークを描画する。 142 | 143 | nvgBeginPath(vg); 144 | nvgMoveTo(vg, (float)graph.left, (float)graph.bottom); 145 | 146 | for (const auto& point : points) 147 | nvgLineTo(vg, point.x, point.y); 148 | 149 | nvgStrokeWidth(vg, (float)g_design.graph.stroke.width); 150 | nvgStrokeColor(vg, g_design.graph.stroke.color); 151 | nvgStroke(vg); 152 | } 153 | 154 | nvgResetScissor(vg); 155 | 156 | Mode::drawGraph(window, context); 157 | } 158 | 159 | //-------------------------------------------------------------------- 160 | -------------------------------------------------------------------------------- /OutProcess/Mode_TopDown.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Mode.h" 3 | #include "MainWindow.h" 4 | #include "App.h" 5 | 6 | //-------------------------------------------------------------------- 7 | 8 | int TopDownMode::getID() const 9 | { 10 | return MainWindow::Mode::topDown; 11 | } 12 | 13 | //-------------------------------------------------------------------- 14 | 15 | void TopDownMode::drawVertScale(MainWindow& window, const LayoutContext& context) 16 | { 17 | // 垂直目盛りを左右に描画する。 18 | 19 | if (window.m_limitVolume <= 0) return; 20 | 21 | NVGcontext* vg = window.m_vg; 22 | const LayoutContext::Graph& graph = context.graph; 23 | 24 | nvgScissor(vg, (float)context.x, (float)graph.y, (float)context.w, (float)graph.h); 25 | 26 | int textPadding = 4; 27 | int textHeight = g_design.scale.vert.text.height + textPadding * 2; 28 | 29 | int prev = -(textHeight + 1); 30 | for (int i = 0; i <= 10; i++) 31 | { 32 | int oy = graph.h * i / 10; 33 | if (oy - prev < textHeight) continue; 34 | prev = oy; 35 | 36 | float fy = (float)(graph.top + oy); 37 | 38 | drawVertScaleLine(window, context, fy); 39 | 40 | char text[MAX_PATH] = {}; 41 | ::StringCbPrintfA(text, sizeof(text), "%d", window.m_limitVolume * i / 10); 42 | 43 | { 44 | nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM); 45 | 46 | float tx = (float)(graph.left - textPadding); 47 | float ty = (float)(fy - textPadding); 48 | 49 | drawText(vg, text, tx, ty, g_design.scale.vert.text); 50 | } 51 | 52 | { 53 | nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_BOTTOM); 54 | 55 | float tx = (float)(graph.right + textPadding); 56 | float ty = (float)(fy - textPadding); 57 | 58 | drawText(vg, text, tx, ty, g_design.scale.vert.text); 59 | } 60 | } 61 | 62 | { 63 | // 基準音量を描画する。 64 | 65 | int y = graph.top + graph.h * window.m_baseVolume / window.m_limitVolume; 66 | 67 | if (y > graph.top && y < graph.bottom) 68 | { 69 | float fy = (float)y; 70 | float mx = (float)context.rc.left; 71 | float lx = (float)context.rc.right; 72 | 73 | drawLine(vg, mx, fy, lx, fy, g_design.scale.vert.base.stroke); 74 | } 75 | } 76 | 77 | nvgResetScissor(vg); 78 | } 79 | 80 | void TopDownMode::drawGraph(MainWindow& window, const LayoutContext& context) 81 | { 82 | int c = (int)theApp.totals.size(); 83 | 84 | if (c <= 0) return; 85 | if (window.m_limitVolume <= 0) return; 86 | 87 | NVGcontext* vg = window.m_vg; 88 | const LayoutContext::Graph& graph = context.graph; 89 | 90 | nvgScissor(vg, (float)graph.x, (float)graph.y, (float)graph.w, (float)graph.h); 91 | 92 | int ox = graph.x - context.hScroll; // 描画範囲の X 座標。 93 | int lh = graph.h * 100 / window.m_limitVolume; 94 | 95 | // グラフを描画する。 96 | 97 | std::vector points; 98 | 99 | { 100 | // まず、描画に必要な座標をすべて取得する。 101 | 102 | for (int i = 0; i < c; i++) 103 | { 104 | float level = theApp.totals[i].level; 105 | float x = (float)window.frame2client(i); 106 | float y = (float)graph.top + lh * level; 107 | 108 | points.emplace_back(x, y); 109 | } 110 | } 111 | 112 | { 113 | // グラフを塗りつぶす。 114 | 115 | nvgBeginPath(vg); 116 | nvgMoveTo(vg, (float)graph.left, (float)(graph.top - context.padding)); 117 | 118 | for (const auto& point : points) 119 | nvgLineTo(vg, point.x, point.y); 120 | 121 | nvgLineTo(vg, (float)graph.right, (float)(graph.top - context.padding)); 122 | 123 | NVGpaint paint = nvgLinearGradient(vg, 124 | (float)graph.left, (float)graph.top, 125 | (float)graph.left, (float)graph.bottom, 126 | g_design.graph.fill.color1, g_design.graph.fill.color2); 127 | nvgFillPaint(vg, paint); 128 | nvgFill(vg); 129 | } 130 | 131 | { 132 | // グラフのストロークを描画する。 133 | 134 | nvgBeginPath(vg); 135 | nvgMoveTo(vg, (float)graph.left, (float)graph.top); 136 | 137 | for (const auto& point : points) 138 | nvgLineTo(vg, point.x, point.y); 139 | 140 | nvgStrokeWidth(vg, (float)g_design.graph.stroke.width); 141 | nvgStrokeColor(vg, g_design.graph.stroke.color); 142 | nvgStroke(vg); 143 | } 144 | 145 | nvgResetScissor(vg); 146 | 147 | Mode::drawGraph(window, context); 148 | } 149 | 150 | //-------------------------------------------------------------------- 151 | -------------------------------------------------------------------------------- /OutProcess/OutProcess.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | //-------------------------------------------------------------------- 4 | -------------------------------------------------------------------------------- /OutProcess/OutProcess.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //-------------------------------------------------------------------- 4 | 5 | struct Label { 6 | int value; 7 | LPCWSTR label; 8 | }; 9 | 10 | //-------------------------------------------------------------------- 11 | -------------------------------------------------------------------------------- /OutProcess/OutProcess.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hebiiro/AviUtl-Plugin-ShowWaveform/ada292c648f8d941588c9261710214e157c187ef/OutProcess/OutProcess.rc -------------------------------------------------------------------------------- /OutProcess/OutProcess.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {3e78d513-8512-4a92-8896-6c1e074647ea} 25 | OutProcess 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | false 82 | 83 | 84 | true 85 | 86 | 87 | false 88 | 89 | 90 | 91 | Level3 92 | true 93 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 94 | true 95 | Use 96 | pch.h 97 | stdcpplatest 98 | 99 | 100 | Windows 101 | true 102 | 103 | 104 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\MySpace\AviUtl\AviUtl110_test\Plugins\$(SolutionName)\$(SolutionName).exe" 105 | 106 | 107 | 108 | 109 | 110 | Level3 111 | true 112 | true 113 | true 114 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 115 | true 116 | Use 117 | pch.h 118 | stdcpplatest 119 | 120 | 121 | Windows 122 | true 123 | true 124 | true 125 | 126 | 127 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\MySpace\AviUtl\AviUtl110_test\Plugins\$(SolutionName)\$(SolutionName).exe" 128 | 129 | 130 | 131 | 132 | 133 | Level3 134 | true 135 | _DEBUG;_WINDOWS;%(PreprocessorDefinitions) 136 | true 137 | Use 138 | pch.h 139 | stdcpplatest 140 | 141 | 142 | Windows 143 | true 144 | 145 | 146 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\AviUtl110_test\Plugins\$(SolutionName)\$(SolutionName).exe" 147 | 148 | 149 | 150 | 151 | 152 | Level3 153 | true 154 | true 155 | true 156 | NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 157 | true 158 | Use 159 | pch.h 160 | stdcpplatest 161 | 162 | 163 | Windows 164 | true 165 | true 166 | true 167 | 168 | 169 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\AviUtl110_test\Plugins\$(SolutionName)\$(SolutionName).exe" 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | Create 208 | Create 209 | Create 210 | Create 211 | 212 | 213 | 214 | 215 | 216 | 217 | {db2053e8-60d4-4bd5-845a-11ca24e2c599} 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /OutProcess/OutProcess.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {b2b8b579-a036-4aeb-aa10-399e689a71f3} 6 | 7 | 8 | {639143d2-2767-4514-ba40-4e8535d9fa7e} 9 | 10 | 11 | 12 | 13 | Framework 14 | 15 | 16 | Framework 17 | 18 | 19 | Framework 20 | 21 | 22 | 23 | 24 | 25 | 26 | Resource 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | Framework 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Resource 61 | 62 | 63 | -------------------------------------------------------------------------------- /OutProcess/ReaderManager.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ReaderManager.h" 3 | #include "App.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | Reader::Reader(HWND hwnd) 8 | { 9 | MY_TRACE(_T("Reader::Reader(0x%08p)\n"), hwnd); 10 | 11 | TCHAR path[MAX_PATH] = {}; 12 | ::GetModuleFileName(theApp.instance, path, MAX_PATH); 13 | ::PathRemoveFileSpec(path); 14 | ::PathAppend(path, _T("ReaderProcess.exe")); 15 | MY_TRACE_TSTR(path); 16 | 17 | TCHAR args[MAX_PATH] = {}; 18 | ::StringCbPrintf(args, sizeof(args), _T("0x%08p"), hwnd); 19 | MY_TRACE_TSTR(args); 20 | 21 | STARTUPINFO si = { sizeof(si) }; 22 | if (!::CreateProcess( 23 | path, // No module name (use command line) 24 | args, // Command line 25 | NULL, // Process handle not inheritable 26 | NULL, // Thread handle not inheritable 27 | FALSE, // Set handle inheritance to FALSE 28 | 0, // No creation flags 29 | NULL, // Use parent's environment block 30 | NULL, // Use parent's starting directory 31 | &si, // Pointer to STARTUPINFO structure 32 | &pi)) // Pointer to PROCESS_INFORMATION structure 33 | { 34 | MY_TRACE(_T("::CreateProcess() failed.\n")); 35 | 36 | return; 37 | } 38 | 39 | shared.init(getSharedReaderBottleName(getId())); 40 | } 41 | 42 | Reader::~Reader() 43 | { 44 | MY_TRACE(_T("Reader::~Reader() : %d, %d\n"), pi.dwProcessId, pi.dwThreadId); 45 | 46 | ::CloseHandle(pi.hThread); 47 | ::CloseHandle(pi.hProcess); 48 | } 49 | 50 | DWORD Reader::getId() 51 | { 52 | return pi.dwThreadId; 53 | } 54 | 55 | ReaderBottle* Reader::getBottle() 56 | { 57 | return shared.getBuffer(); 58 | } 59 | 60 | //-------------------------------------------------------------------- 61 | 62 | // リーダーを取得する。 63 | ReaderPtr ReaderManager::getReader(DWORD id) 64 | { 65 | auto it = readerMap.find(id); 66 | if (it == readerMap.end()) return 0; 67 | return it->second; 68 | } 69 | 70 | // リーダーを作成する。 71 | ReaderPtr ReaderManager::createReader(LPCSTR fileName) 72 | { 73 | MY_TRACE(_T("ReaderManager::createReader(%hs)\n"), fileName); 74 | 75 | ReaderPtr reader = std::make_shared(theApp.mainWindow); 76 | ReaderBottle* shared = reader->getBottle(); 77 | if (!shared) return 0; 78 | ::StringCbCopyA(shared->fileName, sizeof(shared->fileName), fileName); 79 | readerMap[reader->getId()] = reader; 80 | return reader; 81 | } 82 | 83 | // リーダーを削除する。 84 | void ReaderManager::eraseReader(DWORD id) 85 | { 86 | MY_TRACE(_T("ReaderManager::eraseReader(%d)\n"), id); 87 | 88 | readerMap.erase(id); 89 | } 90 | 91 | BOOL ReaderManager::hasEmpty() 92 | { 93 | return (int)readerMap.size() < maxReaderCount; 94 | } 95 | 96 | //-------------------------------------------------------------------- 97 | -------------------------------------------------------------------------------- /OutProcess/ReaderManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //-------------------------------------------------------------------- 4 | 5 | struct Reader { 6 | PROCESS_INFORMATION pi = {}; 7 | SimpleFileMappingT shared; 8 | Reader(HWND hwnd); 9 | ~Reader(); 10 | DWORD getId(); 11 | ReaderBottle* getBottle(); 12 | }; 13 | 14 | typedef std::shared_ptr ReaderPtr; 15 | typedef std::map ReaderMap; 16 | 17 | //-------------------------------------------------------------------- 18 | 19 | struct ReaderManager { 20 | ReaderMap readerMap; 21 | int maxReaderCount = 1; 22 | 23 | ReaderPtr getReader(DWORD id); 24 | ReaderPtr createReader(LPCSTR fileName); 25 | void eraseReader(DWORD id); 26 | BOOL hasEmpty(); 27 | }; 28 | 29 | //-------------------------------------------------------------------- 30 | -------------------------------------------------------------------------------- /OutProcess/WaiterManager.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "WaiterManager.h" 3 | 4 | //-------------------------------------------------------------------- 5 | 6 | Waiter::Waiter(LPCSTR fileName) 7 | : fileName(fileName) 8 | { 9 | } 10 | 11 | //-------------------------------------------------------------------- 12 | 13 | WaiterPtr WaiterManager::createWaiter(LPCSTR fileName) 14 | { 15 | MY_TRACE(_T("WaiterManager::createWaiter(%hs)\n"), fileName); 16 | 17 | auto it = std::find_if(waiterQueue.begin(), waiterQueue.end(), 18 | [fileName](const WaiterPtr& waiter){ return waiter->fileName == fileName; }); 19 | if (it != waiterQueue.end()) 20 | return FALSE; // 既にキューに存在するので何もしない。 21 | 22 | WaiterPtr waiter = std::make_shared(fileName); 23 | waiterQueue.emplace_back(waiter); 24 | return waiter; 25 | } 26 | 27 | // ウェイターを消化する。 28 | void WaiterManager::digestWaiterQueue(ReaderManager& readerManager) 29 | { 30 | MY_TRACE(_T("WaiterManager::digestWaiterQueue()\n")); 31 | 32 | // ウェイターが存在し、なおかつリーダーの数に空きがあるなら 33 | while (!waiterQueue.empty() && readerManager.hasEmpty()) 34 | { 35 | // ウェイターを取得する。 36 | const WaiterPtr& waiter = waiterQueue.front(); 37 | 38 | // リーダーを作成する。 39 | ReaderPtr reader = readerManager.createReader(waiter->fileName.c_str()); 40 | 41 | // ウェイターを削除する。 42 | waiterQueue.pop_front(); 43 | } 44 | 45 | MY_TRACE_INT(waiterQueue.size()); 46 | MY_TRACE_INT(readerManager.readerMap.size()); 47 | } 48 | 49 | //-------------------------------------------------------------------- 50 | -------------------------------------------------------------------------------- /OutProcess/WaiterManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "OutProcess.h" 4 | #include "ReaderManager.h" 5 | 6 | //-------------------------------------------------------------------- 7 | 8 | struct Waiter { 9 | std::string fileName; 10 | Waiter(LPCSTR fileName); 11 | }; 12 | 13 | typedef std::shared_ptr WaiterPtr; 14 | typedef std::deque WaiterQueue; 15 | 16 | //-------------------------------------------------------------------- 17 | 18 | struct WaiterManager { 19 | WaiterQueue waiterQueue; 20 | WaiterPtr createWaiter(LPCSTR fileName); 21 | void digestWaiterQueue(ReaderManager& readerManager); 22 | }; 23 | 24 | //-------------------------------------------------------------------- 25 | -------------------------------------------------------------------------------- /OutProcess/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | #define WIN32_LEAN_AND_MEAN 5 | #define NOMINMAX 6 | #include 7 | #include 8 | #include 9 | #pragma comment(lib, "shlwapi.lib") 10 | #include 11 | #pragma comment(lib, "comctl32.lib") 12 | #include 13 | #pragma comment(lib, "comdlg32.lib") 14 | #include 15 | #include 16 | #include 17 | #pragma comment(lib, "winmm.lib") 18 | #include 19 | #pragma comment(lib, "opengl32.lib") 20 | #pragma comment(lib, "glu32.lib") 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "NanoVG/nanovg.h" 36 | #pragma comment(lib, "NanoVG/NanoVGd32.lib") 37 | #include "aviutl.hpp" 38 | #include "exedit.hpp" 39 | #include "Common/Tracer.h" 40 | #include "Common/WinUtility.h" 41 | #include "Common/Gdi.h" 42 | #include "Common/Dialog.h" 43 | #include "Common/Profile.h" 44 | #include "Common/FileUpdateChecker.h" 45 | #include "../ShowWaveform/Share.h" 46 | 47 | //#ifdef _UNICODE 48 | #if defined _M_IX86 49 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 50 | #elif defined _M_X64 51 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 52 | #else 53 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 54 | #endif 55 | //#endif 56 | -------------------------------------------------------------------------------- /OutProcess/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #pragma warning(disable:4551) 4 | #define GLAD_GL_IMPLEMENTATION 5 | #include 6 | -------------------------------------------------------------------------------- /OutProcess/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "framework.h" 4 | -------------------------------------------------------------------------------- /OutProcess/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ で生成されたインクルード ファイル。 3 | // OutProcess.rc で使用 4 | // 5 | #define IDD_CONFIG_DIALOG 101 6 | #define IDC_SHOW_BPM 1010 7 | #define IDC_ORIG 1020 8 | #define IDC_ORIG_SPIN 1021 9 | #define IDC_BPM 1022 10 | #define IDC_BPM_SPIN 1023 11 | #define IDC_ABOVE 1024 12 | #define IDC_ABOVE_SPIN 1025 13 | #define IDC_BELOW 1026 14 | #define IDC_BELOW_SPIN 1027 15 | #define IDC_LIMIT_VOLUME 1030 16 | #define IDC_LIMIT_VOLUME_SPIN 1031 17 | #define IDC_BASE_VOLUME 1032 18 | #define IDC_BASE_VOLUME_SPIN 1033 19 | #define IDC_MIN_RMS 1040 20 | #define IDC_MIN_RMS_SPIN 1041 21 | #define IDC_MAX_RMS 1042 22 | #define IDC_MAX_RMS_SPIN 1043 23 | #define IDC_BASE_RMS 1044 24 | #define IDC_BASE_RMS_SPIN 1045 25 | #define IDC_ZOOM 1050 26 | #define IDC_ZOOM_SPIN 1051 27 | #define IDC_STATUS 1052 28 | 29 | // Next default values for new objects 30 | // 31 | #ifdef APSTUDIO_INVOKED 32 | #ifndef APSTUDIO_READONLY_SYMBOLS 33 | #define _APS_NEXT_RESOURCE_VALUE 103 34 | #define _APS_NEXT_COMMAND_VALUE 40001 35 | #define _APS_NEXT_CONTROL_VALUE 1053 36 | #define _APS_NEXT_SYMED_VALUE 101 37 | #endif 38 | #endif 39 | -------------------------------------------------------------------------------- /OutProcess/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // // SDKDDKVer.h をインクルードすると、利用できる最も高いレベルの Windows プラットフォームが定義されます。 4 | // 以前の Windows プラットフォーム用にアプリケーションをビルドする場合は、WinSDKVer.h をインクルードし、 5 | // サポートしたいプラットフォームに _WIN32_WINNT マクロを設定してから SDKDDKVer.h をインクルードします。 6 | #include 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AviUtl プラグイン - アイテム内音声波形 2 | 3 | 拡張編集ウィンドウの音声アイテム内に音声波形 (厳密には音声波形ではなく各フレーム毎の音量のグラフ) を表示します。
4 | [最新バージョンをダウンロード](../../releases/latest/) 5 | 6 | ![アイテム内音声波形 1 0 0](https://user-images.githubusercontent.com/96464759/164222503-7f0e446a-5a7e-42b1-b052-0a500594eee5.png) 7 | 8 | ## 導入方法 9 | 10 | 1. [L-SMASH Works](https://github.com/Mr-Ojii/L-SMASH-Works-Auto-Builds/releases) を AviUtl の Plugins フォルダに導入してください。 11 | 2. 以下のファイルを AviUtl の Plugins フォルダに入れてください。 12 | * ShowWaveform.auf 13 | * ShowWaveform (フォルダ) 14 | 15 | ## 使用方法 16 | 17 | 更新モードを「更新する」に設定すると自動的に音声波形が表示されるようになります。 18 | 19 | ### キャッシュをクリアする 20 | 21 | 1. 「キャッシュをクリア」ボタンを押します。 22 | 2. すべての音声アイテムの音声波形が再計算されます。 23 | 24 | * 更新モードを「更新しない」に設定してからキャッシュをクリアすると音声波形がない状態と同じになります。 25 | 26 | ### 全体の音声波形を表示する 27 | 28 | 1. 「全体の音声波形を表示」ボタンを押します。 29 | 2. 全体の音声波形ウィンドウが表示されます。同時に全体の音声波形が再計算されます。 30 | 31 | ### 全体の音声波形ウィンドウ 32 | 33 | * グラフの部分をクリックすると現在フレームを変更できます。 34 | * 時間目盛り上で左右にドラッグすると ```ズーム``` を変更できます。 35 | * 音量メモリ上で上下にドラッグすると ```最大音量 (RMSモード時は下半分が最小RMS、上半分が最大RMS)``` を変更できます。 36 | * マウスホイールすると ```ズーム``` を変更できます。 37 | 38 | ### マルチプロセスを有効化する 39 | 40 | Config.ini の ```[Config]maxReaderCount``` で同時に実行するプロセスの最大数を指定します。 41 | 42 | ### 全体の音声波形ウィンドウのコンテキストメニュー 43 | 44 | * 全体の音声波形ウィンドウで右クリックしてコンテキストメニューを表示します。 45 | * ```RMS``` 描画モードを「RMS」に設定します。RMSが描画されるようになります。 46 | * ```中央``` 描画モードを「中央」に設定します。音量が中央から線対称に描画されます。 47 | * ```ボトムアップ``` 描画モードを「ボトムアップ」に設定します。音量が下から上に描画されます。 48 | * ```トップダウン``` 描画モードを「トップダウン」に設定します。音量が上から下に描画されます。 49 | * ```水平目盛りを上下に表示``` 時間目盛りを上下両方に表示します。 50 | * ```水平目盛りを上のみに表示``` 時間目盛りを上のみに表示します。 51 | * ```水平目盛りを下のみに表示``` 時間目盛りを下のみに表示します。 52 | * ```水平目盛りをサイドだけに表示``` 時間目盛りをグラフのサイドにだけに表示します。 53 | * ```水平目盛りを一直線に表示``` 時間目盛りをグラフを横切るように一直線に表示します。 54 | * ```垂直目盛りを左右に表示``` 音量目盛りを左右両方に表示します。 55 | * ```垂直目盛りを左のみに表示``` 音量目盛りを左のみに表示します。 56 | * ```垂直目盛りを右のみに表示``` 音量目盛りを右のみに表示します。 57 | * ```垂直目盛りをサイドだけに表示``` 音量目盛りをグラフのサイドにだけに表示します。 58 | * ```垂直目盛りを一直線に表示``` 音量目盛りをグラフを横切るように一直線に表示します。 59 | * ```その他の設定``` 「全体の音声波形の設定」ウィンドウを表示します。 60 | 61 | ### 全体の音声波形の設定 62 | 63 | * ```BPMを表示``` チェックを入れるとBPMを描画するようになります。 64 | * ```基準フレーム``` BPMを描画するとき基準になるフレーム番号を指定します。 65 | * ```BPM``` BPMを指定します。 66 | * ```拍子``` 拍子を指定します。(楽譜に書いてある上の数字) 67 | * ```分``` 分を指定します。(楽譜に書いてある下の数字) 68 | * ↑ここまでの設定はプロジェクト毎に保存されます。 69 | * ```最大音量``` 描画可能な最大音量を指定します。(グラフの最大値) 70 | * ```基準音量``` グラフで強調表示したい音量を指定します。 71 | * ```最小RMS``` 描画可能な最小RMSを指定します。(グラフの最小値) 72 | * ```最大RMS``` 描画可能な最大RMSを指定します。(グラフの最大値) 73 | * ```基準RMS``` グラフで強調表示したいRMSを指定します。 74 | * ```ズーム``` 時間方向のズーム値を指定します。 75 | 76 | ## 詳細な設定方法 77 | 78 | ShowWaveform.ini をテキストエディタで編集してから AviUtl を起動します。 79 | 80 | ```ini 81 | [Config] 82 | penColor=0,255,255 83 | ; 音声波形の縁の色を指定します。 84 | ; r,g,b、#rgb、#rrggbb の形式、または -1 を指定できます。 85 | ; -1 を指定すると描画が抑制されます。 86 | 87 | brushColor=0,255,255 88 | ; 音声波形の塗りつぶし色を指定します。 89 | ; penColor と同じ形式で指定できます。 90 | 91 | scale=200 92 | ; 音声波形を描画するサイズを指定します。 93 | ; 数値が大きいほど音声波形が大きく描画されます。 94 | 95 | showType=1 96 | ; 音声波形の表示タイプを指定します。 97 | ; 0 を指定すると音声波形が中央に描画されます。※他の表示タイプより重いです。 98 | ; 1 を指定すると音声波形が下に描画されます。 99 | ; 2 を指定すると音声波形が上に描画されます。 100 | 101 | updateMode=1 102 | ; 音声波形の更新モードを指定します。 103 | ; 0 - 音声波形を更新しません。 104 | ; 1 - 音声波形を自動的に更新します。 105 | ; 2 - 音声波形を自動的に更新しますが、再生中は更新しません。 106 | 107 | xorMode=1 108 | ; 音声波形の描画モードを指定します。 109 | ; 0 - 通常の上書き描画です。 110 | ; 1 - XOR で描画します。 111 | ; 2 - NOT XOR で描画します。 112 | ; 3 - NOT で描画します。 113 | 114 | showWaveform=1 115 | ; 音声波形を表示するか指定します。 116 | ; 0 を指定すると音声波形を表示しません。 117 | ; 1 を指定すると音声波形を表示します。 118 | 119 | showText=1 120 | ; テキストを表示するか指定します。 121 | ; 0 を指定するとテキストを表示しません。 122 | ; 1 を指定するとテキストを表示します。 123 | 124 | noScrollText=1 125 | ; テキストのスクロールを無効化するか指定します。 126 | ; 0 を指定するとテキストをスクロールします。 127 | ; 1 を指定するとテキストをスクロールしません。 128 | 129 | behind=1 130 | ; 音声波形をテキストの後ろに描画するか指定します。 131 | ; 0 を指定するとテキストの前に描画します。 132 | ; 1 を指定するとテキストの後ろに描画します。 133 | 134 | includeLayers= 135 | ; 波形の作成対象となるレイヤーを`,`区切りで指定します。 136 | ; 例えば`1,2,3`と指定するとレイヤー1~3だけが対象となります。 137 | ; 指定なしの場合はすべてのレイヤーが対象になります。 138 | 139 | excludeLayers= 140 | ; 波形の作成対象外となるレイヤーを`,`区切りで指定します。 141 | ; 例えば`4,5,6`と指定するとレイヤー4~6だけが対象外となります。 142 | 143 | excludeDir= 144 | ; 波形の作成対象外となるフォルダを指定します。 145 | ; 例えば`C:\Test`と指定するとパスに`C:\Test`が含まれているファイルは対象外となります。 146 | ``` 147 | 148 | ## 全体の音声波形の設定方法 149 | 150 | Config.ini をテキストエディタで編集します。AviUtl が起動中の場合は変更が自動的に反映されます。 151 | ```ini 152 | [Config] 153 | maxReaderCount=2 ; 同時実行するプロセスの数。大きいほどシステムリソース(瞬間的なメモリ増、及び複数ファイルへの同時アクセス)を消費するが、その分高速化が期待できる。 154 | limitVolume=100 ; グラフで描画する最大音量を指定する。(0~100) 155 | baseVolume=50 ; グラフで描画する基準音量を指定する。(0~100) 156 | minRMS=-33 ; グラフで描画するRMSの最小値を指定する。 157 | maxRMS=14 ; グラフで描画するRMSの最大値を指定する。 158 | baseRMS=0 ; グラフで描画するRMSの基準値を指定する。 159 | zoom=0 ; 追加する描画幅をピクセル単位で指定する。 160 | mode=rms ; 描画モードを指定する。rms, center, bottomUp, topDown のいずれか。 161 | 162 | [Design] 163 | fontDefault=C:\Windows\Fonts\segoeui.ttf 164 | fontDefault2=C:\Windows\Fonts\meiryo.ttc 165 | image.fileName= ; 背景に使用する画像ファイルのパス。 166 | image.offset.x=0 167 | image.offset.y=0 168 | image.align.x=center ; left, right, center のいずれか。 169 | image.align.y=center ; top, bottom, center のいずれか。 170 | image.scaleMode=normal ; normal, fit, crop のいずれか。 171 | image.scale=1.000000 172 | image.angle=0.000000 173 | image.alpha=1.000000 174 | background.fill.color1=51, 51, 51, 255 ; 縦方向のグラデーションの上側。 175 | background.fill.color2=26, 26, 26, 255 ; 縦方向のグラデーションの下側。 176 | body.margin.x=40 ; 左右のマージン。垂直目盛りが描画される範囲。 177 | body.margin.y=30 ; 上下のマージン。水平目盛りが描画される範囲。 178 | body.stroke.style=solid ; ストロークのラインスタイルを指定する。solid, dashed, dotted, glow のいずれか。 179 | body.stroke.width=1 ; ストロークの幅を指定する。 180 | body.stroke.color=255, 255, 255, 128 ; ストロークの色を指定する。 181 | scale.horz.minUnitWidth=100 ; 時間目盛りの主罫線の最小間隔をピクセル単位で指定する。 182 | scale.horz.primary.height=10 ; 時間目盛りの主罫線の高さをピクセル単位で指定する。 183 | scale.horz.primary.stroke.style=solid 184 | scale.horz.primary.stroke.width=1 185 | scale.horz.primary.stroke.color=255, 255, 255, 204 186 | scale.horz.primary.text.height=16 ; フォントの大きさを指定する。 187 | scale.horz.primary.text.color=255, 255, 255, 204 188 | scale.horz.primary.text.shadow.dilate=1.000000 ; 縁取り量をピクセル単位の整数で指定する。offset の影響を受ける。 189 | scale.horz.primary.text.shadow.blur=1.000000 ; ぼかし量をピクセル単位で指定する。 190 | scale.horz.primary.text.shadow.offset.x=0 ; 影を描画する位置を指定する。 191 | scale.horz.primary.text.shadow.offset.y=0 192 | scale.horz.primary.text.shadow.color=0, 0, 0, 128 193 | scale.horz.secondary.height=5 ; 時間目盛りの副罫線の高さをピクセル単位で指定する。 194 | scale.horz.secondary.stroke.style=solid 195 | scale.horz.secondary.stroke.width=1 196 | scale.horz.secondary.stroke.color=255, 255, 255, 102 197 | scale.vert.width=10 ; 音量目盛りの幅をピクセル単位で指定する。 198 | scale.vert.text.height=16 199 | scale.vert.text.color=255, 255, 255, 204 200 | scale.vert.text.shadow.dilate=1.000000 201 | scale.vert.text.shadow.blur=1.000000 202 | scale.vert.text.shadow.offset.x=0 203 | scale.vert.text.shadow.offset.y=0 204 | scale.vert.text.shadow.color=0, 0, 0, 128 205 | scale.vert.stroke.style=solid 206 | scale.vert.stroke.width=1 207 | scale.vert.stroke.color=255, 255, 255, 102 208 | scale.vert.base.stroke.style=solid 209 | scale.vert.base.stroke.width=1 210 | scale.vert.base.stroke.color=255, 0, 0, 128 211 | graph.fill.color1=255, 255, 0, 102 ; 縦方向のグラデーションの上側。 212 | graph.fill.color2=255, 255, 0, 102 ; 縦方向のグラデーションの下側。 213 | graph.stroke.style=solid 214 | graph.stroke.width=1 215 | graph.stroke.color=255, 255, 0, 51 216 | graph.current.stroke.style=solid 217 | graph.current.stroke.width=1 218 | graph.current.stroke.color=0, 255, 0, 102 219 | graph.hot.stroke.style=solid 220 | graph.hot.stroke.width=1 221 | graph.hot.stroke.color=255, 0, 255, 102 222 | graph.last.stroke.style=solid 223 | graph.last.stroke.width=1 224 | graph.last.stroke.color=255, 255, 255, 128 225 | bpm.primary.stroke.style=solid ; ↓ BPM の主罫線の設定。 226 | bpm.primary.stroke.width=1 227 | bpm.primary.stroke.color=255, 255, 255, 128 228 | bpm.primary.text.height=12 229 | bpm.primary.text.color=255, 255, 255, 204 230 | bpm.primary.text.shadow.dilate=1.000000 231 | bpm.primary.text.shadow.blur=1.000000 232 | bpm.primary.text.shadow.offset.x=0 233 | bpm.primary.text.shadow.offset.y=0 234 | bpm.primary.text.shadow.color=0, 0, 0, 128 235 | bpm.secondary.stroke.style=dashed ; ↓ BPM の主罫線の設定。 236 | bpm.secondary.stroke.width=1 237 | bpm.secondary.stroke.color=255, 255, 255, 128 238 | ``` 239 | 240 | ## 更新履歴 241 | 242 | * 7.3.1 - 2024/11/11 🩹アイテムを一定数追加したときエラーになる問題に対応 243 | * 7.3.0 - 2024/03/16 指定されたアイテムを除外できる機能を追加 244 | * 7.2.0 - 2023/08/23 リファクタリング 245 | * 7.1.0 - 2023/07/17 リーダープロセスをマルチスレッド化 246 | * 7.0.0 - 2023/07/07 BPM 表示機能を追加 247 | * 6.4.1 - 2023/04/14 音声アイテムにフィルタを付けたときの問題を修正 248 | * 6.4.0 - 2023/03/30 音声波形をテキストより後ろに描画する機能を追加 249 | * 6.3.0 - 2023/03/29 全体の音声波形ウィンドウの位置を記憶するように修正 250 | * 6.2.0 - 2023/03/27 描画モードを変更できる機能を追加 251 | * 6.1.0 - 2023/03/27 描画幅を変更できる機能を追加 252 | * 6.0.0 - 2023/03/26 音声データの計算をマルチプロセスで行える機能を追加 253 | * 5.0.0 - 2023/03/25 全体の音声波形を表示する機能を追加、24bit PCM データに対応 254 | * 4.0.1 - 2023/03/22 32bit PCM データに対応 255 | * 4.0.0 - 2023/03/21 UI を変更 256 | * 3.2.0 - 2023/03/21 XOR モードを追加 257 | * 3.1.0 - 2023/03/20 ズームアウト時に描画が重くなる問題に対応 258 | * 3.0.0 - 2023/03/19 外部プロセスで音声データの計算を行うように変更 259 | * 2.3.0 - 2022/08/08 テキストのスクロールを無効化する機能を追加 260 | * 2.2.0 - 2022/07/30 プレビュー中は何もしないように変更 261 | * 2.1.0 - 2022/05/22 縮小率の上限を 4000 に変更 262 | * 2.0.0 - 2022/04/26 更新モードを変更 263 | * 1.0.1 - 2022/04/21 保存中は何もしないように修正 264 | * 1.0.0 - 2022/04/20 初版 265 | 266 | ## 動作確認 267 | 268 | * (必須) AviUtl 1.10 & 拡張編集 0.92 http://spring-fragrance.mints.ne.jp/aviutl/ 269 | * (共存確認) patch.aul r43 謎さうなフォーク版29 https://scrapbox.io/nazosauna/patch.aul 270 | 271 | ## クレジット 272 | 273 | * Microsoft Research Detours Package https://github.com/microsoft/Detours 274 | * aviutl_exedit_sdk https://github.com/ePi5131/aviutl_exedit_sdk 275 | * Common Library https://github.com/hebiiro/Common-Library 276 | 277 | ## 作成者情報 278 | 279 | * 作成者 - 蛇色 (へびいろ) 280 | * GitHub - https://github.com/hebiiro 281 | * Twitter - https://twitter.com/io_hebiiro 282 | 283 | ## 免責事項 284 | 285 | この作成物および同梱物を使用したことによって生じたすべての障害・損害・不具合等に関しては、私と私の関係者および私の所属するいかなる団体・組織とも、一切の責任を負いません。各自の責任においてご使用ください。 286 | -------------------------------------------------------------------------------- /ReaderProcess/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Plugin.h" 4 | #include "Calc/Hive.h" 5 | #include "Calc/Worker.h" 6 | 7 | inline struct App 8 | { 9 | HINSTANCE m_instance; 10 | HWND m_client; 11 | Event m_event; 12 | SimpleFileMappingT m_shared; 13 | Input::PluginPtr m_plugin; 14 | Input::MediaPtr m_media; 15 | 16 | BOOL init(HINSTANCE instance) 17 | { 18 | MY_TRACE(_T("App::init()\n")); 19 | 20 | m_instance = instance; 21 | 22 | // クライアントプロセスのウィンドウハンドルを取得する。 23 | m_client = (HWND)_tcstoul(::GetCommandLine(), 0, 0); 24 | MY_TRACE_HEX(m_client); 25 | if (!m_client) return FALSE; 26 | 27 | // ここはクライアントプロセスより先に処理される可能性がある。 28 | // その場合、イベントのオープンには失敗してもよい。 29 | // 共有メモリの確保は成功するのが前提なので open() は使用できない。 30 | 31 | DWORD tid = ::GetCurrentThreadId(); 32 | m_event.open(EVENT_ALL_ACCESS, FALSE, getReaderEventName(tid)); 33 | m_shared.init(getSharedReaderBottleName(tid)); 34 | 35 | return initPlugin(); 36 | } 37 | 38 | BOOL term() 39 | { 40 | MY_TRACE(_T("App::term()\n")); 41 | 42 | return termPlugin(); 43 | } 44 | 45 | BOOL initPlugin() 46 | { 47 | MY_TRACE(_T("App::initPlugin()\n")); 48 | 49 | TCHAR fileName[MAX_PATH] = {}; 50 | ::GetModuleFileName(0, fileName, MAX_PATH); 51 | ::PathRemoveFileSpec(fileName); 52 | ::PathAppend(fileName, _T("..\\lwinput.aui")); 53 | MY_TRACE_TSTR(fileName); 54 | 55 | m_plugin = std::make_shared(fileName); 56 | 57 | return !!m_plugin->getInputPlugin(); 58 | } 59 | 60 | BOOL termPlugin() 61 | { 62 | MY_TRACE(_T("App::termPlugin()\n")); 63 | 64 | m_plugin = 0; 65 | 66 | return TRUE; 67 | } 68 | 69 | // 70 | // 入力プラグインから音声信号を受け取ります。 71 | // 同時並行して音量を算出します。 72 | // 73 | BOOL receive() 74 | { 75 | MY_TRACE(_T("App::receive()\n")); 76 | 77 | // イベントが発生するまで待つ。 78 | if (m_event) 79 | ::WaitForSingleObject(m_event, INFINITE); 80 | 81 | // 共有メモリを取得する。 82 | ReaderBottle* shared = m_shared.getBuffer(); 83 | if (!shared) return FALSE; 84 | 85 | // 入力プラグインのインターフェイスを取得する。 86 | AviUtl::InputPluginDLL* ip = m_plugin->getInputPlugin(); 87 | MY_TRACE_HEX(ip); 88 | if (!ip) return FALSE; 89 | 90 | // メディアを開く。 91 | Input::MediaPtr media = std::make_shared(m_plugin, shared->fileName); 92 | 93 | // メディアのハンドルを取得する。 94 | AviUtl::InputHandle handle = media->getInputHandle(); 95 | MY_TRACE_HEX(handle); 96 | if (!handle) return FALSE; 97 | 98 | // メディア情報を取得する。 99 | MediaInfo* mi = media->getMediaInfo(); 100 | 101 | // バッファのサイズを算出し、バッファを確保する。 102 | int32_t start = 0; 103 | int32_t length = mi->audio_format.nSamplesPerSec / Volume::Resolution; 104 | int32_t bufferSize = length * mi->audio_format.nBlockAlign; 105 | 106 | MY_TRACE_INT(mi->audio_format.wFormatTag); 107 | MY_TRACE_INT(mi->audio_format.nChannels); 108 | MY_TRACE_INT(mi->audio_format.nSamplesPerSec); 109 | MY_TRACE_INT(mi->audio_format.nAvgBytesPerSec); 110 | MY_TRACE_INT(mi->audio_format.nBlockAlign); 111 | MY_TRACE_INT(mi->audio_format.wBitsPerSample); 112 | MY_TRACE_INT(length); 113 | MY_TRACE_INT(bufferSize); 114 | 115 | // 入力プラグインを使用して音声信号を読み込む。 116 | 117 | DWORD startTime = ::timeGetTime(); 118 | 119 | // 計算に必要なデータをハイブに格納しておく。 120 | Calc::hive.setBottle(shared); 121 | Calc::hive.setAudioFormat(mi->audio_format); 122 | 123 | // ワークの配列。 124 | std::vector works(Volume::MaxCount); 125 | 126 | // 読み込んだフレーム数。 127 | int c = Volume::MaxCount; 128 | 129 | // 最大フレーム数までループする。 130 | // ただし、読み込む音声信号がなくなった場合はそこでループは終了する。 131 | for (int i = 0; i < Volume::MaxCount; i++) 132 | { 133 | // 音声信号を受け取るためのバッファを確保する。 134 | Calc::BufferPtr buffer = std::make_shared(bufferSize); 135 | 136 | // AviUtl の入力プラグインを使用して音声信号を取得する。 137 | int32_t read = ip->func_read_audio(handle, start, length, buffer->data()); 138 | 139 | if (read == 0) // 音声信号を読み込めなかった場合は 140 | { 141 | c = i; // 読み込んだフレーム数をセットしてから 142 | 143 | break; // ループを終了する。 144 | } 145 | 146 | // 読み取った分だけ start を進める。 147 | start += read; 148 | 149 | // バッファのサイズを読み取った分だけにする。 150 | buffer->resize(read * mi->audio_format.nBlockAlign); 151 | 152 | // ワーカーを作成する。 153 | Calc::Worker* worker = Calc::Worker::create(i, buffer); 154 | 155 | // スレッドプールワークを作成する。 156 | works[i] = ::CreateThreadpoolWork(Calc::Worker::WorkCallback, worker, 0); 157 | 158 | // スレッドプールワークを開始する。 159 | ::SubmitThreadpoolWork(works[i]); 160 | 161 | if (read < length) // 音声信号が想定より少なかった場合は 162 | { 163 | c = i + 1; // 読み込んだフレーム数をセットしてから 164 | 165 | break; // ループを終了する。 166 | } 167 | } 168 | 169 | // 読み込んだフレーム数。 170 | shared->volumeCount = c; 171 | 172 | // 読み込んだフレーム数の分だけ、スレッドプールワークの終了を待つ。 173 | for (int i = 0; i < c; i++) 174 | { 175 | ::WaitForThreadpoolWorkCallbacks(works[i], FALSE); 176 | ::CloseThreadpoolWork(works[i]); 177 | } 178 | 179 | DWORD endTime = ::timeGetTime(); 180 | 181 | MY_TRACE(_T("所要時間 = %f秒\n"), (endTime - startTime) / 1000.0); 182 | 183 | return TRUE; 184 | } 185 | 186 | // 187 | // クライアントプロセスに算出した音量を送ります。(受け取るように促します) 188 | // 189 | BOOL send() 190 | { 191 | MY_TRACE(_T("App::send()\n")); 192 | 193 | DWORD id = ::GetCurrentThreadId(); // 共有メモリを識別するために必要です。 194 | 195 | return ::PostMessage(m_client, WM_AVIUTL_FILTER_RECEIVE, (WPARAM)id, 0); 196 | } 197 | } app; 198 | -------------------------------------------------------------------------------- /ReaderProcess/Calc/Hive.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Calc 4 | { 5 | #pragma pack(1) 6 | // 7 | // この構造体は 24bit 整数計算を行うために使用されます。 8 | // 9 | struct int24_t { 10 | BYTE n[3]; 11 | operator int32_t() const { 12 | struct { 13 | int32_t n:24; 14 | } s = { *(int32_t*)n }; 15 | return s.n; 16 | } 17 | }; 18 | #pragma pack() 19 | 20 | // 21 | // このクラスは計算に必要な変数を保持します。 22 | // 23 | inline struct Hive 24 | { 25 | // 26 | // 計算結果を格納するための変数です。 27 | // 28 | ReaderBottle* bottle; 29 | 30 | // 31 | // 計算に必要な変数です。 32 | // 33 | WAVEFORMATEX audio_format; 34 | 35 | // 36 | // 計算を実行する前にこの関数を呼び出して 37 | // 計算結果を格納するボトルをセットしてください。 38 | // 39 | void setBottle(ReaderBottle* bottle) 40 | { 41 | this->bottle = bottle; 42 | } 43 | 44 | // 45 | // 計算を実行する前にこの関数を呼び出して 46 | // 計算に必要なオーディオフォーマットをセットしてください。 47 | // 48 | void setAudioFormat(const WAVEFORMATEX& audio_format) 49 | { 50 | this->audio_format = audio_format; 51 | } 52 | } hive; 53 | } 54 | -------------------------------------------------------------------------------- /ReaderProcess/Calc/Worker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Hive.h" 3 | 4 | namespace Calc 5 | { 6 | using Buffer = std::vector; 7 | using BufferPtr = std::shared_ptr; 8 | 9 | // 10 | // このクラスは音声信号から音量を算出します。 11 | // 12 | struct Worker 13 | { 14 | // 15 | // 計算対象のフレーム番号です。 16 | // 17 | int i; 18 | 19 | // 20 | // 計算対象のフレームの音声信号です。 21 | // 22 | BufferPtr buffer; 23 | 24 | static Worker* create(int i, const BufferPtr& buffer) 25 | { 26 | return new Worker(i, buffer); 27 | } 28 | 29 | static VOID CALLBACK WorkCallback( 30 | _Inout_ PTP_CALLBACK_INSTANCE Instance, 31 | _Inout_opt_ PVOID Context, 32 | _Inout_ PTP_WORK Work) 33 | { 34 | Worker* worker = (Worker*)Context; 35 | worker->calcVolume(); 36 | delete worker; 37 | } 38 | 39 | Worker(int i, const BufferPtr& buffer) 40 | : i(i) 41 | , buffer(buffer) 42 | { 43 | } 44 | 45 | void calcVolume() 46 | { 47 | Volume volume = {}; 48 | switch (hive.audio_format.wBitsPerSample) 49 | { 50 | case 8: volume.level = calc((const int8_t*)buffer->data(), (int)(buffer->size() / sizeof( int8_t))); break; 51 | case 16: volume.level = calc((const int16_t*)buffer->data(), (int)(buffer->size() / sizeof(int16_t))); break; 52 | case 24: volume.level = calc((const int24_t*)buffer->data(), (int)(buffer->size() / sizeof(int24_t))); break; 53 | case 32: volume.level = calc((const int32_t*)buffer->data(), (int)(buffer->size() / sizeof(int32_t))); break; 54 | default: volume.level = 0.0f; break; 55 | } 56 | hive.bottle->volumes[i] = volume; 57 | 58 | MY_TRACE(_T("i = %d, level = %f\n"), i, volume.level); 59 | } 60 | 61 | // 62 | // 受け取った 8bit の音声信号を -1.0 ~ 1.0 に正規化して返します。 63 | // 64 | static float normalize(int8_t pcm) 65 | { 66 | return pcm / 128.0f; 67 | } 68 | 69 | // 70 | // 受け取った 16bit の音声信号を -1.0 ~ 1.0 に正規化して返します。 71 | // 72 | static float normalize(int16_t pcm) 73 | { 74 | return pcm / 32768.0f; 75 | } 76 | 77 | // 78 | // 受け取った 24bit の音声信号を -1.0 ~ 1.0 に正規化して返します。 79 | // 80 | static float normalize(int24_t pcm) 81 | { 82 | return pcm / 8388608.0f; 83 | } 84 | 85 | // 86 | // 受け取った 32bit の音声信号を -1.0 ~ 1.0 に正規化して返します。 87 | // 88 | static float normalize(int32_t pcm) 89 | { 90 | return pcm / 2147483648.0f; 91 | } 92 | 93 | // 94 | // 受け取った 32bit 浮動小数点数の音声信号をそのまま返します。 95 | // 96 | static float normalize(float pcm) 97 | { 98 | return pcm; 99 | } 100 | 101 | template 102 | static float calc(const T* pcms, int count) 103 | { 104 | if (!count) return 0.0f; 105 | 106 | float level = 0.0f; 107 | for (int i = 0; i < count; i++) 108 | { 109 | T pcm = pcms[i]; 110 | float n = normalize(pcm); 111 | level += n * n; 112 | } 113 | return sqrtf(level / (float)count); 114 | } 115 | }; 116 | } 117 | -------------------------------------------------------------------------------- /ReaderProcess/Plugin.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Plugin.h" 3 | 4 | //-------------------------------------------------------------------- 5 | namespace Input { 6 | //-------------------------------------------------------------------- 7 | 8 | Plugin::Plugin(LPCTSTR fileName) 9 | { 10 | MY_TRACE(_T("Plugin::Plugin()\n")); 11 | 12 | // プラグイン DLL をロードする。 13 | m_aui = ::LoadLibrary(fileName); 14 | MY_TRACE_HEX(m_aui); 15 | if (!m_aui) return; 16 | 17 | // プラグイン関数を取得する。 18 | Type_GetInputPluginTable GetInputPluginTable = 19 | (Type_GetInputPluginTable)::GetProcAddress(m_aui, "GetInputPluginTable"); 20 | MY_TRACE_HEX(GetInputPluginTable); 21 | if (!GetInputPluginTable) return; 22 | 23 | // プラグインテーブルを取得する。 24 | m_inputPluginTable = GetInputPluginTable(); 25 | MY_TRACE_HEX(m_inputPluginTable); 26 | if (!m_inputPluginTable) return; 27 | 28 | // プラグインを初期化する。 29 | if (m_inputPluginTable->func_init) 30 | m_inputPluginTable->func_init(); 31 | } 32 | 33 | Plugin::~Plugin() 34 | { 35 | MY_TRACE(_T("Plugin::~Plugin()\n")); 36 | 37 | if (!m_aui) 38 | return; 39 | 40 | // プラグインの後始末をする。 41 | if (m_inputPluginTable && m_inputPluginTable->func_exit) 42 | m_inputPluginTable->func_exit(); 43 | 44 | // プラグイン DLL をアンロードする。 45 | ::FreeLibrary(m_aui), m_aui = 0; 46 | } 47 | 48 | AviUtl::InputPluginDLL* Plugin::getInputPlugin() const 49 | { 50 | return m_inputPluginTable; 51 | } 52 | 53 | //-------------------------------------------------------------------- 54 | 55 | Media::Media(PluginPtr plugin, LPCSTR fileName) 56 | { 57 | MY_TRACE(_T("Media::Media(%hs)\n"), fileName); 58 | 59 | m_plugin = plugin; 60 | AviUtl::InputPluginDLL* ip = m_plugin->getInputPlugin(); 61 | 62 | // メディアを開く。 63 | m_fileName = fileName; 64 | MY_TRACE_STR(fileName); 65 | 66 | m_inputHandle = ip->func_open(m_fileName.c_str()); 67 | MY_TRACE_HEX(m_inputHandle); 68 | 69 | if (!m_inputHandle) 70 | return; 71 | 72 | // 入力情報を取得する。 73 | BOOL result = ip->func_info_get(m_inputHandle, &m_inputInfo); 74 | m_mediaInfo.flag = m_inputInfo.flag; 75 | m_mediaInfo.rate = m_inputInfo.rate; 76 | m_mediaInfo.scale = m_inputInfo.scale; 77 | m_mediaInfo.n = m_inputInfo.n; 78 | memcpy(&m_mediaInfo.format, m_inputInfo.format, sizeof(m_mediaInfo.format)); 79 | m_mediaInfo.format.biSize = sizeof(m_mediaInfo.format); 80 | m_mediaInfo.format_size = sizeof(m_mediaInfo.format); 81 | m_mediaInfo.audio_n = m_inputInfo.audio_n; 82 | memcpy(&m_mediaInfo.audio_format, m_inputInfo.audio_format, sizeof(m_mediaInfo.audio_format)); 83 | m_mediaInfo.audio_format.cbSize = sizeof(m_mediaInfo.audio_format); 84 | m_mediaInfo.audio_format_size = sizeof(m_mediaInfo.audio_format); 85 | m_mediaInfo.handler = m_inputInfo.handler; 86 | } 87 | 88 | Media::~Media() 89 | { 90 | MY_TRACE(_T("Media::~Media()\n")); 91 | 92 | // メディアを閉じる。 93 | 94 | if (!m_inputHandle) 95 | return; 96 | 97 | AviUtl::InputPluginDLL* ip = m_plugin->getInputPlugin(); 98 | 99 | ip->func_close(m_inputHandle); 100 | m_inputHandle = 0; 101 | } 102 | 103 | PluginPtr Media::getPlugin() 104 | { 105 | return m_plugin; 106 | } 107 | 108 | LPCSTR Media::getFileName() 109 | { 110 | return m_fileName.c_str(); 111 | } 112 | 113 | AviUtl::InputHandle Media::getInputHandle() 114 | { 115 | return m_inputHandle; 116 | } 117 | 118 | AviUtl::InputInfo* Media::getInputInfo() 119 | { 120 | return &m_inputInfo; 121 | } 122 | 123 | MediaInfo* Media::getMediaInfo() 124 | { 125 | return &m_mediaInfo; 126 | } 127 | 128 | //-------------------------------------------------------------------- 129 | } // namespace Input 130 | //-------------------------------------------------------------------- 131 | -------------------------------------------------------------------------------- /ReaderProcess/Plugin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //-------------------------------------------------------------------- 4 | 5 | struct MediaInfo 6 | { 7 | AviUtl::InputInfo::Flag 8 | flag; // フラグ 9 | int32_t rate,scale; // フレームレート 10 | int32_t n; // フレーム数 11 | BITMAPINFOHEADER format; // 画像フォーマットへのポインタ(次に関数が呼ばれるまで内容を有効にしておく) 12 | int32_t format_size; // 画像フォーマットのサイズ 13 | int32_t audio_n; // 音声サンプル数 14 | WAVEFORMATEX audio_format; // 音声フォーマットへのポインタ(次に関数が呼ばれるまで内容を有効にしておく) 15 | int32_t audio_format_size; // 音声フォーマットのサイズ 16 | DWORD handler; // 画像codecハンドラ 17 | }; 18 | 19 | //-------------------------------------------------------------------- 20 | namespace Input { 21 | //-------------------------------------------------------------------- 22 | 23 | class Plugin; 24 | class Media; 25 | 26 | typedef std::shared_ptr PluginPtr; 27 | typedef std::shared_ptr MediaPtr; 28 | 29 | //-------------------------------------------------------------------- 30 | 31 | typedef AviUtl::InputPluginDLL* (WINAPI* Type_GetInputPluginTable)(); 32 | 33 | class Plugin 34 | { 35 | public: 36 | 37 | HINSTANCE m_aui = 0; 38 | AviUtl::InputPluginDLL* m_inputPluginTable = 0; 39 | 40 | public: 41 | 42 | Plugin(LPCTSTR fileName); 43 | ~Plugin(); 44 | 45 | AviUtl::InputPluginDLL* getInputPlugin() const; 46 | }; 47 | 48 | //-------------------------------------------------------------------- 49 | 50 | class Media 51 | { 52 | private: 53 | 54 | PluginPtr m_plugin; 55 | std::string m_fileName; 56 | AviUtl::InputHandle m_inputHandle = 0; 57 | AviUtl::InputInfo m_inputInfo = {}; 58 | MediaInfo m_mediaInfo = {}; 59 | 60 | public: 61 | 62 | Media(PluginPtr plugin, LPCSTR fileName); 63 | ~Media(); 64 | 65 | PluginPtr getPlugin(); 66 | LPCSTR getFileName(); 67 | AviUtl::InputHandle getInputHandle(); 68 | AviUtl::InputInfo* getInputInfo(); 69 | MediaInfo* getMediaInfo(); 70 | }; 71 | 72 | //-------------------------------------------------------------------- 73 | } // namespace Input 74 | //-------------------------------------------------------------------- 75 | -------------------------------------------------------------------------------- /ReaderProcess/ReaderProcess.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "App.h" 3 | #include "Common/Tracer2.h" 4 | 5 | int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow) 6 | { 7 | struct Initializer 8 | { 9 | Initializer() 10 | { 11 | _tsetlocale(LC_CTYPE, _T("")); 12 | trace_init(0, 0, TRUE); 13 | ::OleInitialize(0); 14 | } 15 | 16 | ~Initializer() 17 | { 18 | trace_term(); 19 | ::OleUninitialize(); 20 | } 21 | 22 | } initializer; 23 | 24 | MY_TRACE(_T("WinMain()\n")); 25 | 26 | app.init(instance); 27 | app.receive(); 28 | app.send(); 29 | app.term(); 30 | 31 | MY_TRACE(_T("プロセスが正常終了しました\n")); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /ReaderProcess/ReaderProcess.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {DB2053E8-60D4-4BD5-845A-11CA24E2C599} 25 | ReaderProcess 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | false 82 | 83 | 84 | true 85 | 86 | 87 | false 88 | 89 | 90 | 91 | Level3 92 | true 93 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 94 | true 95 | Use 96 | pch.h 97 | stdcpplatest 98 | 99 | 100 | Windows 101 | true 102 | 103 | 104 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\MySpace\AviUtl\AviUtl110_test\Plugins\$(SolutionName)\$(TargetFileName)" 105 | 106 | 107 | 108 | 109 | 110 | Level3 111 | true 112 | true 113 | true 114 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 115 | true 116 | Use 117 | pch.h 118 | stdcpplatest 119 | 120 | 121 | Windows 122 | true 123 | true 124 | true 125 | 126 | 127 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\MySpace\AviUtl\AviUtl110_test\Plugins\$(SolutionName)\$(TargetFileName)" 128 | 129 | 130 | 131 | 132 | 133 | Level3 134 | true 135 | _DEBUG;_WINDOWS;%(PreprocessorDefinitions) 136 | true 137 | Use 138 | pch.h 139 | stdcpplatest 140 | 141 | 142 | Windows 143 | true 144 | 145 | 146 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\AviUtl110_test\Plugins\$(SolutionName)\$(TargetFileName)" 147 | 148 | 149 | 150 | 151 | 152 | Level3 153 | true 154 | true 155 | true 156 | NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 157 | true 158 | Use 159 | pch.h 160 | stdcpplatest 161 | 162 | 163 | Windows 164 | true 165 | true 166 | true 167 | 168 | 169 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\AviUtl110_test\Plugins\$(SolutionName)\$(TargetFileName)" 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | Create 186 | Create 187 | Create 188 | Create 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /ReaderProcess/ReaderProcess.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {b2b8b579-a036-4aeb-aa10-399e689a71f3} 6 | 7 | 8 | {6fb733bc-2940-49c6-a089-11b3123c8b78} 9 | 10 | 11 | 12 | 13 | Framework 14 | 15 | 16 | Framework 17 | 18 | 19 | Framework 20 | 21 | 22 | 23 | 24 | Calc 25 | 26 | 27 | Calc 28 | 29 | 30 | 31 | 32 | Framework 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /ReaderProcess/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | #define WIN32_LEAN_AND_MEAN 5 | #define NOMINMAX 6 | #include 7 | #include 8 | #pragma comment(lib, "shlwapi.lib") 9 | #include 10 | #include 11 | #include 12 | #pragma comment(lib, "winmm.lib") 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "aviutl.hpp" 24 | #include "exedit.hpp" 25 | #include "Common/Tracer.h" 26 | #include "Common/WinUtility.h" 27 | #include "Common/Profile.h" 28 | #include "../ShowWaveform/Share.h" 29 | -------------------------------------------------------------------------------- /ReaderProcess/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /ReaderProcess/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "framework.h" 4 | -------------------------------------------------------------------------------- /ReaderProcess/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // // SDKDDKVer.h をインクルードすると、利用できる最も高いレベルの Windows プラットフォームが定義されます。 4 | // 以前の Windows プラットフォーム用にアプリケーションをビルドする場合は、WinSDKVer.h をインクルードし、 5 | // サポートしたいプラットフォームに _WIN32_WINNT マクロを設定してから SDKDDKVer.h をインクルードします。 6 | #include 7 | -------------------------------------------------------------------------------- /ShowWaveform.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31424.327 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShowWaveform", "ShowWaveform\ShowWaveform.vcxproj", "{8E583504-3780-4129-BCC2-BA590DBD0D0E}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3BA88203-63EF-4334-AF22-39C789AA8406}" 9 | ProjectSection(SolutionItems) = preProject 10 | CREDITS.md = CREDITS.md 11 | LICENSE = LICENSE 12 | README.md = README.md 13 | EndProjectSection 14 | EndProject 15 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OutProcess", "OutProcess\OutProcess.vcxproj", "{3E78D513-8512-4A92-8896-6C1E074647EA}" 16 | EndProject 17 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReaderProcess", "ReaderProcess\ReaderProcess.vcxproj", "{DB2053E8-60D4-4BD5-845A-11CA24E2C599}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|x64 = Debug|x64 22 | Debug|x86 = Debug|x86 23 | Release|x64 = Release|x64 24 | Release|x86 = Release|x86 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {8E583504-3780-4129-BCC2-BA590DBD0D0E}.Debug|x64.ActiveCfg = Debug|x64 28 | {8E583504-3780-4129-BCC2-BA590DBD0D0E}.Debug|x64.Build.0 = Debug|x64 29 | {8E583504-3780-4129-BCC2-BA590DBD0D0E}.Debug|x86.ActiveCfg = Debug|Win32 30 | {8E583504-3780-4129-BCC2-BA590DBD0D0E}.Debug|x86.Build.0 = Debug|Win32 31 | {8E583504-3780-4129-BCC2-BA590DBD0D0E}.Release|x64.ActiveCfg = Release|x64 32 | {8E583504-3780-4129-BCC2-BA590DBD0D0E}.Release|x64.Build.0 = Release|x64 33 | {8E583504-3780-4129-BCC2-BA590DBD0D0E}.Release|x86.ActiveCfg = Release|Win32 34 | {8E583504-3780-4129-BCC2-BA590DBD0D0E}.Release|x86.Build.0 = Release|Win32 35 | {3E78D513-8512-4A92-8896-6C1E074647EA}.Debug|x64.ActiveCfg = Debug|x64 36 | {3E78D513-8512-4A92-8896-6C1E074647EA}.Debug|x64.Build.0 = Debug|x64 37 | {3E78D513-8512-4A92-8896-6C1E074647EA}.Debug|x86.ActiveCfg = Debug|Win32 38 | {3E78D513-8512-4A92-8896-6C1E074647EA}.Debug|x86.Build.0 = Debug|Win32 39 | {3E78D513-8512-4A92-8896-6C1E074647EA}.Release|x64.ActiveCfg = Release|x64 40 | {3E78D513-8512-4A92-8896-6C1E074647EA}.Release|x64.Build.0 = Release|x64 41 | {3E78D513-8512-4A92-8896-6C1E074647EA}.Release|x86.ActiveCfg = Release|Win32 42 | {3E78D513-8512-4A92-8896-6C1E074647EA}.Release|x86.Build.0 = Release|Win32 43 | {DB2053E8-60D4-4BD5-845A-11CA24E2C599}.Debug|x64.ActiveCfg = Debug|x64 44 | {DB2053E8-60D4-4BD5-845A-11CA24E2C599}.Debug|x64.Build.0 = Debug|x64 45 | {DB2053E8-60D4-4BD5-845A-11CA24E2C599}.Debug|x86.ActiveCfg = Debug|Win32 46 | {DB2053E8-60D4-4BD5-845A-11CA24E2C599}.Debug|x86.Build.0 = Debug|Win32 47 | {DB2053E8-60D4-4BD5-845A-11CA24E2C599}.Release|x64.ActiveCfg = Release|x64 48 | {DB2053E8-60D4-4BD5-845A-11CA24E2C599}.Release|x64.Build.0 = Release|x64 49 | {DB2053E8-60D4-4BD5-845A-11CA24E2C599}.Release|x86.ActiveCfg = Release|Win32 50 | {DB2053E8-60D4-4BD5-845A-11CA24E2C599}.Release|x86.Build.0 = Release|Win32 51 | EndGlobalSection 52 | GlobalSection(SolutionProperties) = preSolution 53 | HideSolutionNode = FALSE 54 | EndGlobalSection 55 | GlobalSection(ExtensibilityGlobals) = postSolution 56 | SolutionGuid = {483B1548-7CEB-4168-9525-A4CC4E5C6250} 57 | EndGlobalSection 58 | EndGlobal 59 | -------------------------------------------------------------------------------- /ShowWaveform/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "FileCache.h" 4 | #include "ItemCache.h" 5 | #include "SubProcess.h" 6 | #include "SubThread.h" 7 | #include "MainDialog.h" 8 | 9 | //-------------------------------------------------------------------- 10 | // Api Hook 11 | 12 | DECLARE_HOOK_PROC(void, CDECL, DrawObject, (HDC dc, int objectIndex)); 13 | DECLARE_HOOK_PROC(BOOL, WINAPI, DrawObjectText, (HDC dc, int x, int y, UINT options, LPCRECT rc, LPCSTR text, UINT c, CONST INT* dx)); 14 | 15 | //-------------------------------------------------------------------- 16 | 17 | struct App 18 | { 19 | struct ShowType { 20 | static const int Both = 0; 21 | static const int Min = 1; 22 | static const int Max = 2; 23 | }; 24 | 25 | struct UpdateMode { 26 | static const int Off = 0; 27 | static const int On = 1; 28 | static const int OnWithoutPlaying = 2; 29 | }; 30 | 31 | struct XORMode { 32 | static const int None = 0; 33 | static const int XOR = 1; 34 | static const int NotXOR = 2; 35 | static const int Not = 3; 36 | }; 37 | 38 | AviUtlInternal m_auin; 39 | HINSTANCE m_instance = 0; 40 | AviUtl::FilterPlugin* m_fp = 0; 41 | AviUtl::FileInfo m_fi = {}; 42 | int32_t m_currentFrame = 0; 43 | int32_t m_drawing_object_index = -1; 44 | FileCacheManager m_fileCacheManager; 45 | ItemCacheManager m_itemCacheManager; 46 | SubProcess m_subProcess; 47 | SubThreadManager m_subThreadManager; 48 | MainDialog m_mainDialog; 49 | 50 | int (*CallShowColorDialog)(DWORD u1, COLORREF* color, DWORD u3) = 0; 51 | 52 | BOOL m_exists = FALSE; 53 | int m_scale = 100; 54 | int m_showType = ShowType::Both; 55 | int m_updateMode = UpdateMode::On; 56 | int m_xorMode = XORMode::XOR; 57 | COLORREF m_penColor = RGB(0x00, 0xff, 0xff); 58 | COLORREF m_brushColor = RGB(0x00, 0xff, 0xff); 59 | BOOL m_showWaveform = TRUE; 60 | BOOL m_showText = TRUE; 61 | BOOL m_noScrollText = TRUE; 62 | BOOL m_behind = FALSE; 63 | std::set m_includeLayers; 64 | std::set m_excludeLayers; 65 | _bstr_t m_excludeDir = L""; 66 | 67 | App(); 68 | ~App(); 69 | 70 | BOOL DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved); 71 | BOOL func_init(AviUtl::FilterPlugin* fp); 72 | BOOL func_exit(AviUtl::FilterPlugin* fp); 73 | BOOL func_proc(AviUtl::FilterPlugin* fp, AviUtl::FilterProcInfo* fpip); 74 | BOOL func_update(AviUtl::FilterPlugin* fp, AviUtl::FilterPlugin::UpdateStatus status); 75 | BOOL func_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, AviUtl::EditHandle* editp, AviUtl::FilterPlugin* fp); 76 | BOOL func_project_load(AviUtl::FilterPlugin* fp, AviUtl::EditHandle* editp, void* data, int32_t size); 77 | BOOL func_project_save(AviUtl::FilterPlugin* fp, AviUtl::EditHandle* editp, void* data, int32_t* size); 78 | 79 | void load(); 80 | void save(); 81 | BOOL createDialog(); 82 | BOOL updateProjectParams(); 83 | BOOL updateItemCache(BOOL send); 84 | BOOL sendTotalsParams(TotalsParams* params); // サブプロセスに値を送る。 85 | TotalsParamsPtr receiveTotalsParams(); // 共有メモリから値を取得する。 86 | void drawWaveform(HDC dc, LPCRECT rcClip, LPCRECT rcItem); 87 | 88 | void setScale(int scale); 89 | void setShowType(int showType); 90 | void setUpdateMode(int updateMode); 91 | void setXORMode(int xorMode); 92 | void selectPenColor(); 93 | void selectBrushColor(); 94 | void clearAllCache(); 95 | void showFull(); 96 | void setShowWaveform(BOOL showWaveform); 97 | void setShowText(BOOL showText); 98 | void setNoScrollText(BOOL noScrollText); 99 | void setBehind(BOOL behind); 100 | void setIncludeLayers(LPCTSTR text); 101 | void setExcludeLayers(LPCTSTR text); 102 | void setExcludeDir(LPCTSTR text); 103 | 104 | _bstr_t set_to_text(const std::set& set); 105 | void text_to_set(std::set& set, LPCTSTR text); 106 | 107 | BOOL isCacheRequired(ExEdit::Object* object, const AudioParamsPtr& params); 108 | }; 109 | 110 | extern App theApp; 111 | 112 | //-------------------------------------------------------------------- 113 | -------------------------------------------------------------------------------- /ShowWaveform/FileCache.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "FileCache.h" 3 | #include "App.h" 4 | 5 | //--------------------------------------------------------------------- 6 | 7 | FileCachePtr FileCacheManager::getCache(LPCSTR fileName, BOOL create) 8 | { 9 | if (strlen(fileName) == 0) 10 | return 0; 11 | 12 | auto it = cacheMap.find(fileName); 13 | if (it != cacheMap.end()) 14 | { 15 | if (it->second->video_scale == theApp.m_fi.video_scale && 16 | it->second->video_rate == theApp.m_fi.video_rate) 17 | { 18 | return it->second; // キャッシュが見つかったのでそれを返す。 19 | } 20 | } 21 | 22 | if (create) 23 | { 24 | // キャッシュが存在しないので作成する。 25 | createCache(fileName); 26 | } 27 | 28 | return 0; 29 | } 30 | 31 | BOOL FileCacheManager::createCache(LPCSTR fileName) 32 | { 33 | MY_TRACE(_T("FileCacheManager::createCache(%hs)\n"), fileName); 34 | 35 | // サブスレッドマネージャにキャッシュの作成を要請する。 36 | return theApp.m_subThreadManager.requestCache(fileName); 37 | } 38 | 39 | BOOL FileCacheManager::receiveCache() 40 | { 41 | MY_TRACE(_T("FileCacheManager::receiveCache()\n")); 42 | 43 | // 受け取り用のボトルを取得する。 44 | ReceiverBottle* shared = ::shared.receiverBottle.getBuffer(); 45 | if (!shared) return FALSE; 46 | 47 | MY_TRACE_STR(shared->fileName); 48 | MY_TRACE_INT(shared->volumeCount); 49 | 50 | // キャッシュを更新する。 51 | FileCachePtr cache = std::make_shared(); 52 | cache->video_scale = theApp.m_fi.video_scale; 53 | cache->video_rate = theApp.m_fi.video_rate; 54 | cache->volumes.insert(cache->volumes.end(), 55 | shared->volumes, shared->volumes + shared->volumeCount); 56 | cacheMap[shared->fileName] = cache; 57 | 58 | return TRUE; 59 | } 60 | 61 | //--------------------------------------------------------------------- 62 | -------------------------------------------------------------------------------- /ShowWaveform/FileCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ShowWaveform.h" 4 | 5 | //--------------------------------------------------------------------- 6 | 7 | struct FileCache { 8 | int32_t video_scale; 9 | int32_t video_rate; 10 | VolumeArray volumes; 11 | }; 12 | 13 | struct FileCacheManager { 14 | FileCacheMap cacheMap; 15 | FileCachePtr getCache(LPCSTR fileName, BOOL create); 16 | BOOL createCache(LPCSTR fileName); 17 | BOOL receiveCache(); 18 | }; 19 | 20 | //--------------------------------------------------------------------- 21 | -------------------------------------------------------------------------------- /ShowWaveform/ItemCache.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ItemCache.h" 3 | #include "App.h" 4 | 5 | //--------------------------------------------------------------------- 6 | 7 | ItemCachePtr ItemCacheManager::getCache(int32_t object_index) 8 | { 9 | auto it = cacheMap.find(object_index); 10 | if (it == cacheMap.end()) return 0; 11 | return it->second; 12 | } 13 | 14 | BOOL ItemCacheManager::update(BOOL send) 15 | { 16 | MY_TRACE(_T("ItemCacheManager::update(%d)\n"), send); 17 | 18 | std::vector updateItems; 19 | 20 | // 無効なキャッシュを削除する。 21 | for (auto it = cacheMap.begin(); it != cacheMap.end();) 22 | { 23 | auto object = theApp.m_auin.GetObject(it->first); 24 | 25 | if (!(object->flag & ExEdit::Object::Flag::Exist) || 26 | !(object->flag & ExEdit::Object::Flag::Sound)) 27 | { 28 | it->second->params->flag = (uint32_t)object->flag; 29 | updateItems.emplace_back(it->second->params); 30 | cacheMap.erase(it++); 31 | } 32 | else 33 | { 34 | it++; 35 | } 36 | } 37 | 38 | BOOL isCacheCompleted = TRUE; 39 | 40 | // 現在のシーン内のアイテムを列挙する。 41 | int c = theApp.m_auin.GetCurrentSceneObjectCount(); 42 | for (int i = 0; i < c; i++) 43 | { 44 | // オブジェクトを取得する。 45 | ExEdit::Object* object = theApp.m_auin.GetSortedObject(i); 46 | 47 | // オブジェクトのフラグを調べる。 48 | if (!(object->flag & ExEdit::Object::Flag::Sound)) 49 | continue; // 音声波形を取得できるのはサウンドタイプのアイテムのみ。 50 | 51 | // オブジェクトのインデックスを取得します。 52 | auto object_index = theApp.m_auin.get_object_index(object); 53 | if (object_index < 0) continue; 54 | 55 | // すでにキャッシュが作成済みなら 56 | auto it = cacheMap.find(object_index); 57 | if (it != cacheMap.end()) 58 | { 59 | ItemCachePtr cache = it->second; 60 | 61 | // オブジェクトの状態を調べる。 62 | if (!isChanged(cache, object)) 63 | continue; // オブジェクトの状態に変化がないときは何もしない。 64 | } 65 | 66 | // キャッシュを更新する。 67 | ItemCachePtr cache = update(send, object_index, object); 68 | if (cache) 69 | { 70 | updateItems.emplace_back(cache->params); 71 | theApp.m_auin.RedrawLayer(object->layer_set); 72 | } 73 | else 74 | { 75 | // キャッシュをコンプリートできなかった。 76 | isCacheCompleted = FALSE; 77 | } 78 | } 79 | 80 | // 更新が必要なアイテムが存在しない場合はここで処理終了。 81 | if (updateItems.empty()) 82 | return FALSE; 83 | 84 | // 更新が必要なアイテムを通知する。 85 | for (auto& item : updateItems) 86 | theApp.m_subThreadManager.notifyItemChanged(item); 87 | 88 | // キャッシュをコンプリートできている場合のみ再描画をリクエストする。 89 | if (isCacheCompleted) 90 | theApp.m_subThreadManager.requestRedraw(); 91 | 92 | return TRUE; 93 | } 94 | 95 | ItemCachePtr ItemCacheManager::update(BOOL send, int32_t object_index, ExEdit::Object* object) 96 | { 97 | MY_TRACE(_T("ItemCacheManager::update(%d, %d, 0x%08X)\n"), send, object_index, object); 98 | 99 | // 音声アイテムのパラメータを取得する。 100 | AudioParamsPtr params = getAudioParams(object); 101 | if (!params) return 0; 102 | 103 | // このオブジェクトのキャッシュが要求されているかチェックする。 104 | if (!theApp.isCacheRequired(object, params)) return FALSE; 105 | 106 | // ファイルキャシュを取得する。 107 | FileCachePtr fileCache = theApp.m_fileCacheManager.getCache(params->fileName, send); 108 | if (!fileCache) return 0; // ファイルキャッシュが作成されるまでは何もできない。 109 | 110 | // アイテムキャッシュを作成する。 111 | ItemCachePtr itemCache = std::make_shared(); 112 | cacheMap[object_index] = itemCache; 113 | 114 | // オブジェクトの状態を保存しておく。 115 | itemCache->params = params; 116 | 117 | // 現在のフレームレートの1フレーム毎の音量に変換する。 118 | 119 | double scale = (double)Volume::Resolution * theApp.m_fi.video_scale / theApp.m_fi.video_rate; 120 | int32_t range = object->frame_end - object->frame_begin; 121 | for (int32_t i = 0; i <= range; i++) 122 | { 123 | double temp1 = scale * params->playSpeed * i; 124 | double temp2 = scale * params->playBegin; 125 | int32_t src = (int32_t)(temp1 + temp2); 126 | 127 | if (src >= (int32_t)fileCache->volumes.size()) 128 | break; 129 | 130 | Volume volume = fileCache->volumes[src]; 131 | volume.level *= params->volume; 132 | itemCache->volumes.emplace_back(volume); 133 | } 134 | 135 | return itemCache; 136 | } 137 | 138 | AudioParamsPtr ItemCacheManager::getAudioParams(ExEdit::Object* object) 139 | { 140 | int audioFileIndex = theApp.m_auin.GetFilterIndex(object, 2); // 音声ファイル 141 | if (audioFileIndex == -1) return 0; 142 | 143 | int standardPlayIndex = theApp.m_auin.GetFilterIndex(object, 12); // 標準再生 144 | if (standardPlayIndex == -1) return 0; 145 | 146 | int volumeIndex = object->filter_param[standardPlayIndex].track_begin + 0; 147 | int panIndex = object->filter_param[standardPlayIndex].track_begin + 1; 148 | int playBeginIndex = object->filter_param[audioFileIndex].track_begin + 0; 149 | int playSpeedIndex = object->filter_param[audioFileIndex].track_begin + 1; 150 | 151 | AudioParamsPtr params = std::make_shared(); 152 | params->id = (uint32_t)object; 153 | params->flag = (uint32_t)object->flag; 154 | params->frameBegin = object->frame_begin; 155 | params->frameEnd = object->frame_end; 156 | params->sceneSet = object->scene_set; 157 | params->volume = object->track_value_left[volumeIndex] / 1000.0f; 158 | 159 | ExEdit::LayerSetting* layer = theApp.m_auin.GetLayerSetting(object->layer_set); 160 | params->layerFlag = (uint32_t)layer->flag; 161 | 162 | if (object->check_value[1]) 163 | { 164 | // 同じグループの動画アイテムを探す。 165 | int c = theApp.m_auin.GetObjectCount(); 166 | for (int i = 0; i < c; i++) 167 | { 168 | ExEdit::Object* object2 = theApp.m_auin.GetObjectA(i); 169 | if (!object2) continue; 170 | if (object2->group_belong != object->group_belong) continue; 171 | if (object2->scene_set != object->scene_set) continue; 172 | if (object2->exdata_size != 288) continue; 173 | 174 | int movieFileIndex = theApp.m_auin.GetFilterIndex(object2, 0); // 動画ファイル 175 | if (movieFileIndex == -1) continue; 176 | 177 | int playBeginIndex = object2->filter_param[movieFileIndex].track_begin + 0; 178 | int playSpeedIndex = object2->filter_param[movieFileIndex].track_begin + 1; 179 | 180 | // 拡張データを取得する。 181 | auto exdata = (ExEdit::Exdata::efMovieFile*)theApp.m_auin.GetExdata(object2, 0); 182 | 183 | copyFileName(params->fileName, sizeof(params->fileName), exdata->file); 184 | params->playBegin = object2->track_value_left[playBeginIndex]; 185 | params->playSpeed = object2->track_value_left[playSpeedIndex] / 1000.0f; 186 | 187 | break; 188 | } 189 | } 190 | else 191 | { 192 | // 拡張データを取得する。 193 | auto exdata = (ExEdit::Exdata::efAudioFile*)theApp.m_auin.GetExdata(object, 0); 194 | 195 | copyFileName(params->fileName, sizeof(params->fileName), exdata->file); 196 | params->playBegin = object->track_value_left[playBeginIndex] * theApp.m_fi.video_rate / theApp.m_fi.video_scale / 100; 197 | params->playSpeed = object->track_value_left[playSpeedIndex] / 1000.0f; 198 | } 199 | 200 | return params; 201 | } 202 | 203 | BOOL ItemCacheManager::isChanged(const ItemCachePtr& cache, ExEdit::Object* object) 204 | { 205 | AudioParamsPtr params = getAudioParams(object); 206 | if (!params) return FALSE; 207 | 208 | if (strcmp(cache->params->fileName, params->fileName) != 0) return TRUE; 209 | if (cache->params->volume != params->volume) return TRUE; 210 | if (cache->params->playBegin != params->playBegin) return TRUE; 211 | if (cache->params->playSpeed != params->playSpeed) return TRUE; 212 | if (cache->params->frameEnd != params->frameEnd) return TRUE; 213 | if (cache->params->layerFlag != params->layerFlag) return TRUE; 214 | 215 | return FALSE; 216 | } 217 | 218 | void ItemCacheManager::copyFileName(LPSTR dst, size_t size, LPCSTR src) 219 | { 220 | // フルパスを取得する。 221 | ::GetFullPathNameA(src, size / sizeof(*dst), dst, 0); 222 | 223 | // 小文字に変換する。 224 | size_t length = strlen(dst); 225 | for (size_t i = 0; i < length; i++) 226 | { 227 | if (::IsDBCSLeadByte(dst[i])) 228 | i++; 229 | else 230 | dst[i] = tolower(dst[i]); 231 | } 232 | } 233 | 234 | //--------------------------------------------------------------------- 235 | -------------------------------------------------------------------------------- /ShowWaveform/ItemCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ShowWaveform.h" 4 | 5 | //--------------------------------------------------------------------- 6 | 7 | struct ItemCache { 8 | VolumeArray volumes; 9 | AudioParamsPtr params; 10 | }; 11 | 12 | struct ItemCacheManager { 13 | ItemCacheMap cacheMap; 14 | ItemCachePtr getCache(int32_t object_index); 15 | BOOL update(BOOL send); 16 | ItemCachePtr update(BOOL send, int32_t object_index, ExEdit::Object* object); 17 | AudioParamsPtr getAudioParams(ExEdit::Object* object); 18 | BOOL isChanged(const ItemCachePtr& cache, ExEdit::Object* object); 19 | static void copyFileName(LPSTR dst, size_t size, LPCSTR src); 20 | }; 21 | 22 | //--------------------------------------------------------------------- 23 | -------------------------------------------------------------------------------- /ShowWaveform/MainDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MainDialog.h" 3 | #include "App.h" 4 | 5 | //--------------------------------------------------------------------- 6 | 7 | void MainDialog::ignoreNotification(BOOL ignoreNotification) 8 | { 9 | m_ignoreNotification = ignoreNotification; 10 | } 11 | 12 | INT_PTR MainDialog::onDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 13 | { 14 | switch (message) 15 | { 16 | case WM_COMMAND: 17 | { 18 | MY_TRACE(_T("MainDialog::onDlgProc(WM_COMMAND, 0x%08X, 0x%08X)\n"), wParam, lParam); 19 | 20 | UINT code = HIWORD(wParam); 21 | UINT id = LOWORD(wParam); 22 | HWND sender = (HWND)lParam; 23 | 24 | switch (id) 25 | { 26 | case IDC_SCALE: 27 | { 28 | if (code == EN_UPDATE && !m_ignoreNotification) 29 | { 30 | int scale = (int)::GetDlgItemInt(hwnd, IDC_SCALE, 0, TRUE); 31 | theApp.setScale(scale); 32 | } 33 | 34 | break; 35 | } 36 | case IDC_SHOW_TYPE: 37 | { 38 | if (code == CBN_SELCHANGE) 39 | { 40 | HWND comboBox = ::GetDlgItem(hwnd, IDC_SHOW_TYPE); 41 | int showType = ComboBox_GetCurSel(comboBox); 42 | theApp.setShowType(showType); 43 | } 44 | 45 | break; 46 | } 47 | case IDC_UPDATE_MODE: 48 | { 49 | if (code == CBN_SELCHANGE) 50 | { 51 | HWND comboBox = ::GetDlgItem(hwnd, IDC_UPDATE_MODE); 52 | int updateMode = ComboBox_GetCurSel(comboBox); 53 | theApp.setUpdateMode(updateMode); 54 | } 55 | 56 | break; 57 | } 58 | case IDC_XOR_MODE: 59 | { 60 | if (code == CBN_SELCHANGE) 61 | { 62 | HWND comboBox = ::GetDlgItem(hwnd, IDC_XOR_MODE); 63 | int xorMode = ComboBox_GetCurSel(comboBox); 64 | theApp.setXORMode(xorMode); 65 | } 66 | 67 | break; 68 | } 69 | case IDC_PEN_COLOR: 70 | { 71 | theApp.selectPenColor(); 72 | 73 | break; 74 | } 75 | case IDC_BRUSH_COLOR: 76 | { 77 | theApp.selectBrushColor(); 78 | 79 | break; 80 | } 81 | case IDC_CLEAR: 82 | { 83 | theApp.clearAllCache(); 84 | 85 | break; 86 | } 87 | case IDC_SHOW_FULL: 88 | { 89 | theApp.showFull(); 90 | 91 | break; 92 | } 93 | case IDC_SHOW_WAVEFORM: 94 | { 95 | HWND button = ::GetDlgItem(hwnd, IDC_SHOW_WAVEFORM); 96 | BOOL showWaveform = BST_CHECKED == Button_GetCheck(button); 97 | theApp.setShowWaveform(showWaveform); 98 | 99 | break; 100 | } 101 | case IDC_SHOW_TEXT: 102 | { 103 | HWND button = ::GetDlgItem(hwnd, IDC_SHOW_TEXT); 104 | BOOL showText = BST_CHECKED == Button_GetCheck(button); 105 | theApp.setShowText(showText); 106 | 107 | break; 108 | } 109 | case IDC_NO_SCROLL_TEXT: 110 | { 111 | HWND button = ::GetDlgItem(hwnd, IDC_NO_SCROLL_TEXT); 112 | BOOL noScrollText = BST_CHECKED == Button_GetCheck(button); 113 | theApp.setNoScrollText(noScrollText); 114 | 115 | break; 116 | } 117 | case IDC_BEHIND: 118 | { 119 | HWND button = ::GetDlgItem(hwnd, IDC_BEHIND); 120 | BOOL behind = BST_CHECKED == Button_GetCheck(button); 121 | theApp.setBehind(behind); 122 | 123 | break; 124 | } 125 | case IDC_INCLUDE_LAYERS: 126 | { 127 | if (code == EN_UPDATE && !m_ignoreNotification) 128 | { 129 | TCHAR text[MAX_PATH] = {}; 130 | ::GetDlgItemText(hwnd, id, text, std::size(text)); 131 | theApp.setIncludeLayers(text); 132 | } 133 | 134 | break; 135 | } 136 | case IDC_EXCLUDE_LAYERS: 137 | { 138 | if (code == EN_UPDATE && !m_ignoreNotification) 139 | { 140 | TCHAR text[MAX_PATH] = {}; 141 | ::GetDlgItemText(hwnd, id, text, std::size(text)); 142 | theApp.setExcludeLayers(text); 143 | } 144 | 145 | break; 146 | } 147 | case IDC_EXCLUDE_DIR: 148 | { 149 | if (code == EN_UPDATE && !m_ignoreNotification) 150 | { 151 | TCHAR text[MAX_PATH] = {}; 152 | ::GetDlgItemText(hwnd, id, text, std::size(text)); 153 | theApp.setExcludeDir(text); 154 | } 155 | 156 | break; 157 | } 158 | } 159 | 160 | break; 161 | } 162 | case WM_NOTIFY: 163 | { 164 | MY_TRACE(_T("MainDialog::onDlgProc(WM_NOTIFY, 0x%08X, 0x%08X)\n"), wParam, lParam); 165 | 166 | switch (wParam) 167 | { 168 | case IDC_SCALE_SPIN: 169 | { 170 | NMHDR* header = (NMHDR*)lParam; 171 | if (header->code == UDN_DELTAPOS) 172 | { 173 | int scale = ::GetDlgItemInt(hwnd, IDC_SCALE, 0, TRUE); 174 | 175 | NM_UPDOWN* nm = (NM_UPDOWN*)header; 176 | if (nm->iDelta < 0) 177 | { 178 | scale += 10; 179 | } 180 | else 181 | { 182 | scale -= 10; 183 | } 184 | 185 | scale = std::max(scale, 0); 186 | scale = std::min(scale, 2000); 187 | 188 | ::SetDlgItemInt(hwnd, IDC_SCALE, scale, TRUE); 189 | } 190 | 191 | break; 192 | } 193 | } 194 | 195 | break; 196 | } 197 | } 198 | 199 | return Dialog::onDlgProc(hwnd, message, wParam, lParam); 200 | } 201 | 202 | //--------------------------------------------------------------------- 203 | -------------------------------------------------------------------------------- /ShowWaveform/MainDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Resource.h" 3 | 4 | struct MainDialog : public Tools::Dialog 5 | { 6 | BOOL m_ignoreNotification = FALSE; 7 | 8 | void ignoreNotification(BOOL ignoreNotification); 9 | virtual INT_PTR onDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 10 | }; 11 | -------------------------------------------------------------------------------- /ShowWaveform/Share.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //-------------------------------------------------------------------- 4 | 5 | static const LPCTSTR PROP_NAME_WINDOW_CONTAINER = _T("WindowContainer"); 6 | static const LPCTSTR PROP_NAME_DIALOG_CONTAINER = _T("DialogContainer"); 7 | 8 | // OutProcess => InProcess 9 | static const UINT WM_AVIUTL_FILTER_INIT = ::RegisterWindowMessage(_T("WM_AVIUTL_FILTER_INIT")); 10 | static const UINT WM_AVIUTL_FILTER_RECEIVE = ::RegisterWindowMessage(_T("WM_AVIUTL_FILTER_RECEIVE")); 11 | static const UINT WM_AVIUTL_FILTER_CHANGE_FRAME = ::RegisterWindowMessage(_T("WM_AVIUTL_FILTER_CHANGE_FRAME")); 12 | 13 | // InProcess => OutProcess 14 | static const UINT WM_AVIUTL_FILTER_EXIT = ::RegisterWindowMessage(_T("WM_AVIUTL_FILTER_EXIT")); 15 | static const UINT WM_AVIUTL_FILTER_RESIZE = ::RegisterWindowMessage(_T("WM_AVIUTL_FILTER_RESIZE")); 16 | static const UINT WM_AVIUTL_FILTER_SEND = ::RegisterWindowMessage(_T("WM_AVIUTL_FILTER_SEND")); 17 | static const UINT WM_AVIUTL_FILTER_CLEAR = ::RegisterWindowMessage(_T("WM_AVIUTL_FILTER_CLEAR")); 18 | static const UINT WM_AVIUTL_FILTER_REDRAW = ::RegisterWindowMessage(_T("WM_AVIUTL_FILTER_REDRAW")); 19 | 20 | struct SendID { 21 | static const int requestCache = 1; 22 | static const int notifyProjectChanged = 2; 23 | static const int notifyItemChanged = 3; 24 | static const int notifyTotalsChanged = 4; 25 | }; 26 | 27 | //-------------------------------------------------------------------- 28 | 29 | struct Volume { 30 | static const int32_t Resolution = 30; // 時間軸方向の分解能を FPS で指定します。 31 | static const int32_t MaxCount = Resolution * 60 * 60 * 4; // 最大 4 時間 32 | float level; 33 | }; 34 | 35 | struct SenderBottle { 36 | char fileName[MAX_PATH]; 37 | }; 38 | 39 | struct ReceiverBottle { 40 | char fileName[MAX_PATH]; 41 | int32_t volumeCount; 42 | Volume volumes[Volume::MaxCount]; 43 | }; 44 | 45 | struct ReaderBottle { 46 | char fileName[MAX_PATH]; 47 | int32_t volumeCount; 48 | Volume volumes[Volume::MaxCount]; 49 | }; 50 | 51 | struct ProjectParams { 52 | int32_t video_scale; 53 | int32_t video_rate; 54 | int32_t frameNumber; 55 | int32_t sceneIndex; 56 | int32_t currentFrame; 57 | }; 58 | 59 | struct AudioParams { 60 | uint32_t id = 0; 61 | uint32_t flag = 0; 62 | int32_t frameBegin = 0; 63 | int32_t frameEnd = 0; 64 | int32_t sceneSet = 0; 65 | char fileName[MAX_PATH] = {}; 66 | float volume = 1.0; 67 | int32_t playBegin = 0; 68 | float playSpeed = 1.0; 69 | uint32_t layerFlag = 0; 70 | }; 71 | 72 | struct TotalsParams { 73 | BOOL showBPM = FALSE; // BPM を表示するかどうか。 74 | struct Tempo { 75 | int32_t orig = 0; // テンポの基準となるフレーム番号。 76 | int32_t bpm = 120; // 1 分あたりの四分音符の数。テンポの速さはこの変数だけで決まる。 77 | int32_t above = 4; // 楽譜に書いてある上の数字。拍子。テンポの速さには影響を与えない。 78 | int32_t below = 4; // 楽譜に書いてある下の数字。分。テンポの速さには影響を与えない。 79 | } tempo; 80 | }; 81 | 82 | //-------------------------------------------------------------------- 83 | 84 | inline FormatText getMutexName(HWND hwnd) 85 | { 86 | return FormatText(_T("ShowWaveform.Mutex.%08X"), hwnd); 87 | } 88 | 89 | inline FormatText getSharedSenderBottleName(HWND hwnd) 90 | { 91 | return FormatText(_T("ShowWaveform.Shared.SenderBottle.%08X"), hwnd); 92 | } 93 | 94 | inline FormatText getSharedReceiverBottleName(HWND hwnd) 95 | { 96 | return FormatText(_T("ShowWaveform.Shared.ReceiverBottle.%08X"), hwnd); 97 | } 98 | 99 | inline FormatText getReaderEventName(DWORD id) 100 | { 101 | return FormatText(_T("ShowWaveform.Event.Reader.%d"), id); 102 | } 103 | 104 | inline FormatText getSharedReaderBottleName(DWORD id) 105 | { 106 | return FormatText(_T("ShowWaveform.Shared.ReaderBottle.%d"), id); 107 | } 108 | 109 | inline FormatText getSharedProjectParamsName(HWND hwnd) 110 | { 111 | return FormatText(_T("ShowWaveform.Shared.ProjectParams.%08X"), hwnd); 112 | } 113 | 114 | inline FormatText getSharedAudioParamsName(HWND hwnd) 115 | { 116 | return FormatText(_T("ShowWaveform.Shared.AudioParams.%08X"), hwnd); 117 | } 118 | 119 | inline FormatText getSharedSenderTotalsParamsName(HWND hwnd) 120 | { 121 | return FormatText(_T("ShowWaveform.Shared.SenderTotalsParams.%08X"), hwnd); 122 | } 123 | 124 | inline FormatText getSharedReceiverTotalsParamsName(HWND hwnd) 125 | { 126 | return FormatText(_T("ShowWaveform.Shared.ReceiverTotalsParams.%08X"), hwnd); 127 | } 128 | 129 | //-------------------------------------------------------------------- 130 | 131 | typedef std::shared_ptr SenderBottlePtr; 132 | typedef std::shared_ptr ReceiverBottlePtr; 133 | typedef std::shared_ptr ProjectParamsPtr; 134 | typedef std::shared_ptr AudioParamsPtr; 135 | typedef std::shared_ptr TotalsParamsPtr; 136 | 137 | //-------------------------------------------------------------------- 138 | 139 | struct Shared { 140 | Mutex mutex; 141 | SimpleFileMappingT senderBottle; 142 | SimpleFileMappingT receiverBottle; 143 | SimpleFileMappingT projectParams; 144 | SimpleFileMappingT audioParams; 145 | SimpleFileMappingT senderTotalsParams; 146 | SimpleFileMappingT receiverTotalsParams; 147 | 148 | BOOL init(HWND hwnd) 149 | { 150 | MY_TRACE(_T("Shared::init()\n")); 151 | 152 | mutex.init(0, FALSE, getMutexName(hwnd)); 153 | senderBottle.init(getSharedSenderBottleName(hwnd)); 154 | receiverBottle.init(getSharedReceiverBottleName(hwnd)); 155 | projectParams.init(getSharedProjectParamsName(hwnd)); 156 | audioParams.init(getSharedAudioParamsName(hwnd)); 157 | senderTotalsParams.init(getSharedSenderTotalsParamsName(hwnd)); 158 | receiverTotalsParams.init(getSharedReceiverTotalsParamsName(hwnd)); 159 | 160 | return TRUE; 161 | } 162 | 163 | BOOL term() 164 | { 165 | MY_TRACE(_T("Shared::term()\n")); 166 | 167 | return TRUE; 168 | } 169 | 170 | SenderBottlePtr getSenderBottle() 171 | { 172 | SenderBottle* shared = senderBottle.getBuffer(); 173 | if (!shared) return 0; 174 | return std::make_shared(*shared); 175 | } 176 | 177 | ProjectParamsPtr getProjectParams() 178 | { 179 | MY_TRACE(_T("Shared::getProjectParams()\n")); 180 | 181 | ProjectParams* shared = projectParams.getBuffer(); 182 | if (!shared) return 0; 183 | return std::make_shared(*shared); 184 | } 185 | 186 | AudioParamsPtr getAudioParams() 187 | { 188 | MY_TRACE(_T("Shared::getAudioParams()\n")); 189 | 190 | AudioParams* shared = audioParams.getBuffer(); 191 | if (!shared) return 0; 192 | return std::make_shared(*shared); 193 | } 194 | 195 | TotalsParamsPtr getSenderTotalsParams() 196 | { 197 | MY_TRACE(_T("Shared::getSenderTotalsParams()\n")); 198 | 199 | TotalsParams* shared = senderTotalsParams.getBuffer(); 200 | if (!shared) return 0; 201 | return std::make_shared(*shared); 202 | } 203 | 204 | BOOL setSenderTotalsParams(const TotalsParams* params) 205 | { 206 | MY_TRACE(_T("Shared::setSenderTotalsParams()\n")); 207 | 208 | Synchronizer sync(mutex); 209 | TotalsParams* shared = senderTotalsParams.getBuffer(); 210 | if (!shared) return FALSE; 211 | *shared = *params; 212 | return TRUE; 213 | } 214 | 215 | TotalsParamsPtr getReceiverTotalsParams() 216 | { 217 | MY_TRACE(_T("Shared::getReceiverTotalsParams()\n")); 218 | 219 | TotalsParams* shared = receiverTotalsParams.getBuffer(); 220 | if (!shared) return 0; 221 | return std::make_shared(*shared); 222 | } 223 | 224 | BOOL setReceiverTotalsParams(const TotalsParams* params) 225 | { 226 | MY_TRACE(_T("Shared::setReceiverTotalsParams()\n")); 227 | 228 | Synchronizer sync(mutex); 229 | TotalsParams* shared = receiverTotalsParams.getBuffer(); 230 | if (!shared) return FALSE; 231 | *shared = *params; 232 | return TRUE; 233 | } 234 | }; 235 | 236 | //-------------------------------------------------------------------- 237 | -------------------------------------------------------------------------------- /ShowWaveform/ShowWaveform.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ShowWaveform.h" 3 | #include "App.h" 4 | 5 | BOOL func_init(AviUtl::FilterPlugin* fp) 6 | { 7 | return theApp.func_init(fp); 8 | } 9 | 10 | BOOL func_exit(AviUtl::FilterPlugin* fp) 11 | { 12 | return theApp.func_exit(fp); 13 | } 14 | 15 | BOOL func_proc(AviUtl::FilterPlugin* fp, AviUtl::FilterProcInfo* fpip) 16 | { 17 | return theApp.func_proc(fp, fpip); 18 | } 19 | 20 | BOOL func_update(AviUtl::FilterPlugin* fp, AviUtl::FilterPlugin::UpdateStatus status) 21 | { 22 | return theApp.func_update(fp, status); 23 | } 24 | 25 | BOOL func_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, AviUtl::EditHandle* editp, AviUtl::FilterPlugin* fp) 26 | { 27 | return theApp.func_WndProc(hwnd, message, wParam, lParam, editp, fp); 28 | } 29 | 30 | BOOL func_project_load(AviUtl::FilterPlugin* fp, AviUtl::EditHandle* editp, void* data, int32_t size) 31 | { 32 | return theApp.func_project_load(fp, editp, data, size); 33 | } 34 | 35 | BOOL func_project_save(AviUtl::FilterPlugin* fp, AviUtl::EditHandle* editp, void* data, int32_t* size) 36 | { 37 | return theApp.func_project_save(fp, editp, data, size); 38 | } 39 | 40 | BOOL APIENTRY DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) 41 | { 42 | return theApp.DllMain(instance, reason, reserved); 43 | } 44 | 45 | AviUtl::FilterPluginDLL* WINAPI GetFilterTable() 46 | { 47 | LPCSTR name = "アイテム内音声波形"; 48 | LPCSTR information = "アイテム内音声波形 7.3.1 by 蛇色"; 49 | 50 | static AviUtl::FilterPluginDLL filter = 51 | { 52 | .flag = 53 | AviUtl::FilterPluginDLL::Flag::AlwaysActive | 54 | // AviUtl::FilterPluginDLL::Flag::DispFilter | 55 | AviUtl::FilterPluginDLL::Flag::WindowSize | 56 | AviUtl::FilterPluginDLL::Flag::WindowThickFrame | 57 | AviUtl::FilterPluginDLL::Flag::ExInformation, 58 | .x = 300, 59 | .y = 350, 60 | .name = name, 61 | .func_proc = func_proc, 62 | .func_init = func_init, 63 | .func_exit = func_exit, 64 | .func_update = func_update, 65 | .func_WndProc = func_WndProc, 66 | .information = information, 67 | .func_project_load = func_project_load, 68 | .func_project_save = func_project_save, 69 | }; 70 | 71 | return &filter; 72 | } 73 | -------------------------------------------------------------------------------- /ShowWaveform/ShowWaveform.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | GetFilterTable @1 3 | -------------------------------------------------------------------------------- /ShowWaveform/ShowWaveform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Share.h" 4 | 5 | //--------------------------------------------------------------------- 6 | 7 | struct FileCache; 8 | struct FileCacheManager; 9 | struct ItemCache; 10 | struct ItemCacheManager; 11 | 12 | typedef std::vector VolumeArray; 13 | 14 | typedef std::shared_ptr FileCachePtr; 15 | typedef std::map FileCacheMap; 16 | 17 | typedef std::shared_ptr ItemCachePtr; 18 | typedef std::map ItemCacheMap; 19 | 20 | typedef std::shared_ptr SenderBottlePtr; 21 | typedef std::shared_ptr ReceiverBottlePtr; 22 | typedef std::shared_ptr ProjectParamsPtr; 23 | typedef std::shared_ptr AudioParamsPtr; 24 | typedef std::shared_ptr TotalsParamsPtr; 25 | 26 | //--------------------------------------------------------------------- 27 | -------------------------------------------------------------------------------- /ShowWaveform/ShowWaveform.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hebiiro/AviUtl-Plugin-ShowWaveform/ada292c648f8d941588c9261710214e157c187ef/ShowWaveform/ShowWaveform.rc -------------------------------------------------------------------------------- /ShowWaveform/ShowWaveform.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {79bae488-39c4-4741-beda-1e2ee6428bed} 6 | 7 | 8 | {d8bd7764-ca8e-4dc1-8b9e-3ae1918c9bb9} 9 | 10 | 11 | {b0df70ad-6fbb-43ea-acf0-034e4025bc3b} 12 | 13 | 14 | 15 | 16 | 17 | Common 18 | 19 | 20 | Common 21 | 22 | 23 | Common 24 | 25 | 26 | Common 27 | 28 | 29 | 30 | 31 | 32 | Framework 33 | 34 | 35 | 36 | 37 | 38 | Resource 39 | 40 | 41 | Common 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Framework 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Framework 60 | 61 | 62 | 63 | 64 | Resource 65 | 66 | 67 | -------------------------------------------------------------------------------- /ShowWaveform/SubProcess.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SubProcess.h" 3 | #include "App.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | BOOL SubProcess::init(AviUtl::FilterPlugin* fp) 8 | { 9 | MY_TRACE(_T("SubProcess::init()\n")); 10 | 11 | // サブプロセスのウィンドウの親となるコンテナウィンドウを作成する。 12 | 13 | HWND owner = ::GetWindow(fp->hwnd, GW_OWNER); 14 | 15 | if (!m_windowContainer.init(fp, owner, _T("全体の音声波形"))) 16 | { 17 | MY_TRACE(_T("全体の音声波形ウィンドウの作成に失敗しました\n")); 18 | 19 | return FALSE; 20 | } 21 | 22 | if (!m_dialogContainer.init(fp, owner, _T("全体の音声波形の設定"))) 23 | { 24 | MY_TRACE(_T("全体の音声波形ダイアログの作成に失敗しました\n")); 25 | 26 | return FALSE; 27 | } 28 | 29 | // ウィンドウコンテナとダイアログコンテナを関連付ける。 30 | 31 | ::SetProp(m_windowContainer.m_hwnd, PROP_NAME_DIALOG_CONTAINER, m_dialogContainer.m_hwnd); 32 | ::SetProp(m_dialogContainer.m_hwnd, PROP_NAME_WINDOW_CONTAINER, m_windowContainer.m_hwnd); 33 | 34 | // コンテナウィンドウの作成が完了したので、サブプロセスを起動する。 35 | 36 | TCHAR path[MAX_PATH] = {}; 37 | ::GetModuleFileName(fp->dll_hinst, path, MAX_PATH); 38 | ::PathRemoveExtension(path); 39 | ::PathAppend(path, _T("ShowWaveform.exe")); 40 | MY_TRACE_TSTR(path); 41 | 42 | TCHAR args[MAX_PATH] = {}; 43 | ::StringCbPrintf(args, sizeof(args), _T("0x%08p"), m_windowContainer.m_hwnd); 44 | MY_TRACE_TSTR(args); 45 | 46 | STARTUPINFO si = { sizeof(si) }; 47 | if (!::CreateProcess( 48 | path, // No module name (use command line) 49 | args, // Command line 50 | NULL, // Process handle not inheritable 51 | NULL, // Thread handle not inheritable 52 | FALSE, // Set handle inheritance to FALSE 53 | 0, // No creation flags 54 | NULL, // Use parent's environment block 55 | NULL, // Use parent's starting directory 56 | &si, // Pointer to STARTUPINFO structure 57 | &m_pi)) // Pointer to PROCESS_INFORMATION structur 58 | { 59 | MY_TRACE(_T("::CreateProcess() failed.\n")); 60 | 61 | return FALSE; 62 | } 63 | 64 | return TRUE; 65 | } 66 | 67 | BOOL SubProcess::exit(AviUtl::FilterPlugin* fp) 68 | { 69 | MY_TRACE(_T("SubProcess::exit()\n")); 70 | 71 | m_dialogContainer.exit(fp); 72 | m_windowContainer.exit(fp); 73 | 74 | ::PostMessage(m_dialogContainer.m_inner, WM_AVIUTL_FILTER_EXIT, 0, 0); 75 | ::PostMessage(m_windowContainer.m_inner, WM_AVIUTL_FILTER_EXIT, 0, 0); 76 | 77 | return TRUE; 78 | } 79 | 80 | //-------------------------------------------------------------------- 81 | 82 | BOOL SubProcess::Container::init(AviUtl::FilterPlugin* fp, HWND owner, LPCTSTR windowText) 83 | { 84 | MY_TRACE(_T("SubProcess::Container::init(%s)\n"), windowText); 85 | 86 | const LPCTSTR className = _T("AviUtl"); 87 | 88 | WNDCLASSEX wc = { sizeof(wc) }; 89 | wc.style = 0; 90 | wc.lpfnWndProc = wndProc; 91 | wc.hInstance = fp->dll_hinst; 92 | wc.hCursor = ::LoadCursor(0, IDC_ARROW); 93 | wc.lpszClassName = className; 94 | ::RegisterClassEx(&wc); 95 | 96 | m_hwnd = ::CreateWindowEx( 97 | WS_EX_NOPARENTNOTIFY, 98 | className, windowText, 99 | WS_VISIBLE | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 100 | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, 101 | 0, 0, 400, 400, 102 | owner, 0, fp->dll_hinst, 0); 103 | 104 | ::SetProp(m_hwnd, getPropName(), this); 105 | 106 | return !!m_hwnd; 107 | } 108 | 109 | BOOL SubProcess::Container::exit(AviUtl::FilterPlugin* fp) 110 | { 111 | MY_TRACE(_T("SubProcess::Container::exit()\n")); 112 | 113 | ::DestroyWindow(m_hwnd); 114 | 115 | return TRUE; 116 | } 117 | 118 | LRESULT SubProcess::Container::onWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 119 | { 120 | switch (message) 121 | { 122 | case WM_CLOSE: 123 | { 124 | MY_TRACE(_T("SubProcess::Container::onWndProc(WM_CLOSE, 0x%08X, 0x%08X)\n"), wParam, lParam); 125 | 126 | if (::IsWindowVisible(hwnd)) 127 | ::ShowWindow(hwnd, SW_HIDE); 128 | else 129 | ::ShowWindow(hwnd, SW_SHOW); 130 | 131 | return 0; 132 | } 133 | } 134 | 135 | return ::DefWindowProc(hwnd, message, wParam, lParam); 136 | } 137 | 138 | LRESULT CALLBACK SubProcess::Container::wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 139 | { 140 | Container* container = (Container*)::GetProp(hwnd, getPropName()); 141 | if (container) return container->onWndProc(hwnd, message, wParam, lParam); 142 | return ::DefWindowProc(hwnd, message, wParam, lParam); 143 | } 144 | 145 | //-------------------------------------------------------------------- 146 | 147 | void SubProcess::WindowContainer::delayedUpdate() 148 | { 149 | MY_TRACE(_T("SubProcess::WindowContainer::delayedUpdate()\n")); 150 | 151 | ::SetTimer(m_hwnd, TimerID::Update, 100, 0); 152 | } 153 | 154 | void SubProcess::WindowContainer::delayedSendTotalsParams(const TotalsParams* params) 155 | { 156 | MY_TRACE(_T("SubProcess::WindowContainer::delayedSendTotalsParams()\n")); 157 | 158 | m_delayedTotalsParams = *params; 159 | 160 | ::SetTimer(m_hwnd, TimerID::SendTotalsParams, 100, 0); 161 | } 162 | 163 | LRESULT SubProcess::WindowContainer::onWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 164 | { 165 | switch (message) 166 | { 167 | case WM_SIZE: 168 | { 169 | MY_TRACE(_T("SubProcess::WindowContainer::onWndProc(WM_SIZE, 0x%08X, 0x%08X)\n"), wParam, lParam); 170 | 171 | ::PostMessage(m_inner, WM_AVIUTL_FILTER_RESIZE, 0, 0); 172 | 173 | break; 174 | } 175 | case WM_TIMER: 176 | { 177 | MY_TRACE(_T("SubProcess::WindowContainer::onWndProc(WM_TIMER, 0x%08X, 0x%08X)\n"), wParam, lParam); 178 | 179 | switch (wParam) 180 | { 181 | case TimerID::Update: 182 | { 183 | if (m_inner) 184 | { 185 | MY_TRACE(_T("delayed update\n")); 186 | 187 | ::KillTimer(hwnd, TimerID::Update); 188 | 189 | theApp.updateProjectParams(); 190 | theApp.updateItemCache(TRUE); 191 | } 192 | 193 | break; 194 | } 195 | case TimerID::SendTotalsParams: 196 | { 197 | if (m_inner) 198 | { 199 | MY_TRACE(_T("delayed send totals params\n")); 200 | 201 | ::KillTimer(hwnd, TimerID::SendTotalsParams); 202 | 203 | theApp.sendTotalsParams(&m_delayedTotalsParams); 204 | } 205 | 206 | break; 207 | } 208 | } 209 | 210 | break; 211 | } 212 | } 213 | 214 | if (message == WM_AVIUTL_FILTER_INIT) 215 | { 216 | MY_TRACE(_T("SubProcess::WindowContainer::onWndProc(WM_AVIUTL_FILTER_INIT, 0x%08X, 0x%08X)\n"), wParam, lParam); 217 | 218 | m_inner = (HWND)wParam; 219 | ::PostMessage(m_inner, WM_AVIUTL_FILTER_RESIZE, 0, 0); 220 | } 221 | else if (message == WM_AVIUTL_FILTER_RECEIVE) 222 | { 223 | MY_TRACE(_T("SubProcess::WindowContainer::onWndProc(WM_AVIUTL_FILTER_RECEIVE, 0x%08X, 0x%08X)\n"), wParam, lParam); 224 | 225 | if (!theApp.m_exists) 226 | return FALSE; 227 | 228 | theApp.m_fileCacheManager.receiveCache(); 229 | theApp.m_itemCacheManager.update(FALSE); 230 | } 231 | else if (message == WM_AVIUTL_FILTER_CHANGE_FRAME) 232 | { 233 | MY_TRACE(_T("SubProcess::WindowContainer::onWndProc(WM_AVIUTL_FILTER_CHANGE_FRAME, 0x%08X, 0x%08X)\n"), wParam, lParam); 234 | 235 | int32_t frame = (int32_t)wParam; 236 | MY_TRACE_INT(frame); 237 | 238 | theApp.m_fp->exfunc->set_frame(theApp.m_auin.GetEditp(), frame); 239 | ::PostMessage(theApp.m_fp->hwnd, AviUtl::FilterPlugin::WindowMessage::Command, 0, 0); 240 | } 241 | 242 | return Container::onWndProc(hwnd, message, wParam, lParam); 243 | } 244 | 245 | //-------------------------------------------------------------------- 246 | 247 | LRESULT SubProcess::DialogContainer::onWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 248 | { 249 | switch (message) 250 | { 251 | case WM_SIZE: 252 | { 253 | MY_TRACE(_T("SubProcess::DialogContainer::onWndProc(WM_SIZE, 0x%08X, 0x%08X)\n"), wParam, lParam); 254 | 255 | ::PostMessage(m_inner, WM_AVIUTL_FILTER_RESIZE, 0, 0); 256 | 257 | break; 258 | } 259 | } 260 | 261 | if (message == WM_AVIUTL_FILTER_INIT) 262 | { 263 | MY_TRACE(_T("SubProcess::DialogContainer::onWndProc(WM_AVIUTL_FILTER_INIT, 0x%08X, 0x%08X)\n"), wParam, lParam); 264 | 265 | m_inner = (HWND)wParam; 266 | ::PostMessage(m_inner, WM_AVIUTL_FILTER_RESIZE, 0, 0); 267 | } 268 | else if (message == WM_AVIUTL_FILTER_RECEIVE) 269 | { 270 | MY_TRACE(_T("SubProcess::DialogContainer::onWndProc(WM_AVIUTL_FILTER_RECEIVE, 0x%08X, 0x%08X)\n"), wParam, lParam); 271 | } 272 | else if (message == WM_AVIUTL_FILTER_CHANGE_FRAME) 273 | { 274 | MY_TRACE(_T("SubProcess::DialogContainer::onWndProc(WM_AVIUTL_FILTER_CHANGE_FRAME, 0x%08X, 0x%08X)\n"), wParam, lParam); 275 | } 276 | 277 | return Container::onWndProc(hwnd, message, wParam, lParam); 278 | } 279 | 280 | //-------------------------------------------------------------------- 281 | -------------------------------------------------------------------------------- /ShowWaveform/SubProcess.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ShowWaveform.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | struct SubProcess 8 | { 9 | PROCESS_INFORMATION m_pi = {}; 10 | 11 | BOOL init(AviUtl::FilterPlugin* fp); 12 | BOOL exit(AviUtl::FilterPlugin* fp); 13 | 14 | struct Container { 15 | HWND m_hwnd = 0; 16 | HWND m_inner = 0; 17 | BOOL init(AviUtl::FilterPlugin* fp, HWND owner, LPCTSTR windowText); 18 | BOOL exit(AviUtl::FilterPlugin* fp); 19 | virtual LRESULT onWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 20 | static LRESULT CALLBACK wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 21 | static LPCTSTR getPropName(){ return _T("SubProcess.Container"); } 22 | }; 23 | 24 | struct WindowContainer : Container { 25 | struct TimerID { 26 | static const int Update = 1000; 27 | static const int SendTotalsParams = 1001; 28 | }; 29 | TotalsParams m_delayedTotalsParams; 30 | void delayedUpdate(); 31 | void delayedSendTotalsParams(const TotalsParams* params); 32 | LRESULT onWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 33 | } m_windowContainer; 34 | 35 | struct DialogContainer : Container { 36 | LRESULT onWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 37 | } m_dialogContainer; 38 | }; 39 | 40 | //-------------------------------------------------------------------- 41 | -------------------------------------------------------------------------------- /ShowWaveform/SubThread.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SubThread.h" 3 | #include "App.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | Shared shared; 8 | 9 | //-------------------------------------------------------------------- 10 | 11 | CacheRequest::CacheRequest(LPCSTR fileName) 12 | : fileName(fileName) 13 | { 14 | } 15 | 16 | //-------------------------------------------------------------------- 17 | 18 | SubThread::SubThread() 19 | { 20 | MY_TRACE(_T("SubThread::SubThread()\n")); 21 | } 22 | 23 | SubThread::~SubThread() 24 | { 25 | MY_TRACE(_T("SubThread::~SubThread()\n")); 26 | } 27 | 28 | void SubThread::onPostCacheRequest(const CacheRequest* cacheRequest) 29 | { 30 | MY_TRACE(_T("SubThreadManager::onPostCacheRequest()\n")); 31 | 32 | auto it = cacheRequestMap.find(cacheRequest->fileName); 33 | if (it != cacheRequestMap.end()) 34 | { 35 | // 同一のリクエストがマップ内に残っているので 36 | // このリクエストは破棄する。 37 | delete cacheRequest; 38 | MY_TRACE(_T("リクエストを破棄しました\n")); 39 | return; 40 | } 41 | 42 | cacheRequestMap[cacheRequest->fileName] = cacheRequest; 43 | 44 | ::PostThreadMessage(::GetCurrentThreadId(), SubThread::WM_SEND_CACHE_REQUEST, (WPARAM)cacheRequest, 0); 45 | } 46 | 47 | void SubThread::onSendCacheRequest(const CacheRequest* cacheRequest) 48 | { 49 | MY_TRACE(_T("SubThreadManager::onSendCacheRequest()\n")); 50 | 51 | // 送信用のボトルを取得する。 52 | SenderBottle* shared = ::shared.senderBottle.getBuffer(); 53 | if (shared) 54 | { 55 | ::StringCbCopyA(shared->fileName, sizeof(shared->fileName), cacheRequest->fileName.c_str()); 56 | 57 | // サブプロセスにキャッシュの作成をリクエストする。 58 | ::SendMessage(theApp.m_subProcess.m_windowContainer.m_inner, WM_AVIUTL_FILTER_SEND, SendID::requestCache, 0); 59 | } 60 | 61 | // このリクエストをマップから削除する。 62 | auto it = cacheRequestMap.find(cacheRequest->fileName); 63 | if (it != cacheRequestMap.end()) 64 | { 65 | delete it->second; 66 | cacheRequestMap.erase(it); 67 | } 68 | } 69 | 70 | void SubThread::onSendProjectChanged(const ProjectParams* params) 71 | { 72 | MY_TRACE(_T("SubThreadManager::onSendProjectChanged()\n")); 73 | 74 | ProjectParams* shared = ::shared.projectParams.getBuffer(); 75 | if (shared) 76 | { 77 | *shared = *params; 78 | 79 | // サブプロセスにアイテムの変更を通知する。 80 | ::SendMessage(theApp.m_subProcess.m_windowContainer.m_inner, WM_AVIUTL_FILTER_SEND, SendID::notifyProjectChanged, 0); 81 | } 82 | 83 | delete params; 84 | } 85 | 86 | void SubThread::onSendItemChanged(const AudioParams* params) 87 | { 88 | MY_TRACE(_T("SubThreadManager::onSendItemChanged()\n")); 89 | 90 | AudioParams* shared = ::shared.audioParams.getBuffer(); 91 | if (shared) 92 | { 93 | *shared = *params; 94 | 95 | // サブプロセスにアイテムの変更を通知する。 96 | ::SendMessage(theApp.m_subProcess.m_windowContainer.m_inner, WM_AVIUTL_FILTER_SEND, SendID::notifyItemChanged, 0); 97 | } 98 | 99 | delete params; 100 | } 101 | 102 | void SubThread::onSendTotalsChanged(const TotalsParams* params) 103 | { 104 | MY_TRACE(_T("SubThreadManager::onSendTotalsChanged()\n")); 105 | 106 | TotalsParams* shared = ::shared.senderTotalsParams.getBuffer(); 107 | if (shared) 108 | { 109 | *shared = *params; 110 | 111 | // サブプロセスにサブプロセスパラメータの変更を通知する。 112 | ::SendMessage(theApp.m_subProcess.m_windowContainer.m_inner, WM_AVIUTL_FILTER_SEND, SendID::notifyTotalsChanged, 0); 113 | } 114 | 115 | delete params; 116 | } 117 | 118 | void SubThread::onPostClearRequest() 119 | { 120 | MY_TRACE(_T("SubThreadManager::onPostClearRequest()\n")); 121 | 122 | ::SendMessage(theApp.m_subProcess.m_windowContainer.m_inner, WM_AVIUTL_FILTER_CLEAR, 0, 0); 123 | } 124 | 125 | void SubThread::onPostRedrawRequest() 126 | { 127 | MY_TRACE(_T("SubThreadManager::onPostRedrawRequest()\n")); 128 | 129 | ::SendMessage(theApp.m_subProcess.m_windowContainer.m_inner, WM_AVIUTL_FILTER_REDRAW, 0, 0); 130 | } 131 | 132 | DWORD SubThread::proc() 133 | { 134 | MSG msg = {}; 135 | while (::GetMessage(&msg, 0, 0, 0)) 136 | { 137 | if (!msg.hwnd) 138 | { 139 | switch (msg.message) 140 | { 141 | case WM_POST_CACHE_REQUEST: 142 | { 143 | onPostCacheRequest((const CacheRequest*)msg.wParam); 144 | break; 145 | } 146 | case WM_SEND_CACHE_REQUEST: 147 | { 148 | onSendCacheRequest((const CacheRequest*)msg.wParam); 149 | break; 150 | } 151 | case WM_SEND_PROJECT_CHANGED: 152 | { 153 | onSendProjectChanged((const ProjectParams*)msg.wParam); 154 | break; 155 | } 156 | case WM_SEND_ITEM_CHANGED: 157 | { 158 | onSendItemChanged((const AudioParams*)msg.wParam); 159 | break; 160 | } 161 | case WM_SEND_TOTALS_CHANGED: 162 | { 163 | onSendTotalsChanged((const TotalsParams*)msg.wParam); 164 | break; 165 | } 166 | case WM_POST_CLEAR_REQUEST: 167 | { 168 | onPostClearRequest(); 169 | break; 170 | } 171 | case WM_POST_REDRAW_REQUEST: 172 | { 173 | onPostRedrawRequest(); 174 | break; 175 | } 176 | case WM_QUIT: 177 | { 178 | return 0; 179 | } 180 | } 181 | } 182 | 183 | ::TranslateMessage(&msg); 184 | ::DispatchMessage(&msg); 185 | } 186 | 187 | return 0; 188 | } 189 | 190 | //-------------------------------------------------------------------- 191 | 192 | BOOL SubThreadManager::init(AviUtl::FilterPlugin* fp) 193 | { 194 | MY_TRACE(_T("SubThreadManager::init()\n")); 195 | 196 | HWND hwnd = theApp.m_subProcess.m_windowContainer.m_hwnd; 197 | 198 | shared.init(hwnd); 199 | 200 | { 201 | TotalsParams params; // 初期値。 202 | shared.setSenderTotalsParams(¶ms); 203 | shared.setReceiverTotalsParams(¶ms); 204 | } 205 | 206 | m_handle = ::CreateThread(0, 0, threadProc, 0, 0, &m_tid); 207 | return !!m_handle; 208 | } 209 | 210 | BOOL SubThreadManager::exit(AviUtl::FilterPlugin* fp) 211 | { 212 | MY_TRACE(_T("SubThreadManager::exit()\n")); 213 | 214 | shared.term(); 215 | 216 | // return ::PostThreadMessage(m_tid, WM_QUIT, 0, 0); 217 | return ::TerminateThread(m_handle, -1); 218 | } 219 | 220 | BOOL SubThreadManager::requestCache(LPCSTR fileName) 221 | { 222 | MY_TRACE(_T("SubThreadManager::requestCache(%hs)\n"), fileName); 223 | 224 | return ::PostThreadMessage(m_tid, SubThread::WM_POST_CACHE_REQUEST, (WPARAM)new CacheRequest(fileName), 0); 225 | } 226 | 227 | BOOL SubThreadManager::notifyProjectChanged(const ProjectParamsPtr& params) 228 | { 229 | MY_TRACE(_T("SubThreadManager::notifyProjectChanged()\n")); 230 | 231 | return ::PostThreadMessage(m_tid, SubThread::WM_SEND_PROJECT_CHANGED, (WPARAM)new ProjectParams(*params), 0); 232 | } 233 | 234 | BOOL SubThreadManager::notifyItemChanged(const AudioParamsPtr& params) 235 | { 236 | MY_TRACE(_T("SubThreadManager::notifyItemChanged()\n")); 237 | 238 | return ::PostThreadMessage(m_tid, SubThread::WM_SEND_ITEM_CHANGED, (WPARAM)new AudioParams(*params), 0); 239 | } 240 | 241 | BOOL SubThreadManager::notifyTotalsChanged(const TotalsParamsPtr& params) 242 | { 243 | MY_TRACE(_T("SubThreadManager::notifyTotalsChanged()\n")); 244 | 245 | return ::PostThreadMessage(m_tid, SubThread::WM_SEND_TOTALS_CHANGED, (WPARAM)new TotalsParams(*params), 0); 246 | } 247 | 248 | BOOL SubThreadManager::requestClear() 249 | { 250 | MY_TRACE(_T("SubThreadManager::requestClear()\n")); 251 | 252 | return ::PostThreadMessage(m_tid, SubThread::WM_POST_CLEAR_REQUEST, 0, 0); 253 | } 254 | 255 | BOOL SubThreadManager::requestRedraw() 256 | { 257 | MY_TRACE(_T("SubThreadManager::requestRedraw()\n")); 258 | 259 | return ::PostThreadMessage(m_tid, SubThread::WM_POST_REDRAW_REQUEST, 0, 0); 260 | } 261 | 262 | //-------------------------------------------------------------------- 263 | 264 | DWORD CALLBACK SubThreadManager::threadProc(LPVOID param) 265 | { 266 | SubThread subThread; 267 | 268 | return subThread.proc(); 269 | } 270 | 271 | //-------------------------------------------------------------------- 272 | -------------------------------------------------------------------------------- /ShowWaveform/SubThread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ShowWaveform.h" 4 | 5 | //-------------------------------------------------------------------- 6 | 7 | extern Shared shared; 8 | 9 | //-------------------------------------------------------------------- 10 | 11 | struct CacheRequest 12 | { 13 | std::string fileName; 14 | 15 | // メインスレッド側の処理。 16 | CacheRequest(LPCSTR fileName); 17 | }; 18 | 19 | struct SubThread 20 | { 21 | static const UINT WM_POST_CACHE_REQUEST = WM_APP + 1; 22 | static const UINT WM_SEND_CACHE_REQUEST = WM_APP + 2; 23 | static const UINT WM_SEND_PROJECT_CHANGED = WM_APP + 3; 24 | static const UINT WM_SEND_ITEM_CHANGED = WM_APP + 4; 25 | static const UINT WM_POST_CLEAR_REQUEST = WM_APP + 5; 26 | static const UINT WM_POST_REDRAW_REQUEST = WM_APP + 6; 27 | static const UINT WM_SEND_TOTALS_CHANGED = WM_APP + 7; 28 | 29 | std::map cacheRequestMap; 30 | 31 | // サブスレッド側の処理。 32 | SubThread(); 33 | ~SubThread(); 34 | void onPostCacheRequest(const CacheRequest* cacheRequest); 35 | void onSendCacheRequest(const CacheRequest* cacheRequest); 36 | void onSendProjectChanged(const ProjectParams* params); 37 | void onSendItemChanged(const AudioParams* params); 38 | void onSendTotalsChanged(const TotalsParams* params); 39 | void onPostClearRequest(); 40 | void onPostRedrawRequest(); 41 | DWORD proc(); 42 | }; 43 | 44 | struct SubThreadManager 45 | { 46 | DWORD m_tid = 0; 47 | Handle m_handle; 48 | 49 | // メインスレッド側の処理。 50 | BOOL init(AviUtl::FilterPlugin* fp); 51 | BOOL exit(AviUtl::FilterPlugin* fp); 52 | BOOL requestCache(LPCSTR fileName); 53 | BOOL notifyProjectChanged(const ProjectParamsPtr& params); 54 | BOOL notifyItemChanged(const AudioParamsPtr& params); 55 | BOOL notifyTotalsChanged(const TotalsParamsPtr& params); 56 | BOOL requestClear(); 57 | BOOL requestRedraw(); 58 | 59 | // サブスレッド側の処理。 60 | static DWORD CALLBACK threadProc(LPVOID param); 61 | }; 62 | 63 | //-------------------------------------------------------------------- 64 | -------------------------------------------------------------------------------- /ShowWaveform/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /ShowWaveform/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #define NOMINMAX 5 | #include 6 | #include 7 | #pragma comment(lib, "msimg32.lib") 8 | #include 9 | #pragma comment(lib, "shlwapi.lib") 10 | #include 11 | #pragma comment(lib, "comctl32.lib") 12 | #include 13 | #include 14 | #pragma comment(lib, "winmm.lib") 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "aviutl.hpp" 29 | #include "exedit.hpp" 30 | #include "Common/Tracer.h" 31 | #include "Common/WinUtility.h" 32 | #include "Common/Dialog.h" 33 | #include "Common/Profile.h" 34 | #include "Common/Hook.h" 35 | #include "Common/AviUtlInternal.h" 36 | #include "detours/detours.h" 37 | #pragma comment(lib, "detours/detours.lib") 38 | -------------------------------------------------------------------------------- /ShowWaveform/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ で生成されたインクルード ファイル。 3 | // ShowWaveform.rc で使用 4 | // 5 | #define IDD_MAIN_DIALOG 101 6 | #define IDC_SHOW_TYPE 1001 7 | #define IDC_SCALE 1002 8 | #define IDC_SCALE_SPIN 1003 9 | #define IDC_UPDATE_MODE 1004 10 | #define IDC_XOR_MODE 1005 11 | #define IDC_PEN_COLOR 1006 12 | #define IDC_BRUSH_COLOR 1007 13 | #define IDC_CLEAR 1008 14 | #define IDC_SHOW_FULL 1009 15 | #define IDC_SHOW_WAVEFORM 1010 16 | #define IDC_SHOW_TEXT 1011 17 | #define IDC_NO_SCROLL_TEXT 1012 18 | #define IDC_BEHIND 1013 19 | #define IDC_INCLUDE_LAYERS 1014 20 | #define IDC_EXCLUDE_LAYERS 1015 21 | #define IDC_EXCLUDE_FOLDER 1016 22 | #define IDC_EXCLUDE_DIR 1016 23 | 24 | // Next default values for new objects 25 | // 26 | #ifdef APSTUDIO_INVOKED 27 | #ifndef APSTUDIO_READONLY_SYMBOLS 28 | #define _APS_NEXT_RESOURCE_VALUE 104 29 | #define _APS_NEXT_COMMAND_VALUE 40001 30 | #define _APS_NEXT_CONTROL_VALUE 1011 31 | #define _APS_NEXT_SYMED_VALUE 101 32 | #endif 33 | #endif 34 | --------------------------------------------------------------------------------