OSDN Git Service

最初のコミット
authorsfpg <sfpg@users.sourceforge.jp>
Fri, 12 Oct 2012 20:39:45 +0000 (05:39 +0900)
committersfpg <sfpg@users.sourceforge.jp>
Fri, 12 Oct 2012 20:39:45 +0000 (05:39 +0900)
81 files changed:
.gitignore [new file with mode: 0644]
SF.props [new file with mode: 0644]
wasapi2.sln [new file with mode: 0644]
wasapi2/application.cpp [new file with mode: 0644]
wasapi2/application.h [new file with mode: 0644]
wasapi2/async_reader.cpp [new file with mode: 0644]
wasapi2/async_reader.h [new file with mode: 0644]
wasapi2/audio_base.h [new file with mode: 0644]
wasapi2/audio_filter.h [new file with mode: 0644]
wasapi2/audio_processor.h [new file with mode: 0644]
wasapi2/audio_source.h [new file with mode: 0644]
wasapi2/base_window.cpp [new file with mode: 0644]
wasapi2/base_window.h [new file with mode: 0644]
wasapi2/code_converter.cpp [new file with mode: 0644]
wasapi2/code_converter.h [new file with mode: 0644]
wasapi2/config_tab_dialog.cpp [new file with mode: 0644]
wasapi2/config_tab_dialog.h [new file with mode: 0644]
wasapi2/directx.ico [new file with mode: 0644]
wasapi2/dout.h [new file with mode: 0644]
wasapi2/dpi.cpp [new file with mode: 0644]
wasapi2/dpi.h [new file with mode: 0644]
wasapi2/exception.cpp [new file with mode: 0644]
wasapi2/exception.h [new file with mode: 0644]
wasapi2/icon.cpp [new file with mode: 0644]
wasapi2/icon.h [new file with mode: 0644]
wasapi2/info_tab_dialog.cpp [new file with mode: 0644]
wasapi2/info_tab_dialog.h [new file with mode: 0644]
wasapi2/input_thread.cpp [new file with mode: 0644]
wasapi2/input_thread.h [new file with mode: 0644]
wasapi2/jumplist.cpp [new file with mode: 0644]
wasapi2/jumplist.h [new file with mode: 0644]
wasapi2/logger.cpp [new file with mode: 0644]
wasapi2/logger.h [new file with mode: 0644]
wasapi2/message_loop.h [new file with mode: 0644]
wasapi2/mixer_thread.cpp [new file with mode: 0644]
wasapi2/mixer_thread.h [new file with mode: 0644]
wasapi2/output_thread.cpp [new file with mode: 0644]
wasapi2/output_thread.h [new file with mode: 0644]
wasapi2/reader_thread.cpp [new file with mode: 0644]
wasapi2/reader_thread.h [new file with mode: 0644]
wasapi2/resource.h [new file with mode: 0644]
wasapi2/ring_buffer.cpp [new file with mode: 0644]
wasapi2/ring_buffer.h [new file with mode: 0644]
wasapi2/sample_rate_converter.cpp [new file with mode: 0644]
wasapi2/sample_rate_converter.h [new file with mode: 0644]
wasapi2/seq_tab_dialog.cpp [new file with mode: 0644]
wasapi2/seq_tab_dialog.h [new file with mode: 0644]
wasapi2/sequence_dialog.cpp [new file with mode: 0644]
wasapi2/sequencer.cpp [new file with mode: 0644]
wasapi2/sequencer.h [new file with mode: 0644]
wasapi2/sf_com.cpp [new file with mode: 0644]
wasapi2/sf_com.h [new file with mode: 0644]
wasapi2/sf_memory.h [new file with mode: 0644]
wasapi2/sf_windows.cpp [new file with mode: 0644]
wasapi2/sf_windows.h [new file with mode: 0644]
wasapi2/singleton.h [new file with mode: 0644]
wasapi2/stdafx.cpp [new file with mode: 0644]
wasapi2/stdafx.h [new file with mode: 0644]
wasapi2/tab_dialog.cpp [new file with mode: 0644]
wasapi2/tab_dialog.h [new file with mode: 0644]
wasapi2/taskbar.cpp [new file with mode: 0644]
wasapi2/taskbar.h [new file with mode: 0644]
wasapi2/thread_base.cpp [new file with mode: 0644]
wasapi2/thread_base.h [new file with mode: 0644]
wasapi2/timer.cpp [new file with mode: 0644]
wasapi2/timer.h [new file with mode: 0644]
wasapi2/toplevel_window.cpp [new file with mode: 0644]
wasapi2/toplevel_window.h [new file with mode: 0644]
wasapi2/wasapi.cpp [new file with mode: 0644]
wasapi2/wasapi.h [new file with mode: 0644]
wasapi2/wasapi2.manifest [new file with mode: 0644]
wasapi2/wasapi2.rc [new file with mode: 0644]
wasapi2/wasapi2.vcxproj [new file with mode: 0644]
wasapi2/wasapi_base.cpp [new file with mode: 0644]
wasapi2/wasapi_exclusive_timer.cpp [new file with mode: 0644]
wasapi2/wasapi_manager.cpp [new file with mode: 0644]
wasapi2/wavefile.cpp [new file with mode: 0644]
wasapi2/wavefile.h [new file with mode: 0644]
wasapi2/winmain.cpp [new file with mode: 0644]
wasapi2/writer_thread.cpp [new file with mode: 0644]
wasapi2/writer_thread.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..85d14d6
--- /dev/null
@@ -0,0 +1,14 @@
+_UpgradeReport_Files/
+*.vcxproj.*
+*.old
+*.xml
+*.sdf
+*.suo
+*.dsp
+*.dsw
+*.vcproj
+unix/
+Debug/
+Release/
+ipch/
+sidplay2/
\ No newline at end of file
diff --git a/SF.props b/SF.props
new file mode 100644 (file)
index 0000000..1b9e770
--- /dev/null
+++ b/SF.props
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ImportGroup Label="PropertySheets" />
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <IncludePath>H:\libs\DirectXTK\Inc;H:\libs\boost_1_51_0\boost_1_51_0;H:\libs\xbyak\xbyak;H:\libs\zlib125\zlib-1.2.5;H:\libs\lpng150\lpng150;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup>
+    <LibraryPath>H:\libs\zlib125\zlib-1.2.5;$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <StructMemberAlignment>16Bytes</StructMemberAlignment>
+      <EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
+      <PreprocessorDefinitions>_UNICODE;UNICODE;_WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <CompileAsWinRT>true</CompileAsWinRT>
+      <AdditionalUsingDirectories>C:\Program Files %28x86%29\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\Microsoft.VCLibs\11.0\References\CommonConfiguration\neutral;C:\Program Files %28x86%29\Windows Kits\8.0\References\CommonConfiguration\Neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup />
+</Project>
\ No newline at end of file
diff --git a/wasapi2.sln b/wasapi2.sln
new file mode 100644 (file)
index 0000000..efbddb8
--- /dev/null
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2012 for Windows Desktop
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wasapi2", "wasapi2\wasapi2.vcxproj", "{87DCF2CB-7B02-4B6D-9191-237065BDB69C}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|x64 = Debug|x64
+               Release|x64 = Release|x64
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {87DCF2CB-7B02-4B6D-9191-237065BDB69C}.Debug|x64.ActiveCfg = Debug|x64
+               {87DCF2CB-7B02-4B6D-9191-237065BDB69C}.Debug|x64.Build.0 = Debug|x64
+               {87DCF2CB-7B02-4B6D-9191-237065BDB69C}.Release|x64.ActiveCfg = Release|x64
+               {87DCF2CB-7B02-4B6D-9191-237065BDB69C}.Release|x64.Build.0 = Release|x64
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/wasapi2/application.cpp b/wasapi2/application.cpp
new file mode 100644 (file)
index 0000000..8c59c76
--- /dev/null
@@ -0,0 +1,248 @@
+/*\r
+==============================================================================\r
+\r
+This file is part of the async\r
+Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+#include "StdAfx.h"\r
+#include <commctrl.h>\r
+\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+\r
+#include "message_loop.h"\r
+#include "sf_com.h"\r
+#include "application.h"\r
+#include "dout.h"\r
+#include "async_reader.h"\r
+\r
+#ifndef HINST_THISCOMPONENT\r
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;\r
+#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)\r
+#endif\r
+\r
+\r
+using namespace std;\r
+\r
+namespace sf {\r
+#ifdef _DEBUG\r
+  std::wstring application::app_id_(L"SF.async_debug");\r
+#else\r
+  std::wstring application::app_id_(L"SF.async");\r
+#endif\r
+\r
+  application::application()  \r
+  {\r
+    instance_handle_ = HINST_THISCOMPONENT;\r
+    // ベースディレクトリの取得\r
+    wchar_t dir[MAX_PATH];\r
+    ::GetCurrentDirectoryW(MAX_PATH,dir);\r
+    base_directory_.assign(dir);\r
+  }\r
+\r
+  application::~application()\r
+  {\r
+  };\r
+\r
+  int application::execute(HINSTANCE hInstance,\r
+    HINSTANCE hPrevInstance,\r
+    LPTSTR    lpCmdLine,\r
+    int       nCmdShow)\r
+  {\r
+#ifdef _DEBUG\r
+    ::_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);\r
+#endif\r
+    UNREFERENCED_PARAMETER(hPrevInstance);\r
+    UNREFERENCED_PARAMETER(lpCmdLine);\r
+    std::wcout.imbue(std::locale(""));\r
+\r
+    // 2重起動の防止\r
+    SECURITY_DESCRIPTOR sd;\r
+    InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);\r
+    SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE);        \r
+    SECURITY_ATTRIBUTES sec_attr;\r
+    sec_attr.nLength = sizeof (sec_attr);\r
+    sec_attr.lpSecurityDescriptor = &sd;\r
+    sec_attr.bInheritHandle = TRUE; \r
+#ifdef _DEBUG \r
+    sf::handle_holder handle(::CreateMutex(&sec_attr, FALSE, _T("async_mutex_debug")));\r
+#else\r
+    sf::handle_holder handle(::CreateMutex(&sec_attr, FALSE, _T("async_mutex")));\r
+#endif\r
+\r
+    if(NULL == handle.get() || ::GetLastError() == ERROR_ALREADY_EXISTS)\r
+    {\r
+      return 0;\r
+    }\r
+\r
+    // プロセスの優先順位\r
+    SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);\r
+\r
+    // コモンコントロールの初期化 \r
+    static const INITCOMMONCONTROLSEX common_ctrls =\r
+    {\r
+      sizeof(INITCOMMONCONTROLSEX),\r
+      ICC_STANDARD_CLASSES | ICC_BAR_CLASSES\r
+    };\r
+\r
+    InitCommonControlsEx(&common_ctrls);\r
+\r
+    // COMの初期化\r
+    sf::com_initialize init(0,multi_threaded);\r
+    // アプリケーションIDの登録\r
+    sf::throw_if_err<application::exception>()(SetCurrentProcessExplicitAppUserModelID(app_id_.c_str()));\r
+    timeBeginPeriod(1);\r
+    sf::wasapi_device_manager::instance()->current_output_device();\r
+\r
+    // ウィンドウの作成\r
+    window_ = sf::create_toplevel_window(\r
+      std::wstring(L"async"),std::wstring(L"asyncテスト"));\r
+\r
+\r
+    //   bool a = reader_ringbuffer_.is_lock_free();\r
+    //    wdout << ( ? L"**** true ****":L"---- false ----") << std::endl;\r
+    // mixer スレッドの起動\r
+    //mixer_thread_.execute();\r
+    // ファイルリーダースレッドの起動\r
+    reader_thread_.execute();\r
+\r
+    input_thread_.execute();\r
+    // wasapi入力スレッドの起動\r
+    input_thread_.wait_status(input_thread_t::status_device_config_ok);\r
+\r
+    // デフォルトの入出力デバイスをセットする\r
+    try {\r
+      // wasapi出力スレッドの起動\r
+      output_thread_.execute();\r
+      output_thread_.wait_status(output_thread_t::status_device_config_ok);\r
+      apply_output_device_config\r
+        (wasapi_device_manager::instance()->current_output_device_index(),\r
+         wasapi_device_manager::instance()->current_output_device().params);\r
+      apply_input_device_config\r
+        (wasapi_device_manager::instance()->current_input_device_index(),\r
+         wasapi_device_manager::instance()->current_input_device().params);\r
+    } catch (...) {\r
+\r
+    }\r
+\r
+    WPARAM ret = sf::dialog_message_loop(reinterpret_cast<HWND>(window_->raw_handle()))();\r
+    timeEndPeriod(1);\r
+\r
+    // スレッドを終了する\r
+    reader_thread_.change_status(reader_thread_t::status_exit);\r
+    input_thread_.change_status(input_thread_t::status_exit);\r
+   // mixer_thread_.change_status(mixer_thread_t::status_exit);\r
+    output_thread_.change_status(output_thread_t::status_exit);\r
+\r
+    // スレッド終了待ち\r
+    //mixer_thread_.join();\r
+    reader_thread_.join();\r
+    output_thread_.join();\r
+    input_thread_.join();\r
\r
+    // WASAPIをシャットダウンする\r
+    wasapi_device_manager::instance().reset();\r
+\r
+    return ret;\r
+  }\r
+\r
+  void application::reader_setup(const std::wstring& file_path)\r
+  {\r
+    try {\r
+      reader_thread_.setup(file_path);\r
+       window_->reader_ready();\r
+     } catch (win32_error_exception& e) {\r
+      window_->message_box((boost::wformat(L"ファイル読み込み時にエラーが発生しました。%s") % e.error()).str(),wstring(L"ファイル読込エラー"));\r
+    }\r
+  }\r
+\r
+  void application::reader_read_file()\r
+  {\r
+    try {\r
+       reader_thread_.read_file();\r
+       window_->reader_read_file();\r
+     } catch (win32_error_exception& e) {\r
+      window_->message_box((boost::wformat(L"再生開始時にエラーが発生しました。%s") % e.error()).str(),wstring(L"再生エラー"));\r
+    }\r
+  }\r
+  \r
+  void application::reader_pause()\r
+  {\r
+    try {\r
+       reader_thread_.pause();\r
+       if(reader_thread_.status() == reader_thread_t::status_pause_ok)\r
+       {\r
+         window_->reader_pause();\r
+       } else {\r
+         window_->reader_read_file();\r
+       }\r
+     } catch (win32_error_exception& e) {\r
+      window_->message_box((boost::wformat(L"一時停止時にエラーが発生しました。%s") % e.error()).str(),wstring(L"一時停止エラー"));\r
+    }\r
+  }\r
+  \r
+  void application::reader_stop()\r
+  {\r
+    try {\r
+       reader_thread_.stop();\r
+       window_->reader_stop();\r
+     } catch (win32_error_exception& e) {\r
+      window_->message_box((boost::wformat(L"停止時にエラーが発生しました。%s") % e.error()).str(),wstring(L"停止エラー"));\r
+    }\r
+  }\r
+\r
+  void application::reader_end()\r
+  {\r
+    window_->reader_stop();\r
+  }\r
+\r
+  void application::apply_output_device_config(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+  {\r
+    // スレッドの休止\r
+    int reader_status = reader_thread_.status();\r
+    reader_thread_.change_and_wait(reader_thread_t::status_config,reader_thread_t::status_config_ok);\r
+\r
+   // int mixer_status = mixer_thread_.status();\r
+   // mixer_thread_.change_and_wait(mixer_thread_t::status_config,mixer_thread_t::status_config_ok);\r
+\r
+    int input_status = input_thread_.status();\r
+    input_thread_.change_and_wait(input_thread_t::status_pause,input_thread_t::status_pause_ok);\r
+\r
+    // 出力の変更\r
+    output_thread_.apply_config(device_index,params);\r
+\r
+  //  mixer_thread_.init_buffer();\r
+  //  mixer_thread_.change_and_wait(mixer_thread_t::status_process,mixer_thread_t::status_processing);\r
+\r
+    reader_thread_.init_buffer();\r
+    reader_thread_.change_and_wait(reader_thread_t::status_ready,reader_thread_t::status_ready_ok);\r
+\r
+    input_thread_.init_buffer();\r
+    //input_thread_.apply_config(\r
+    //wasapi_device_manager::instance()->current_input_device_index(),\r
+    //wasapi_device_manager::instance()->current_input_device().params);\r
+    input_thread_.change_and_wait(input_status - 1,input_status);\r
+\r
+  }\r
+\r
+}\r
+\r
diff --git a/wasapi2/application.h b/wasapi2/application.h
new file mode 100644 (file)
index 0000000..8c9be53
--- /dev/null
@@ -0,0 +1,146 @@
+#pragma once\r
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+#include "singleton.h"\r
+#include "exception.h"\r
+#include "ring_buffer.h"\r
+#include "wasapi.h"\r
+#include "async_reader.h"\r
+#include "sf_memory.h"\r
+#include "toplevel_window.h"\r
+#include "reader_thread.h"\r
+#include "output_thread.h"\r
+#include "input_thread.h"\r
+#include "mixer_thread.h"\r
+#include "sequencer.h"\r
+\r
+namespace sf {\r
+class application : public singleton<application>\r
+{\r
+  static const size_t Q_SIZE = 8;\r
+public:\r
+  struct exception\r
+    : public sf::win32_error_exception \r
+  {\r
+    exception(uint32_t hr) : win32_error_exception(hr) {};\r
+    exception() : win32_error_exception() {} ;\r
+  };\r
+\r
\r
+  application();\r
+  ~application();\r
+  \r
+  int execute(HINSTANCE hInstance,\r
+                     HINSTANCE hPrevInstance,\r
+                     LPTSTR    lpCmdLine,\r
+                     int       nCmdShow);\r
+  \r
+\r
+  std::wstring& app_id(){return app_id_;};\r
+  HINSTANCE instance_handle() {return instance_handle_;};\r
+  \r
+  // アプリケーションのカレントディレクトリを返す\r
+  const std::wstring& base_directory() const { return base_directory_; }\r
+\r
\r
+// ----------------------------------------\r
+private:\r
+// ----------------------------------------\r
+\r
+  //void wasapi_setup();\r
+  HINSTANCE instance_handle_;\r
+  int return_code_;\r
+  \r
+//---------------------------------------\r
+// ファイル読取り関係\r
+//---------------------------------------\r
+public:\r
+\r
+  void reader_setup(const std::wstring& file_path);\r
+  void reader_read_file();\r
+  void reader_pause();\r
+  void reader_stop();\r
+  void reader_end();\r
+  uint64_t reader_position() {return reader_thread_.position();}\r
+  void reader_position(uint64_t pos){reader_thread_.position(pos);}\r
+  uint64_t reader_data_size(){return reader_thread_.size();}\r
+  void reader_repeat_mode(bool v){ reader_thread_.repeat_mode(v);}\r
+  bool reader_repeat_mode(){ return reader_thread_.repeat_mode();}\r
+  int reader_status(std::memory_order o = std::memory_order_seq_cst) {return reader_thread_.status(o);}\r
+  ringbuffer_t& reader_ringbuffer() {return reader_thread_.ringbuffer();}\r
+private:\r
+  reader_thread_t reader_thread_;\r
+\r
+// ----------------------------\r
+// WASAPI出力関係\r
+// ----------------------------\r
+// 出力デバイスの設定・変更\r
+public:\r
+  void apply_output_device_config(int device_index,wasapi_device_manager::device_info::params_t& params);\r
+  audio_base& output_device() {return output_thread_.device();}\r
+  ringbuffer_t& output_ringbuffer() {return output_thread_.ringbuffer();}\r
+  output_thread_t& output_thread(){return output_thread_;}\r
+private:\r
+  output_thread_t output_thread_;\r
+// -----------------------------  \r
+// WASAPI入力関係\r
+// -----------------------------  \r
+public:\r
+  void apply_input_device_config(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+  {\r
+      input_thread_.apply_config(device_index,params);\r
+  };\r
+  audio_base& input_device() {return input_thread_.device();}\r
+  ringbuffer_t& input_ringbuffer() {return input_thread_.ringbuffer();}\r
+  input_thread_t& input_thread(){return input_thread_;}\r
+private:\r
+  input_thread_t input_thread_;\r
+\r
+// -----------------------------  \r
+// ミキサー関係\r
+// -----------------------------  \r
+public:\r
+  ringbuffer_t& mixer_ringbuffer(){return mixer_thread_.ringbuffer();}\r
+  mixer_thread_t& mixer_thread(){return mixer_thread_;}\r
+private:\r
+  mixer_thread_t mixer_thread_;\r
+\r
+// -----------------------------  \r
+// その他\r
+// -----------------------------  \r
+\r
+  std::wstring base_directory_;\r
+  sf::toplevel_window_ptr window_;\r
+//--------------------------------\r
+// シーケンサ\r
+//--------------------------------\r
+public:\r
+  sf::sequencer & sequencer() {return seq_;}\r
+private:\r
+  sf::sequencer seq_;\r
+  static std::wstring app_id_;\r
+  static const int WAIT_TIMEOUT_DEFAULT = 100; \r
+\r
+};\r
+}\r
+\r
diff --git a/wasapi2/async_reader.cpp b/wasapi2/async_reader.cpp
new file mode 100644 (file)
index 0000000..a1d9a3e
--- /dev/null
@@ -0,0 +1,470 @@
+/*\r
+==============================================================================\r
+\r
+This file is part of the async\r
+Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+\r
+// SDK\82Ì\83T\83\93\83v\83\8b\82ð\89ü\91¢\82µ\82½\8dì\82Á\82½\82à\82Ì\81B\93à\97e\82Í\82Ù\82Ú\82»\82Ì\82Ü\82Ü\82¾\82ª\81A\94ñ\93¯\8aú\93Ç\82Ý\8d\9e\82Ý\82É\r
+// \91Î\89\9e\82³\82¹\82½\81B\r
+\r
+#include "stdafx.h"\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+#include <stdio.h>\r
+#include <assert.h>\r
+#include <wtypes.h>\r
+#include <mmreg.h>\r
+#include <ks.h>\r
+#include <ksmedia.h>\r
+#include "stdafx.h"\r
+#include "async_reader.h"\r
+using namespace std;\r
+\r
+namespace sf\r
+{\r
+  typedef struct\r
+  {\r
+    ULONG Riff4CC;      // "RIFF" 4-character code\r
+    ULONG FileSize;     // total file size in bytes\r
+    ULONG Wave4CC;      // "WAVE" 4-character code\r
+    ULONG Fmt4CC;       // "fmt " 4-character code\r
+    ULONG FormatSize;   // wave format size in bytes\r
+  } FileHeader;\r
+\r
+  typedef struct\r
+  {\r
+    ULONG ChunkType;\r
+    ULONG ChunkSize;\r
+  } ChunkHeader;\r
+\r
+  // Any file smaller than this cannot possibly contain wave data.\r
+#define MIN_WAVE_FILE_SIZE (sizeof(FileHeader)+sizeof(PCMWAVEFORMAT)+sizeof(ChunkHeader)+1)\r
+\r
+  // Macro to build FOURCC from first four characters in ASCII string\r
+#define FOURCC(s)  ((ULONG)(s[0] | (s[1]<<8) | (s[2]<<16) | (s[3]<<24)))\r
+\r
+  //\r
+  // Constructor -- Open wave file and parse file header.\r
+  //\r
+  async_reader::async_reader(const std::wstring file_name, bool repeat_mode) \r
+    : \r
+    stream_status_(false),\r
+    data_chunk_position(0),\r
+    total_data_bytes_(0),\r
+    data_bytes_remaining_(0),\r
+    offset_(0),\r
+    reader_repeat_mode_(repeat_mode),\r
+    async_reading_(false)\r
+  {\r
+\r
+    // \83C\83x\83\93\83g\83I\83u\83W\83F\83N\83g\82Ì\8f\89\8aú\89»\r
+    ZeroMemory(&wfx_, sizeof(wfx_));\r
+    event_.reset(::CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE));\r
+\r
+    // OVERLAPPED\8d\\91¢\91Ì\82Ì\8f\89\8aú\89»\r
+    ZeroMemory(&overlapped_,sizeof(overlapped_));\r
+    overlapped_.hEvent = event_.get();\r
+\r
+\r
+    try{\r
+      // \83t\83@\83C\83\8b\83I\81[\83v\83\93\r
+      file_.reset(CreateFile(file_name.c_str(),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY | FILE_FLAG_OVERLAPPED,NULL));\r
+      if(file_.get() == INVALID_HANDLE_VALUE)\r
+      {\r
+        throw win32_error_exception(GetLastError());\r
+      }\r
+\r
+      // \83t\83@\83C\83\8b\83w\83b\83_\82Ì\93Ç\82Ý\8d\9e\82Ý\r
+      FileHeader fileHdr;\r
+      read_data_sync(reinterpret_cast<BYTE*>(&fileHdr),sizeof(fileHdr));\r
+\r
+      // \83w\83b\83_\82Ì\83`\83F\83b\83N\r
+      if (fileHdr.Riff4CC != FOURCC("RIFF") ||\r
+        fileHdr.FileSize < MIN_WAVE_FILE_SIZE ||\r
+        fileHdr.Wave4CC != FOURCC("WAVE") ||\r
+        fileHdr.Fmt4CC != FOURCC("fmt ") ||\r
+        fileHdr.FormatSize < sizeof(PCMWAVEFORMAT))\r
+      {\r
+        throw file_error_exception(std::wstring(L"\95s\96¾\82È.WAV\83t\83@\83C\83\8b\83t\83H\81[\83}\83b\83g\82Å\82·\81B"));\r
+      }\r
+\r
+      // \83t\83H\81[\83}\83b\83g\83f\83X\83N\83\8a\83v\83^\82Ì\93Ç\82Ý\8d\9e\82Ý\r
+      read_data_sync(reinterpret_cast<BYTE*>(&wfx_),min(fileHdr.FormatSize,sizeof(wfx_)));\r
+      //offset += min(fileHdr.FormatSize,sizeof(wfx_));\r
+\r
+      // Skip over any padding at the end of the format in the format chunk.\r
+      if (fileHdr.FormatSize > sizeof(wfx_))\r
+      {\r
+        offset_ += (fileHdr.FormatSize - sizeof(wfx_));\r
+      }\r
+\r
+      // If format type is PCMWAVEFORMAT, convert to valid WAVEFORMATEX structure.\r
+      if (wfx_.Format.wFormatTag == WAVE_FORMAT_PCM)\r
+      {\r
+        wfx_.Format.cbSize = 0;\r
+      }\r
+\r
+      // If format type is WAVEFORMATEX, convert to WAVEFORMATEXTENSIBLE.\r
+      if (wfx_.Format.wFormatTag == WAVE_FORMAT_PCM ||\r
+        wfx_.Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)\r
+      {\r
+        if (wfx_.Format.wFormatTag == WAVE_FORMAT_PCM)\r
+        {\r
+          wfx_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;\r
+        }\r
+        else\r
+        {\r
+          wfx_.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;\r
+        }\r
+        wfx_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;\r
+\r
+        // Note that the WAVEFORMATEX structure is valid for\r
+        // representing wave formats with only 1 or 2 channels.\r
+        if (wfx_.Format.nChannels == 1)\r
+        {\r
+          wfx_.dwChannelMask = SPEAKER_FRONT_CENTER;\r
+        }\r
+        else if (wfx_.Format.nChannels == 2)\r
+        {\r
+          wfx_.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;\r
+        }\r
+        else\r
+        {\r
+          throw file_error_exception(std::wstring(L"\83T\83|\81[\83g\82µ\82Ä\82¢\82È\82¢.WAV\83t\83@\83C\83\8b\82Å\82·\81B"));\r
+        }\r
+        wfx_.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);\r
+        wfx_.Samples.wValidBitsPerSample = wfx_.Format.wBitsPerSample;\r
+      }\r
+\r
+      // This wave file reader understands only PCM and IEEE float formats.\r
+      if (wfx_.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE ||\r
+        wfx_.SubFormat != KSDATAFORMAT_SUBTYPE_PCM &&\r
+        wfx_.SubFormat != KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)\r
+      {\r
+        throw file_error_exception(std::wstring(L"\83T\83|\81[\83g\82µ\82Ä\82¢\82È\82¢.WAV\83t\83@\83C\83\8b\82Å\82·\81B"));\r
+      }\r
+\r
+      // \83f\81[\83^\83`\83\83\83\93\83N\82ð\8c\9f\8dõ\82·\82é\81B\82»\82Ì\91¼\82Ì\83`\83\83\83\93\83N\82Í\93Ç\82Ý\94ò\82Î\82·\81B\r
+      ChunkHeader chunkHdr;   /// \83`\83\83\83\93\83N\83w\83b\83_\r
+      for (;;)\r
+      {\r
+        // Read header at start of next chunk of file.\r
+        data_chunk_position = offset_;\r
+        read_data_sync(reinterpret_cast<BYTE*>(&chunkHdr),sizeof(ChunkHeader));\r
+        if (chunkHdr.ChunkType == FOURCC("data"))\r
+        {\r
+          break;  // found start of data chunk\r
+        }\r
+      }\r
+\r
+      // We've found the start of the data chunk. We're reader_ready to start\r
+      // playing wave data...\r
+      total_data_bytes_ = chunkHdr.ChunkSize;\r
+      data_bytes_remaining_ = total_data_bytes_;\r
+      if (total_data_bytes_ == 0)\r
+      {\r
+        throw file_error_exception(std::wstring(L"\83t\83@\83C\83\8b\83T\83C\83Y\82ª\95s\90³\82Å\82·\81B"));\r
+      }\r
+      stream_status_ = true;\r
+    } catch (exception& e) {\r
+      stream_status_ = false;\r
+      throw;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Destructor\r
+  //\r
+  async_reader::~async_reader()\r
+  {\r
+    // \8ec\82Á\82Ä\82¢\82éI/O\82Í\83L\83\83\83\93\83Z\83\8b\82·\82é\r
+    if(async_reading_){\r
+      DWORD numbytes_copied;\r
+      DWORD res = GetOverlappedResult(file_.get(),&overlapped_,(LPDWORD)&numbytes_copied,FALSE);\r
+      if(!res)\r
+      {\r
+        switch(GetLastError())\r
+        {\r
+        case ERROR_IO_INCOMPLETE:\r
+        case ERROR_IO_PENDING:\r
+          ::CancelIoEx(file_.get(),&overlapped_);\r
+          WaitForSingleObject(event_.get(),INFINITE);\r
+          break;\r
+        }\r
+      }\r
+    }\r
+    \r
+    // \83t\83@\83C\83\8b\82ð\83N\83\8d\81[\83Y\82·\82é\r
+    if (file_)\r
+    {\r
+      file_.release();\r
+      //      fclose(file_);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Reset the file pointer to the start of the wave data.\r
+  //\r
+  void async_reader::reset_data_position()\r
+  {\r
+    if (!stream_status_ )\r
+    {\r
+      throw file_error_exception(std::wstring(L"\83t\83@\83C\83\8b\82ª\83I\81[\83v\83\93\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B"));\r
+    }\r
+\r
+    // Read the header for the data chunk.\r
+    ChunkHeader chunkHdr;\r
+    offset_ = data_chunk_position;\r
+    read_data_sync(reinterpret_cast<BYTE*>(&chunkHdr),sizeof(chunkHdr));\r
+\r
+    // Sanity check: The chunk header shouldn't have changed.\r
+    if (chunkHdr.ChunkType != FOURCC("data") ||\r
+      chunkHdr.ChunkSize != total_data_bytes_)\r
+    {\r
+      throw file_error_exception(std::wstring(L"\95s\90³\82ÈWAV\83t\83@\83C\83\8b\82Å\82·\81B"));\r
+    }\r
+\r
+    data_bytes_remaining_ = total_data_bytes_;\r
+\r
+  }\r
+\r
+  void async_reader::seek(uint64_t pos)\r
+  {\r
+    if (!stream_status_ )\r
+    {\r
+      throw file_error_exception(std::wstring(L"\83t\83@\83C\83\8b\82ª\83I\81[\83v\83\93\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B"));\r
+    }\r
+    pos = (pos / get_wave_format().Format.nBlockAlign) * get_wave_format().Format.nBlockAlign;\r
+    data_bytes_remaining_ = total_data_bytes_ - pos;\r
+    offset_ = pos + data_chunk_position + sizeof(ChunkHeader);\r
+    overlapped_.Pointer = (PVOID)pos;\r
+  }\r
+\r
+\r
+  //\r
+  // Load next block of wave data from file into playback buffer.\r
+  // In repeat mode, when we reach the end of the wave data in the\r
+  // file, we just reset the file pointer back to the start of the\r
+  // data and continue filling the caller's buffer until it is full.\r
+  // In single-reader_read_file mode, once we reach the end of the wave data in\r
+  // the file, we just fill the buffer with silence instead of with\r
+  // real data.\r
+  //\r
+  void async_reader::read_data(BYTE *buffer, uint64_t numbytes_to_copy)\r
+  {\r
+    assert(async_reading_ == false);\r
+\r
+    if (!stream_status_ )\r
+    {\r
+      throw file_error_exception(std::wstring(L"\83t\83@\83C\83\8b\82ª\83I\81[\83v\83\93\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B"));\r
+    }\r
+\r
+    if (buffer == NULL)\r
+    {\r
+      throw file_error_exception(L"\83o\83b\83t\83@\83A\83h\83\8c\83X\82ª\96³\8cø\82Å\82·\81B");\r
+    }\r
+\r
+    if (numbytes_to_copy == 0)\r
+    {\r
+      throw file_error_exception(L"\93Ç\82Ý\8d\9e\82Ý\83o\83C\83g\90\94\82Ì\8ew\92è\82ª0\82Å\82·\81B");\r
+    }\r
+\r
+    ULONG numbytes_copied;\r
+    overlapped_.Pointer = (PVOID)offset_;\r
+    int result = ReadFile(file_.get(),buffer,numbytes_to_copy,&numbytes_copied,&overlapped_);\r
+    if(!result)\r
+    {\r
+      DWORD err = GetLastError(); \r
+      switch(err)\r
+      {\r
+      case ERROR_HANDLE_EOF:\r
+        {\r
+          if(numbytes_to_copy > numbytes_copied)\r
+          {\r
+            BYTE silence = (wfx_.Format.wBitsPerSample==8) ? 0x80 : 0;\r
+            memset(buffer + numbytes_copied, silence, numbytes_to_copy - numbytes_copied);\r
+          }\r
+          offset_ += numbytes_copied; \r
+          async_reading_ = false;\r
+\r
+          if(reader_repeat_mode_){\r
+            reset_data_position();\r
+          }\r
+          throw file_eof_exception(std::wstring(L"\83t\83@\83C\83\8b\82Ì\8fI\82í\82è\82É\92B\82µ\82½\82½\82ß\81A\82±\82ê\88È\8fã\83f\81[\83^\93Ç\82Ý\8d\9e\82Þ\82±\82Æ\82ª\82Å\82«\82Ü\82¹\82ñ\81B"));\r
+        }\r
+        break;\r
+      case ERROR_IO_PENDING:\r
+        //{\r
+        //  DWORD res = GetOverlappedResult(file_.get(),&overlapped_,&num_of_read,TRUE);\r
+        //  if(!res)\r
+        //  {\r
+        //    throw file_error_exception(win32_error_exception::get_last_error_str());\r
+        //  } else {\r
+        //    if(res != numbytes_to_copy)\r
+        //    {\r
+        //      throw file_error_exception(std::wstring(L"\93Ç\82Ý\8d\9e\82ñ\82¾\83f\81[\83^\83T\83C\83Y\82ª\8d\87\82¢\82Ü\82¹\82ñ\81B"));\r
+        //    }\r
+        //  }\r
+        //}\r
+        async_reading_ = true;\r
+        break;\r
+      default:\r
+        throw file_error_exception(win32_error_exception::get_last_error_str(err));\r
+        break;\r
+      }\r
+    } else {\r
+      data_bytes_remaining_ -= numbytes_copied;\r
+      offset_ += numbytes_copied;\r
+      async_reading_ = false;\r
+      //current += numbytes_copied;\r
+    }\r
+\r
+\r
+    //if(numbytes_copied > data_bytes_remaining_)\r
+    //{\r
+    //  if (fread(current, 1, data_bytes_remaining_, file_) != data_bytes_remaining_)\r
+    //  {\r
+    //    throw exception(L"\95s\90³\82ÈWAV\83t\83@\83C\83\8b\82Å\82·\81B");\r
+    //  }\r
+    //  current += data_bytes_remaining_;\r
+    //  numbytes_copied -= data_bytes_remaining_;\r
+    //  data_bytes_remaining_ = 0;\r
+\r
+    //  // The file pointer now sits at the end of the data chunk.\r
+    //  // Are we operating in repeat mode?\r
+    //  if (!reader_repeat_mode_)\r
+    //  {\r
+    //    // Nope, we're operating in single-reader_read_file mode. Fill\r
+    //    // the rest of the buffer with silence and return.\r
+    //    BYTE silence = (wfx_.Format.wBitsPerSample==8) ? 0x80 : 0;\r
+    //    memset(current, silence, numbytes_copied);\r
+    //    return;  // yup, we're done\r
+    //  }\r
+    //  // Yes, we're operating in repeat mode, so loop back to\r
+    //  // the start of the wave data in the file's data chunk\r
+    //  // and continue loading data into the caller's buffer.\r
+    //  reset_data_position();\r
+\r
+    //}\r
+\r
+    //assert(numbytes_copied > 0);\r
+    //assert(numbytes_copied <= data_bytes_remaining_);\r
+\r
+    //// The remainder of the data chunk is big enough to\r
+    //// completely fill the remainder of the caller's buffer.\r
+    //if (fread(buffer, 1, numbytes_copied, file_) != numbytes_copied)\r
+    //{\r
+    //  throw exception(L"\95s\90³\82ÈWAV\83t\83@\83C\83\8b\82Å\82·\81B");\r
+    //}\r
+    //data_bytes_remaining_ -= numbytes_copied;\r
+    //current += numbytes_copied;\r
+  }\r
+\r
+  void async_reader::read_data_sync(BYTE *buffer, uint64_t numbytes_to_copy)\r
+  {\r
+    uint32_t numbytes_copied(0);\r
+    overlapped_.Pointer = (PVOID)offset_;\r
+\r
+    int result = ReadFile(file_.get(),buffer, numbytes_to_copy, (LPDWORD)&numbytes_copied, &overlapped_);\r
+\r
+    if(!result)\r
+    {\r
+      uint32_t err = GetLastError(); \r
+      switch(err)\r
+      {\r
+      case ERROR_HANDLE_EOF:\r
+        {\r
+          offset_ += numbytes_copied;\r
+          //if(reader_repeat_mode_){\r
+          //  reset_data_position();\r
+          //}\r
+          throw file_eof_exception(std::wstring(L"\83t\83@\83C\83\8b\82Ì\8fI\82í\82è\82É\92B\82µ\82½\82½\82ß\81A\83w\83b\83_\82ð\93Ç\82Ý\8d\9e\82Þ\82±\82Æ\82ª\82Å\82«\82Ü\82¹\82ñ\81B"));\r
+        }\r
+        break;\r
+      case ERROR_IO_PENDING:\r
+        {\r
+          DWORD res = GetOverlappedResult(file_.get(),&overlapped_,(LPDWORD)&numbytes_copied,TRUE);\r
+          if(!res)\r
+          {\r
+            throw file_error_exception(win32_error_exception::get_last_error_str());\r
+          } else {\r
+            if(numbytes_copied != numbytes_to_copy)\r
+            {\r
+              throw file_error_exception(std::wstring(L"\93Ç\82Ý\8d\9e\82ñ\82¾\83f\81[\83^\83T\83C\83Y\82ª\8d\87\82¢\82Ü\82¹\82ñ\81B"));\r
+            }\r
+            offset_ += numbytes_copied;\r
+          }\r
+        }\r
+        break;\r
+      default:\r
+          throw file_error_exception(win32_error_exception::get_last_error_str(err));\r
+        break;\r
+      }\r
+    } else {\r
+      offset_ += numbytes_copied;\r
+    }\r
+  };\r
+\r
+  void async_reader::wait(int timer)\r
+  {\r
+    if(!async_reading_)\r
+    {\r
+      return;\r
+    }\r
+\r
+    uint32_t numbytes_copied(0);\r
+    DWORD res = GetOverlappedResult(file_.get(),&overlapped_,(LPDWORD)&numbytes_copied,TRUE);\r
+    // \83G\83\89\81[\83`\83F\83b\83N\r
+    if(!res)\r
+    {\r
+      DWORD err = GetLastError();\r
+      switch (err) \r
+      { \r
+      case ERROR_HANDLE_EOF: \r
+        { \r
+          // Handle an end of file\r
+          //if(reader_repeat_mode_){\r
+          //  reset_data_position();\r
+          //}\r
+          throw file_eof_exception(win32_error_exception::get_last_error_str(err));\r
+          break;\r
+        } \r
+      default:\r
+        {\r
+          throw file_error_exception(win32_error_exception::get_last_error_str(err));\r
+        }\r
+      }\r
+    }\r
+\r
+    ResetEvent(event_.get());\r
+    offset_ += numbytes_copied;\r
+    data_bytes_remaining_ -= numbytes_copied;\r
+    if(data_bytes_remaining_ <= 0 && reader_repeat_mode_)\r
+    {\r
+      reset_data_position();\r
+    }\r
+    async_reading_ = false;\r
+  };\r
+\r
+\r
+}\r
diff --git a/wasapi2/async_reader.h b/wasapi2/async_reader.h
new file mode 100644 (file)
index 0000000..06461c5
--- /dev/null
@@ -0,0 +1,88 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#include <audioclient.h>
+#include "exception.h"
+#include "audio_source.h"
+#include "sf_memory.h"
+
+namespace sf {
+  class async_reader : public audio_source
+  {
+  public:
+    struct file_error_exception : public sf::exception 
+    {
+      file_error_exception(const std::wstring& reason) : exception(reason) {};
+      file_error_exception(const wchar_t* reason) : exception(std::wstring(reason)) {};
+    };
+
+    struct file_eof_exception : public sf::exception
+    {
+      file_eof_exception(const std::wstring& reason) : exception(reason) {};
+      file_eof_exception(const wchar_t* reason) : exception(std::wstring(reason)) {};
+
+    };
+    async_reader(const std::wstring file_name, bool repeat_mode);
+    ~async_reader();
+    bool stream_status() { return stream_status_; };
+    WAVEFORMATEXTENSIBLE &get_wave_format()
+    {
+      return  wfx_ ;
+    };
+
+    bool more_data_available()
+    {
+      return (stream_status_  &&
+        (reader_repeat_mode_  || data_bytes_remaining_ > 0));
+    };
+    uint64_t total_data_bytes() { return total_data_bytes_; }
+    uint64_t data_bytes_remaining() { return data_bytes_remaining_; }
+    bool seekable() {return true;}
+    void seek(uint64_t pos);
+    void read_data(BYTE *buffer, uint64_t numbytes_to_copy);
+    void read_data_sync(BYTE *buffer, uint64_t numbytes_to_copy);
+
+    void reset_data_position();
+    HANDLE raw_handle() { return file_.get();};
+    void wait(int timer = INFINITE);
+    bool repeat_mode() const  {return reader_repeat_mode_;}
+    void repeat_mode(bool v) { reader_repeat_mode_ = v;}
+  private:
+
+    handle_holder file_;
+    handle_holder event_;
+    bool stream_status_;
+    uint64_t data_chunk_position;
+    uint64_t total_data_bytes_;
+    uint64_t data_bytes_remaining_;
+    uint64_t offset_;
+    WAVEFORMATEXTENSIBLE wfx_;
+    bool reader_repeat_mode_;
+    bool async_reading_;
+    OVERLAPPED overlapped_;
+
+  };
+
+
+}
+
diff --git a/wasapi2/audio_base.h b/wasapi2/audio_base.h
new file mode 100644 (file)
index 0000000..3bbb0a3
--- /dev/null
@@ -0,0 +1,77 @@
+#pragma once\r
+/*\r
+  ==============================================================================\r
+\r
+   Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+#include "exception.h"\r
+namespace sf {\r
+struct audio_base : boost::noncopyable\r
+{\r
+  virtual ~audio_base() {};\r
+  virtual bool is_enabled () const  = 0;\r
+  /// \83C\83x\83\93\83g\83\82\81[\83h\82Ì\91Ò\82¿\r
+  virtual void wait() = 0;\r
+  /// \83T\83E\83\93\83h\8dÄ\90\8f\88\97\9d\r
+ // virtual size_t process(BYTE* buffer,size_t size) = 0;\r
+  virtual bool is_start() = 0;\r
+  virtual uint32_t get_buffer(BYTE** buffer,uint32_t size) = 0;\r
+  virtual uint32_t get_buffer(BYTE** buffer) = 0;\r
+  virtual void release_buffer(uint32_t num_byte_written) = 0;\r
+  virtual void start() = 0;\r
+  virtual void stop() = 0;\r
+  virtual void reset() = 0;\r
+  virtual uint32_t get_buffer_byte_size () const  = 0;\r
+  virtual uint32_t get_frame_size() const = 0;\r
+  virtual uint32_t get_buffer_size () const  = 0;\r
+  virtual uint32_t get_current_padding()  = 0;\r
+  virtual uint64_t get_position() const = 0;\r
+  virtual uint64_t get_buffer_duration() = 0;\r
+  virtual uint32_t get_channel() = 0;\r
+  virtual win32_error_exception* const result()  = 0;\r
+};\r
+\r
+struct get_buffer \r
+{\r
+  get_buffer(audio_base& b,uint32_t s) : audio_base_(b),buffer_size_(0)\r
+  {\r
+    buffer_size_ = b.get_buffer(&buffer_ptr_,s);\r
+  }\r
+\r
+  get_buffer(audio_base& b) : audio_base_(b),buffer_size_(0)\r
+  {\r
+    buffer_size_ = b.get_buffer(&buffer_ptr_);\r
+  }\r
+\r
+  ~get_buffer()\r
+  {\r
+    audio_base_.release_buffer(buffer_size_);\r
+  }\r
\r
+  operator BYTE*(){return buffer_ptr_;}\r
+  BYTE* get() {return buffer_ptr_;}\r
+  const uint32_t size() const { return buffer_size_;}\r
+  const uint32_t size_byte() const { return audio_base_.get_buffer_byte_size();}\r
+private:\r
+  uint32_t buffer_size_;\r
+  BYTE* buffer_ptr_;\r
+  audio_base& audio_base_;\r
+};\r
+}\r
+\r
diff --git a/wasapi2/audio_filter.h b/wasapi2/audio_filter.h
new file mode 100644 (file)
index 0000000..a439c10
--- /dev/null
@@ -0,0 +1,31 @@
+#pragma once
+/*
+  ==============================================================================
+
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+namespace sf{
+class audio_filter
+{
+public:
+  virtual ~audio_filter() {}
+  virtual void apply(float * in,float * out,size_t size) = 0;
+};
+}
+
diff --git a/wasapi2/audio_processor.h b/wasapi2/audio_processor.h
new file mode 100644 (file)
index 0000000..c99fe7f
--- /dev/null
@@ -0,0 +1,31 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+namespace sf{
+
+  struct audio_processor
+  {
+  public:
+    virtual ~audio_processor() {};
+  };
+}
\ No newline at end of file
diff --git a/wasapi2/audio_source.h b/wasapi2/audio_source.h
new file mode 100644 (file)
index 0000000..f40f9d2
--- /dev/null
@@ -0,0 +1,42 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+namespace sf{
+
+  class audio_source
+  {
+  public:
+    virtual ~audio_source() {};
+    virtual bool seekable() = 0;
+    virtual bool stream_status() = 0;
+    virtual WAVEFORMATEXTENSIBLE &get_wave_format() = 0;
+    virtual bool more_data_available() = 0;
+    virtual void read_data(BYTE *buffer, uint64_t numbytes) = 0;
+    virtual void reset_data_position() = 0;
+    virtual uint64_t total_data_bytes() = 0;
+    virtual void seek(uint64_t pos) = 0;
+    virtual uint64_t data_bytes_remaining() = 0;
+    virtual HANDLE raw_handle() = 0;
+    virtual void wait(int timer = -1) = 0;
+  };
+}
\ No newline at end of file
diff --git a/wasapi2/base_window.cpp b/wasapi2/base_window.cpp
new file mode 100644 (file)
index 0000000..ca9ceaa
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-10 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#include "StdAfx.h"
+#include "base_window.h"
+
+namespace sf {
+}
\ No newline at end of file
diff --git a/wasapi2/base_window.h b/wasapi2/base_window.h
new file mode 100644 (file)
index 0000000..12655e1
--- /dev/null
@@ -0,0 +1,67 @@
+#pragma once\r
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+namespace sf {\r
+/** window \83x\81[\83X\83N\83\89\83X */\r
+\r
+struct rect {\r
+  uint32_t width;\r
+  uint32_t height;\r
+};\r
+\r
+struct base_window : boost::noncopyable\r
+{\r
+  typedef boost::signals2::signal<void ()> on_render_type;\r
+\r
+  on_render_type on_render;\r
+  \r
+  // \90\82ÌWindow\83n\83\93\83h\83\8b\82ð\95Ô\82·\81B\r
+  virtual void * raw_handle() const = 0;\r
+  // \83E\83B\83\93\83h\83E\82ð\90\90¬\82·\82é\r
+  virtual void create() = 0;\r
+//  virtual void show(uint32_t show_flag) = 0;\r
+  // \83E\83B\83\93\83h\83E\82ð\95\\8e¦\82·\82é\r
+  virtual void show() = 0;\r
+  // \83E\83B\83\93\83h\83E\82ª\8d¡\95\\8e¦\82³\82ê\82Ä\82¢\82é\82©\82ð\95Ô\82·\r
+  virtual bool is_show() = 0;\r
+  // \83E\83B\83\93\83h\83E\82ð\89B\82·\r
+  virtual void hide() = 0;\r
+  //virtual void activate() = 0;\r
+  //virtual bool is_activate() = 0;\r
+  //virtual void deactivate() = 0;\r
+  //virtual void \r
+  //virtual void size(uint32_t width,uint32_t height); \r
+  //virtual rect size(); \r
+\r
+  virtual void text(std::wstring& text) = 0;\r
+  //virtual std::wstring text() = 0;\r
+\r
+  virtual void update() = 0;\r
+\r
+protected:\r
+  virtual ~base_window() {};\r
+\r
+};\r
+\r
+}\r
+\r
diff --git a/wasapi2/code_converter.cpp b/wasapi2/code_converter.cpp
new file mode 100644 (file)
index 0000000..5de5e82
--- /dev/null
@@ -0,0 +1,34 @@
+#include "stdafx.h"
+
+namespace sf 
+{
+
+  code_converter<char,wchar_t>::code_converter(const char*p)
+  {
+    int len = ::MultiByteToWideChar(CP_ACP,0,p,-1,NULL,0);
+    m_dest.reset(new wchar_t[len]);
+    ::MultiByteToWideChar(CP_ACP,0,p,-1,&m_dest[0],len);
+  };
+
+  code_converter<char,wchar_t>::code_converter(const std::string& p)
+  {
+    int len = ::MultiByteToWideChar(CP_ACP,0,p.c_str(),-1,NULL,0);
+    m_dest.reset(new wchar_t[len]);
+    ::MultiByteToWideChar(CP_ACP,0,p.c_str(),-1,&m_dest[0],len);
+  };
+
+  code_converter<wchar_t,char>::code_converter(const wchar_t*p)
+  {
+    int len = ::WideCharToMultiByte(CP_ACP,0,p,-1,NULL,0,NULL,NULL);
+    m_dest.reset(new char[len]);
+    ::WideCharToMultiByte(CP_ACP,0,p,-1,&m_dest[0],len,NULL,NULL);
+  };
+
+  code_converter<wchar_t,char>::code_converter(const std::wstring & p)
+  {
+    int len = ::WideCharToMultiByte(CP_ACP,0,p.c_str(),-1,NULL,0,NULL,NULL);
+    m_dest.reset(new char[len]);
+    ::WideCharToMultiByte(CP_ACP,0,p.c_str(),-1,&m_dest[0],len,NULL,NULL);
+  };
+
+};
\ No newline at end of file
diff --git a/wasapi2/code_converter.h b/wasapi2/code_converter.h
new file mode 100644 (file)
index 0000000..9ee1cc2
--- /dev/null
@@ -0,0 +1,79 @@
+#pragma once\r
+\r
+\r
+/** @file\r
+ *  @author S.F. (Satoshi Fujiwara)\r
+ *  @brief wchar_t <--> char の変換ユーティリティ\r
+ *  引数として文字列を引き渡す際、変換が必要な場合、下記のようにアダプタ的に使用することを想定している。\r
+ *  std::wstring a(L"abcd");\r
+ *  std::wstring b((sf::code_converter<wcha_t,char>(a)));\r
+ *\r
+ * 後、ATLコード差し替え用のtypedefも用意している。\r
+ *  これは、アダプタとしての利用のみに限定される。\r
+ *  sf::ct2a hoge_(L"abcef"); // 想定していない(動作する場合もあるし、ダメな場合もある)\r
+ */\r
+\r
+namespace sf \r
+{\r
+    /** 雛形 */\r
+    template <typename SrcChar,typename DestChar>\r
+    struct code_converter\r
+    {\r
+    public:\r
+        explicit code_converter(SrcChar* p);\r
+        explicit code_converter(std::basic_string<SrcChar> & p);\r
+        operator DestChar*();\r
+    };\r
+\r
+    /** char -> wchar_tへの変換 */\r
+    template <>\r
+    struct code_converter<char,wchar_t>\r
+    {\r
+        explicit code_converter(const char* p);\r
+        explicit code_converter(const std::string& p);\r
+\r
+        operator wchar_t*() const {return m_dest.get();}\r
+    private:\r
+        boost::scoped_array<wchar_t> m_dest;\r
+    };\r
+\r
+    /** wchar_t -> char */\r
+    template <>\r
+    struct code_converter<wchar_t,char>\r
+    {\r
+        explicit code_converter(const wchar_t* p);\r
+        explicit code_converter(const std::wstring& p);\r
+        operator char* () const {return m_dest.get();}\r
+    private:\r
+        boost::scoped_array<char> m_dest;\r
+    };\r
+\r
+    /** ATLコード差し替えのためのエイリアス */\r
+    typedef sf::code_converter<char,wchar_t> ca2w;\r
+\r
+    /** ATLコード差し替えのためのエイリアス */\r
+    typedef sf::code_converter<wchar_t,char> cw2a;\r
+\r
+    #ifdef _UNICODE\r
+\r
+        /** ATLコード差し替えのためのエイリアス */\r
+        typedef sf::code_converter<char,wchar_t> ca2t;\r
+        /** ATLコード差し替えのためのエイリアス */\r
+        typedef sf::code_converter<wchar_t,char> ct2a;\r
+\r
+        /** ATLコード差し替えのためのエイリアス */\r
+        inline const wchar_t* ct2w(const wchar_t* p) { return p;};\r
+        /** ATLコード差し替えのためのエイリアス */\r
+        inline const wchar_t* cw2t(const wchar_t* p) { return p;};\r
+\r
+    #else\r
+\r
+        /** ATLコード差し替えのためのエイリアス */\r
+        inline const char* ct2a(const char* p) { return p;};\r
+        /** ATLコード差し替えのためのエイリアス */\r
+        inline const char* ca2t(const char* p) { return p;};\r
+\r
+    #endif\r
+}\r
+\r
+\r
diff --git a/wasapi2/config_tab_dialog.cpp b/wasapi2/config_tab_dialog.cpp
new file mode 100644 (file)
index 0000000..b5f96ca
--- /dev/null
@@ -0,0 +1,712 @@
+/*\r
+==============================================================================\r
+\r
+Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+/* ToDo\r
+\r
+TODO: リサイズに対応する\r
+\r
+*/\r
+\r
+#include "stdafx.h"\r
+#include "resource.h"\r
+#define BOOST_ASSIGN_MAX_PARAMS 7\r
+#include <boost/assign.hpp>\r
+#include <boost/assign/ptr_list_of.hpp>\r
+#include <boost/assign/ptr_list_inserter.hpp>\r
+#include <boost/foreach.hpp>\r
+\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+\r
+#include "sf_windows.h"\r
+#include "CommDlg.h"\r
+#include "icon.h"\r
+#include "timer.h"\r
+#include "exception.h"\r
+#include "application.h"\r
+#include "config_tab_dialog.h"\r
+\r
+#define THROW_IFERR(hres) \\r
+  if (FAILED(hres)) { throw sf::win32_error_exception(hres); }\r
+\r
+#ifndef HINST_THISCOMPONENT\r
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;\r
+#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)\r
+#endif\r
+\r
+namespace sf \r
+{\r
+    config_tab_dialog::config_tab_dialog(sf::base_window& parent_window,HWND tab_hwnd,int tab_id,const std::wstring& menu_name,const std::wstring& name,HINSTANCE inst,LPCTSTR temp)\r
+      : tab_dialog_base(parent_window,tab_hwnd,tab_id,menu_name,name,inst,temp)\r
+      ,update_config_dialog_(false)\r
+      ,edit_output_config_(false)\r
+      ,edit_input_config_(false)\r
+    {\r
+      create();\r
+      hide();\r
+    }\r
+\r
+    LRESULT config_tab_dialog::window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)\r
+    {\r
+      switch(message)\r
+      {\r
+      case WM_INITDIALOG:\r
+        init_config_dialog();\r
+        return TRUE;\r
+      case WM_COMMAND:\r
+        {\r
+          switch(LOWORD(wParam)){\r
+            // ---------------------------------\r
+            // 出力\r
+            // ---------------------------------\r
+          case IDC_ENDPOINT_DEVICE:\r
+            // エンドポイントデバイス\r
+            if(HIWORD(wParam) == CBN_SELCHANGE && !update_config_dialog_)\r
+            {\r
+              edit_output_config_ = true;\r
+              current_output_driver_index_ = SendMessage(GetDlgItem(hwnd,IDC_ENDPOINT_DEVICE),CB_GETITEMDATA,SendMessage(GetDlgItem(hwnd,IDC_ENDPOINT_DEVICE),CB_GETCURSEL,0,0),0);\r
+              update_config_dialog();\r
+            }\r
+            return TRUE;\r
+          case IDC_SAMPLE_BIT:\r
+            // サンプルビット数\r
+            if(HIWORD(wParam) == CBN_SELCHANGE && !update_config_dialog_)\r
+            {\r
+              edit_output_config_ = true;\r
+              editing_output_params_.bits =  SendMessage(GetDlgItem(hwnd,IDC_SAMPLE_BIT),CB_GETITEMDATA,SendMessage(GetDlgItem(hwnd,IDC_SAMPLE_BIT),CB_GETCURSEL,0,0),0);\r
+              update_config_dialog();\r
+            }\r
+            return TRUE;\r
+          case IDC_VALID_SAMPLE_BITS:\r
+            // 実際のサンプルビット数\r
+            if(HIWORD(wParam) == CBN_SELCHANGE &&  !update_config_dialog_)\r
+            {\r
+              edit_output_config_ = true;\r
+              editing_output_params_.valid_bits =  SendMessage(GetDlgItem(hwnd,IDC_VALID_SAMPLE_BITS),CB_GETITEMDATA,SendMessage(GetDlgItem(hwnd,IDC_VALID_SAMPLE_BITS),CB_GETCURSEL,0,0),0);\r
+              update_config_dialog();\r
+            }\r
+            return TRUE;\r
+          case IDC_SAMPLE_RATE:\r
+            // サンプル周波数\r
+            if(HIWORD(wParam) == CBN_SELCHANGE &&  !update_config_dialog_)\r
+            {\r
+              edit_output_config_ = true;\r
+              editing_output_params_.sample_rate =  SendMessage(GetDlgItem(hwnd,IDC_SAMPLE_RATE),CB_GETITEMDATA,SendMessage(GetDlgItem(hwnd,IDC_SAMPLE_RATE),CB_GETCURSEL,0,0),0);\r
+              update_config_dialog();\r
+            }\r
+            return TRUE;\r
+          case IDC_EXC_MODE:\r
+            // 排他モード\r
+            {\r
+              if(!update_config_dialog_){\r
+                edit_output_config_ = true;\r
+\r
+                //application::instance()->exclusive_mode(::SendMessage(GetDlgItem(hwnd,IDC_EXC_MODE),BM_GETCHECK,0,0) == BST_CHECKED);\r
+                editing_output_params_.exclusive_mode = ::SendMessage(GetDlgItem(hwnd,IDC_EXC_MODE),BM_GETCHECK,0,0) == BST_CHECKED;\r
+                update_config_dialog();\r
+              }\r
+            }\r
+            return TRUE;\r
+          case IDC_EVENT_MODE:\r
+            // イベントモード\r
+            {\r
+              if(!update_config_dialog_){\r
+                //application::instance()->exclusive_mode(::SendMessage(GetDlgItem(hwnd,IDC_EXC_MODE),BM_GETCHECK,0,0) == BST_CHECKED);\r
+                editing_output_params_.event_mode = ::SendMessage(GetDlgItem(hwnd,IDC_EVENT_MODE),BM_GETCHECK,0,0) == BST_CHECKED;\r
+                edit_output_config_ = true;\r
+                update_config_dialog();\r
+              }\r
+            }\r
+            return TRUE;\r
+\r
+          case IDC_LATENCY:\r
+            // レイテンシ\r
+            if(HIWORD(wParam) == EN_UPDATE  &&  !update_config_dialog_)\r
+            {\r
+              edit_output_config_ = true;\r
+              enable_control(hwnd_,IDC_APPLY,true);\r
+              enable_control(hwnd_,IDC_CANCEL,true);\r
+              //BOOL success = FALSE;\r
+              //int res = 0;\r
+              //res = GetDlgItemInt(hwnd_,IDC_LATENCY,&success,TRUE);\r
+              //if(success)\r
+              //{\r
+              //  editing_output_params_.latency = res;\r
+              //} else {\r
+              //  message_box(L"不正な値が設定されています。",L"エラー",MB_OK);\r
+              //}\r
+            }\r
+            return TRUE;\r
+            // ---------------------------------\r
+            // 入力\r
+            // ---------------------------------\r
+          case IDC_INPUT_ENDPOINT_DEVICE:\r
+            if(HIWORD(wParam) == CBN_SELCHANGE && !update_config_dialog_)\r
+            {\r
+              edit_input_config_ = true;\r
+              current_input_driver_index_ \r
+                = SendMessage(\r
+                GetDlgItem(hwnd,IDC_INPUT_ENDPOINT_DEVICE),\r
+                CB_GETITEMDATA,\r
+                SendMessage(GetDlgItem(hwnd,IDC_INPUT_ENDPOINT_DEVICE),CB_GETCURSEL,0,0),\r
+                0);\r
+              update_config_dialog();\r
+            }\r
+            return TRUE;\r
+          case IDC_INPUT_SAMPLE_BIT:\r
+            if(HIWORD(wParam) == CBN_SELCHANGE && !update_config_dialog_)\r
+            {\r
+              edit_input_config_ = true;\r
+              editing_input_params_.bits \r
+                =  SendMessage(\r
+                GetDlgItem(hwnd,IDC_INPUT_SAMPLE_BIT),\r
+                CB_GETITEMDATA,\r
+                SendMessage(GetDlgItem(hwnd,IDC_INPUT_SAMPLE_BIT),CB_GETCURSEL,0,0)\r
+                ,0);\r
+              update_config_dialog();\r
+            }\r
+            return TRUE;\r
+          case IDC_INPUT_VALID_SAMPLE_BITS:\r
+            if(HIWORD(wParam) == CBN_SELCHANGE && !update_config_dialog_)\r
+            {\r
+              edit_input_config_ = true;\r
+              editing_input_params_.valid_bits \r
+                =  SendMessage(\r
+                GetDlgItem(hwnd,IDC_INPUT_VALID_SAMPLE_BITS),\r
+                CB_GETITEMDATA,\r
+                SendMessage(GetDlgItem(hwnd,IDC_INPUT_VALID_SAMPLE_BITS),CB_GETCURSEL,0,0),\r
+                0);\r
+              update_config_dialog();\r
+            }\r
+            return TRUE;\r
+          case IDC_INPUT_SAMPLE_RATE:\r
+            if(HIWORD(wParam) == CBN_SELCHANGE &&  !update_config_dialog_)\r
+            {\r
+              edit_input_config_ = true;\r
+              editing_input_params_.sample_rate\r
+                =  SendMessage(\r
+                GetDlgItem(hwnd,IDC_INPUT_SAMPLE_RATE),\r
+                CB_GETITEMDATA,\r
+                SendMessage(GetDlgItem(hwnd,IDC_INPUT_SAMPLE_RATE),CB_GETCURSEL,0,0),\r
+                0);\r
+              update_config_dialog();\r
+            }\r
+            return TRUE;\r
+          case IDC_INPUT_EXC_MODE:\r
+            {\r
+              if(!update_config_dialog_){\r
+                edit_input_config_ = true;\r
+\r
+                //application::instance()->exclusive_mode(::SendMessage(GetDlgItem(hwnd,IDC_INPUT_EXC_MODE),BM_GETCHECK,0,0) == BST_CHECKED);\r
+                editing_input_params_.exclusive_mode \r
+                  = ::SendMessage(GetDlgItem(hwnd,IDC_INPUT_EXC_MODE),BM_GETCHECK,0,0) \r
+                  == BST_CHECKED;\r
+                update_config_dialog();\r
+              }\r
+            }\r
+            return TRUE;\r
+          case IDC_INPUT_EVENT_MODE:\r
+            {\r
+              if(!update_config_dialog_){\r
+                //application::instance()->exclusive_mode(::SendMessage(GetDlgItem(hwnd,IDC_INPUT_EXC_MODE),BM_GETCHECK,0,0) == BST_CHECKED);\r
+                editing_input_params_.event_mode \r
+                  = ::SendMessage(GetDlgItem(hwnd,IDC_INPUT_EVENT_MODE),BM_GETCHECK,0,0) \r
+                  == BST_CHECKED;\r
+                edit_input_config_ = true;\r
+                update_config_dialog();\r
+              }\r
+            }\r
+            return TRUE;\r
+          case IDC_INPUT_LATENCY:\r
+            if(HIWORD(wParam) == EN_UPDATE  &&  !update_config_dialog_)\r
+            {\r
+              edit_input_config_ = true;\r
+              enable_control(hwnd_,IDC_APPLY,true);\r
+              enable_control(hwnd_,IDC_CANCEL,true);\r
+              //BOOL success = FALSE;\r
+              //int res = 0;\r
+              //res = GetDlgItemInt(hwnd_,IDC_INPUT_LATENCY,&success,TRUE);\r
+              //if(success)\r
+              //{\r
+              //  editing_input_params_.latency = res;\r
+              //} else {\r
+              //  message_box(L"不正な値が設定されています。",L"エラー",MB_OK);\r
+              //}\r
+            }\r
+            return TRUE;\r
+            // ---------------------------------\r
+            // 設定反映\r
+            // ---------------------------------\r
+          case IDC_APPLY:\r
+            {\r
+              BOOL success = FALSE;\r
+              REFERENCE_TIME res(0);\r
+\r
+              // 出力デバイス設定\r
+\r
+              if(edit_output_config_){\r
+                res = GetDlgItemInt(hwnd_,IDC_LATENCY,&success,TRUE);\r
+                if(success)\r
+                {\r
+                  editing_output_params_.latency = res * 10000;\r
+                } else {\r
+                  message_box(L"レイテンシに不正な値が設定されています。",L"エラー",MB_OK);\r
+                }\r
+                try {\r
+                  application::instance()->apply_output_device_config\r
+                    (current_output_driver_index_,editing_output_params_);\r
+                  edit_output_config_ = false;\r
+                } catch (...) \r
+                {\r
+                  application::instance()->apply_output_device_config\r
+                    (wasapi_device_manager::instance()->current_output_device_index(),\r
+                    wasapi_device_manager::instance()->current_output_device().params);\r
+                  edit_output_config_ = true;\r
+                }\r
+              }\r
+\r
+              // 入力デバイス設定\r
+\r
+              if(edit_input_config_){\r
+                res = GetDlgItemInt(hwnd_,IDC_INPUT_LATENCY,&success,TRUE);\r
+                if(success)\r
+                {\r
+                  editing_input_params_.latency = res * 10000;\r
+                } else {\r
+                  message_box(L"レイテンシに不正な値が設定されています。",L"エラー",MB_OK);\r
+                }\r
+                try {\r
+                  application::instance()->apply_input_device_config\r
+                    (current_input_driver_index_,editing_input_params_);\r
+                  edit_input_config_ = false;\r
+                } catch (...) \r
+                {\r
+                  application::instance()->apply_input_device_config\r
+                    (wasapi_device_manager::instance()->current_input_device_index(),\r
+                    wasapi_device_manager::instance()->current_input_device().params);\r
+                  edit_input_config_ = true;\r
+                }\r
+              }\r
+              update_config_dialog();\r
+            }\r
+            return TRUE;\r
+            // ---------------------------------\r
+            // 設定キャンセル\r
+            // ---------------------------------\r
+          case IDC_CANCEL:\r
+            {\r
+              wasapi_device_manager::ptr m(sf::wasapi_device_manager::instance());\r
+\r
+              if(edit_output_config_){\r
+                editing_output_params_ = m->current_output_device().params;\r
+                edit_output_config_ = false;\r
+              }\r
+\r
+              if(edit_input_config_){\r
+                editing_input_params_ = m->current_input_device().params;\r
+                edit_input_config_ = false;\r
+              }\r
+\r
+              update_config_dialog();\r
+              return TRUE;\r
+            }\r
+          }\r
+          return FALSE;\r
+        }\r
+      case WM_CTLCOLORDLG:\r
+      case WM_CTLCOLORSTATIC:\r
+      case WM_CTLCOLORBTN:\r
+      case WM_CTLCOLOR:\r
+        SetBkMode((HDC)wParam,TRANSPARENT);\r
+        return  (LRESULT)GetStockObject( /* NULL_BRUSH */WHITE_BRUSH );\r
+      case WM_ERASEBKGND:\r
+        return FALSE;\r
+      }\r
+      return FALSE;  \r
+    };\r
+\r
+  void config_tab_dialog::init_config_dialog()\r
+  {\r
+\r
+    wasapi_device_manager::ptr m(sf::wasapi_device_manager::instance());\r
+\r
+    // バックアップ\r
+    {\r
+      // 出力\r
+      editing_output_params_ = m->current_output_device().params;\r
+      wasapi_device_manager::device_infos_t& i(m->output_device_infos());\r
+\r
+      for(int c = 0;c < i.size();++c)\r
+      {\r
+        if(i[c].is_selected){\r
+          current_output_driver_index_ = c;\r
+        }\r
+      }\r
+    }\r
+\r
+    {\r
+      // 入力\r
+      editing_input_params_ = m->current_input_device().params;\r
+      wasapi_device_manager::device_infos_t& i(m->input_device_infos());\r
+      for(int c = 0;c < i.size();++c)\r
+      {\r
+        if(i[c].is_selected){\r
+          current_input_driver_index_ = c;\r
+        }\r
+      }\r
+    }\r
+    edit_output_config_ = false;\r
+    edit_input_config_ = false;\r
+    update_config_dialog();\r
+    //i[current_index].support_formats\r
+\r
+  }\r
+\r
+ void config_tab_dialog::update_config_dialog()\r
+  {\r
+    update_config_dialog_ = true;\r
+    application::ptr app(application::instance());\r
+\r
+    // ----------------------------------------\r
+    enable_control(hwnd_,IDC_APPLY,edit_output_config_ || edit_input_config_);\r
+    enable_control(hwnd_,IDC_CANCEL,edit_output_config_ || edit_input_config_);\r
+\r
+\r
+    // デバイスコンボボックスのセットアップ\r
+    wasapi_device_manager::ptr m(sf::wasapi_device_manager::instance());\r
+\r
+    // ==========================================\r
+    // 出力設定\r
+    // ==========================================\r
+    { \r
+      wasapi_device_manager::device_infos_t& i(m->output_device_infos());\r
+\r
+      HWND hwnd_endp = GetDlgItem(hwnd_,IDC_ENDPOINT_DEVICE);\r
+      SendMessage(hwnd_endp,CB_RESETCONTENT,0,0);\r
+\r
+      for(int c = 0,e = i.size(); c < e;++c)\r
+      {\r
+        SendMessage(hwnd_endp,CB_ADDSTRING,0,(LPARAM)i[c].device_friendly_name.c_str());\r
+        SendMessage(hwnd_endp,CB_SETITEMDATA,c,c);\r
+        if(c == current_output_driver_index_)\r
+        {\r
+          SendMessage(hwnd_endp,CB_SETCURSEL,c,0);\r
+        }\r
+      }\r
+\r
+      typedef wasapi_device_manager::format_map_type fmts_t;\r
+      fmts_t& fmts = i[current_output_driver_index_].support_formats;\r
+      //// \r
+      HWND hwnd_smp_bits = GetDlgItem(hwnd_,IDC_SAMPLE_BIT);\r
+    \r
+      SendMessage(hwnd_smp_bits,CB_RESETCONTENT,0,0);\r
+      uint32_t share_mode = AUDCLNT_SHAREMODE_SHARED;\r
+      if(editing_output_params_.exclusive_mode)\r
+      {\r
+        share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
+        ::SendDlgItemMessage(hwnd_,IDC_EXC_MODE,BM_SETCHECK,BST_CHECKED ,0);\r
+      } else {\r
+        ::SendDlgItemMessage(hwnd_,IDC_EXC_MODE,BM_SETCHECK,BST_UNCHECKED ,0);\r
+      }\r
+\r
+      if(editing_output_params_.event_mode)\r
+      {\r
+        ::SendDlgItemMessage(hwnd_,IDC_EVENT_MODE,BM_SETCHECK,BST_CHECKED ,0);\r
+      } else {\r
+        ::SendDlgItemMessage(hwnd_,IDC_EVENT_MODE,BM_SETCHECK,BST_UNCHECKED ,0);\r
+      }\r
+\r
+      typedef fmts_t::mapped_type fsmpbits_t;\r
+      fsmpbits_t& fsmpbits = fmts[share_mode];\r
+      {\r
+        int c = 0;\r
+        std::for_each(fsmpbits.begin(),fsmpbits.end(),\r
+          [&](fsmpbits_t::value_type & pair)\r
+          {\r
+            SendMessage(hwnd_smp_bits,CB_ADDSTRING,0,(LPARAM)(boost::lexical_cast<std::wstring>(pair.first).c_str()));\r
+            SendMessage(hwnd_smp_bits,CB_SETITEMDATA,c,pair.first);\r
+            if(editing_output_params_.bits == pair.first)\r
+            {\r
+              SendMessage(hwnd_smp_bits,CB_SETCURSEL,c,0);\r
+            }\r
+            ++c;\r
+          }\r
+        );\r
+      }\r
+\r
+      // ----------------------------------------\r
+      // ----------------------------------------\r
+    \r
+      typedef wasapi_device_manager::format_map_type::mapped_type::mapped_type fmts_vbits_t;\r
+\r
+      fmts_vbits_t& fmts_vbits = fmts[share_mode][editing_output_params_.bits];\r
+      int cnt_vbits = 0;\r
+      HWND hwnd_valid_bits = GetDlgItem(hwnd_,IDC_VALID_SAMPLE_BITS);\r
+      SendMessage(hwnd_valid_bits,CB_RESETCONTENT,0,0);\r
+      std::for_each(fmts_vbits.begin(),fmts_vbits.end(),\r
+        [&](fmts_vbits_t::value_type& pair_vbits)\r
+      {\r
+        SendMessage(hwnd_valid_bits,CB_ADDSTRING,0,(LPARAM)(boost::lexical_cast<std::wstring>(pair_vbits.first).c_str()));\r
+        SendMessage(hwnd_valid_bits,CB_SETITEMDATA,cnt_vbits,pair_vbits.first);\r
+        if(pair_vbits.first == editing_output_params_.valid_bits)\r
+        {\r
+          SendMessage(hwnd_valid_bits,CB_SETCURSEL,cnt_vbits,0);\r
+        }\r
+        cnt_vbits++;\r
+      }\r
+      );\r
+\r
+      // ----------------------------------------\r
+      // ----------------------------------------\r
+      typedef wasapi_device_manager::format_map_type::mapped_type::mapped_type::mapped_type fmts_channels_t;\r
+      fmts_channels_t & \r
+        fmts_channels = fmts[share_mode][editing_output_params_.bits][editing_output_params_.valid_bits];\r
+      //typedef decltype(fmts_channels) fmts_channels_t;\r
+      int cnt_channels = 0;\r
+      HWND hwnd_channels = GetDlgItem(hwnd_,IDC_CHANNEL);\r
+      SendMessage(hwnd_channels,CB_RESETCONTENT,0,0);\r
+      std::for_each(fmts_channels.begin(),fmts_channels.end(),\r
+        [&](fmts_channels_t::value_type & pair_channel)\r
+      {\r
+        SendMessage(hwnd_channels,CB_ADDSTRING,0,(LPARAM)(boost::lexical_cast<std::wstring>(pair_channel.first).c_str()));\r
+        SendMessage(hwnd_channels,CB_SETITEMDATA,cnt_channels,pair_channel.first);\r
+        if(pair_channel.first == editing_output_params_.channel)\r
+        {\r
+          SendMessage(hwnd_channels,CB_SETCURSEL,cnt_channels,0);\r
+        }\r
+        cnt_channels++;\r
+      }\r
+      );\r
+\r
+      // ----------------------------------------\r
+      // ----------------------------------------\r
+\r
+      typedef wasapi_device_manager::format_map_type::mapped_type::mapped_type::mapped_type::mapped_type fmts_sample_rates_t;\r
+      fmts_sample_rates_t& fmts_sample_rates \r
+        = fmts[share_mode][editing_output_params_.bits][editing_output_params_.valid_bits][editing_output_params_.channel];\r
+      int cnt_samples = 0;\r
+      HWND hwnd_sample = GetDlgItem(hwnd_,IDC_SAMPLE_RATE);\r
+      SendMessage(hwnd_sample,CB_RESETCONTENT,0,0);\r
+      std::for_each(fmts_sample_rates.begin(),fmts_sample_rates.end(),\r
+        [&](fmts_sample_rates_t::value_type & pair_sample)\r
+      {\r
+        SendMessage(hwnd_sample,CB_ADDSTRING,0,(LPARAM)(boost::lexical_cast<std::wstring>(pair_sample.first).c_str()));\r
+        SendMessage(hwnd_sample,CB_SETITEMDATA,cnt_samples,pair_sample.first);\r
+        if(pair_sample.first == editing_output_params_.sample_rate)\r
+        {\r
+          SendMessage(hwnd_sample,CB_SETCURSEL,cnt_samples,0);\r
+        }\r
+        cnt_samples++;\r
+      }\r
+      );\r
+\r
+\r
+      // ----------------------------------------\r
+      // ----------------------------------------\r
+      SetDlgItemInt(hwnd_,IDC_LATENCY,editing_output_params_.latency/10000,TRUE);\r
+      SetDlgItemText(hwnd_,IDC_MIN_MAX_LATENCY,(boost::wformat(L"(%dms ~ %dms)") \r
+        % (i[current_output_driver_index_].latency_minimum / 10000) \r
+        % (i[current_output_driver_index_].latency_default / 10000)).str().c_str());\r
+    } // 出力ダイアログ\r
+\r
+    // ===================================================================\r
+    // 入力設定\r
+    // ===================================================================\r
+    { \r
+      wasapi_device_manager::device_infos_t& i(m->input_device_infos());\r
+\r
+      HWND hwnd_endp = GetDlgItem(hwnd_,IDC_INPUT_ENDPOINT_DEVICE);\r
+      SendMessage(hwnd_endp,CB_RESETCONTENT,0,0);\r
+\r
+      for(int c = 0,e = i.size(); c < e;++c)\r
+      {\r
+        SendMessage(hwnd_endp,CB_ADDSTRING,0,(LPARAM)i[c].device_friendly_name.c_str());\r
+        SendMessage(hwnd_endp,CB_SETITEMDATA,c,c);\r
+        if(c == current_input_driver_index_)\r
+        {\r
+          SendMessage(hwnd_endp,CB_SETCURSEL,c,0);\r
+        }\r
+      }\r
+\r
+      typedef wasapi_device_manager::format_map_type fmts_t;\r
+      fmts_t& fmts = i[current_input_driver_index_].support_formats;\r
+      //// \r
+      HWND hwnd_smp_bits = GetDlgItem(hwnd_,IDC_INPUT_SAMPLE_BIT);\r
+    \r
+      SendMessage(hwnd_smp_bits,CB_RESETCONTENT,0,0);\r
+      uint32_t share_mode = AUDCLNT_SHAREMODE_SHARED;\r
+      if(editing_input_params_.exclusive_mode)\r
+      {\r
+        share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
+        ::SendDlgItemMessage(hwnd_,IDC_INPUT_EXC_MODE,BM_SETCHECK,BST_CHECKED ,0);\r
+      } else {\r
+        ::SendDlgItemMessage(hwnd_,IDC_INPUT_EXC_MODE,BM_SETCHECK,BST_UNCHECKED ,0);\r
+      }\r
+\r
+      if(editing_input_params_.event_mode)\r
+      {\r
+        ::SendDlgItemMessage(hwnd_,IDC_INPUT_EVENT_MODE,BM_SETCHECK,BST_CHECKED ,0);\r
+      } else {\r
+        ::SendDlgItemMessage(hwnd_,IDC_INPUT_EVENT_MODE,BM_SETCHECK,BST_UNCHECKED ,0);\r
+      }\r
+\r
+      typedef fmts_t::mapped_type fsmpbits_t;\r
+      fsmpbits_t& fsmpbits = fmts[share_mode];\r
+      {\r
+        int c = 0;\r
+        std::for_each(fsmpbits.begin(),fsmpbits.end(),\r
+          [&](fsmpbits_t::value_type & pair)\r
+          {\r
+            SendMessage(hwnd_smp_bits,CB_ADDSTRING,0,(LPARAM)(boost::lexical_cast<std::wstring>(pair.first).c_str()));\r
+            SendMessage(hwnd_smp_bits,CB_SETITEMDATA,c,pair.first);\r
+            if(editing_input_params_.bits == pair.first)\r
+            {\r
+              SendMessage(hwnd_smp_bits,CB_SETCURSEL,c,0);\r
+            }\r
+            ++c;\r
+          }\r
+        );\r
+      }\r
+\r
+      // ----------------------------------------\r
+      // ----------------------------------------\r
+    \r
+      typedef wasapi_device_manager::format_map_type::mapped_type::mapped_type fmts_vbits_t;\r
+\r
+      fmts_vbits_t& fmts_vbits = fmts[share_mode][editing_input_params_.bits];\r
+      int cnt_vbits = 0;\r
+      HWND hwnd_valid_bits = GetDlgItem(hwnd_,IDC_INPUT_VALID_SAMPLE_BITS);\r
+      SendMessage(hwnd_valid_bits,CB_RESETCONTENT,0,0);\r
+      std::for_each(fmts_vbits.begin(),fmts_vbits.end(),\r
+        [&](fmts_vbits_t::value_type& pair_vbits)\r
+      {\r
+        SendMessage(hwnd_valid_bits,CB_ADDSTRING,0,(LPARAM)(boost::lexical_cast<std::wstring>(pair_vbits.first).c_str()));\r
+        SendMessage(hwnd_valid_bits,CB_SETITEMDATA,cnt_vbits,pair_vbits.first);\r
+        if(pair_vbits.first == editing_input_params_.valid_bits)\r
+        {\r
+          SendMessage(hwnd_valid_bits,CB_SETCURSEL,cnt_vbits,0);\r
+        }\r
+        cnt_vbits++;\r
+      }\r
+      );\r
+\r
+      // ----------------------------------------\r
+      // ----------------------------------------\r
+      typedef wasapi_device_manager::format_map_type::mapped_type::mapped_type::mapped_type fmts_channels_t;\r
+      fmts_channels_t & \r
+        fmts_channels = fmts[share_mode][editing_input_params_.bits][editing_input_params_.valid_bits];\r
+      //typedef decltype(fmts_channels) fmts_channels_t;\r
+      int cnt_channels = 0;\r
+      HWND hwnd_channels = GetDlgItem(hwnd_,IDC_INPUT_CHANNEL);\r
+      SendMessage(hwnd_channels,CB_RESETCONTENT,0,0);\r
+      std::for_each(fmts_channels.begin(),fmts_channels.end(),\r
+        [&](fmts_channels_t::value_type & pair_channel)\r
+      {\r
+        SendMessage(hwnd_channels,CB_ADDSTRING,0,(LPARAM)(boost::lexical_cast<std::wstring>(pair_channel.first).c_str()));\r
+        SendMessage(hwnd_channels,CB_SETITEMDATA,cnt_channels,pair_channel.first);\r
+        if(pair_channel.first == editing_input_params_.channel)\r
+        {\r
+          SendMessage(hwnd_channels,CB_SETCURSEL,cnt_channels,0);\r
+        }\r
+        cnt_channels++;\r
+      }\r
+      );\r
+\r
+      // ----------------------------------------\r
+      // ----------------------------------------\r
+\r
+      typedef wasapi_device_manager::format_map_type::mapped_type::mapped_type::mapped_type::mapped_type fmts_sample_rates_t;\r
+      fmts_sample_rates_t& fmts_sample_rates \r
+        = fmts[share_mode][editing_input_params_.bits][editing_input_params_.valid_bits][editing_input_params_.channel];\r
+      int cnt_samples = 0;\r
+      HWND hwnd_sample = GetDlgItem(hwnd_,IDC_INPUT_SAMPLE_RATE);\r
+      SendMessage(hwnd_sample,CB_RESETCONTENT,0,0);\r
+      std::for_each(fmts_sample_rates.begin(),fmts_sample_rates.end(),\r
+        [&](fmts_sample_rates_t::value_type & pair_sample)\r
+      {\r
+        SendMessage(hwnd_sample,CB_ADDSTRING,0,(LPARAM)(boost::lexical_cast<std::wstring>(pair_sample.first).c_str()));\r
+        SendMessage(hwnd_sample,CB_SETITEMDATA,cnt_samples,pair_sample.first);\r
+        if(pair_sample.first == editing_input_params_.sample_rate)\r
+        {\r
+          SendMessage(hwnd_sample,CB_SETCURSEL,cnt_samples,0);\r
+        }\r
+        cnt_samples++;\r
+      }\r
+      );\r
+\r
+\r
+      // ----------------------------------------\r
+      // ----------------------------------------\r
+      SetDlgItemInt(hwnd_,IDC_INPUT_LATENCY,editing_input_params_.latency/10000,TRUE);\r
+      SetDlgItemText(hwnd_,IDC_INPUT_MIN_MAX_LATENCY,(boost::wformat(L"(%dms ~ %dms)") \r
+        % (i[current_input_driver_index_].latency_minimum / 10000) \r
+        % (i[current_input_driver_index_].latency_default / 10000)).str().c_str());\r
+    } // 入力ダイアログ\r
+\r
+    update_config_dialog_ = false;\r
+  }\r
+\r
+  void config_tab_dialog::enable_config_dialog(bool value)\r
+  {\r
+    // 出力部分\r
+    enable_control(hwnd_,IDC_EXC_MODE,value);\r
+    enable_control(hwnd_,IDC_EVENT_MODE,value);\r
+    enable_control(hwnd_,IDC_ENDPOINT_DEVICE,value);\r
+    enable_control(hwnd_,IDC_SAMPLE_BIT,value);\r
+    enable_control(hwnd_,IDC_VALID_SAMPLE_BITS,value);\r
+    enable_control(hwnd_,IDC_SAMPLE_RATE,value);\r
+    enable_control(hwnd_,IDC_LATENCY,value);\r
+    enable_control(hwnd_,IDC_CHANNEL,value);\r
+    // 入力部分\r
+    enable_control(hwnd_,IDC_INPUT_EXC_MODE,value);\r
+    enable_control(hwnd_,IDC_INPUT_EVENT_MODE,value);\r
+    enable_control(hwnd_,IDC_INPUT_ENDPOINT_DEVICE,value);\r
+    enable_control(hwnd_,IDC_INPUT_SAMPLE_BIT,value);\r
+    enable_control(hwnd_,IDC_INPUT_VALID_SAMPLE_BITS,value);\r
+    enable_control(hwnd_,IDC_INPUT_SAMPLE_RATE,value);\r
+    enable_control(hwnd_,IDC_INPUT_LATENCY,value);\r
+    enable_control(hwnd_,IDC_INPUT_CHANNEL,value);\r
+    // 設定反映・キャンセル部分\r
+    if(value){\r
+      enable_control(hwnd_,IDC_APPLY,edit_output_config_ || edit_input_config_);\r
+      enable_control(hwnd_,IDC_CANCEL,edit_output_config_ || edit_input_config_);\r
+    } else {\r
+      enable_control(hwnd_,IDC_APPLY,false);\r
+      enable_control(hwnd_,IDC_CANCEL,false);\r
+    }\r
+\r
+  }\r
+\r
+  void config_tab_dialog::enable()\r
+  {\r
+    enable_config_dialog(true);\r
+  }\r
+\r
+  void config_tab_dialog::disable()\r
+  {\r
+    enable_config_dialog(false);\r
+  }\r
+\r
+}\r
+\r
diff --git a/wasapi2/config_tab_dialog.h b/wasapi2/config_tab_dialog.h
new file mode 100644 (file)
index 0000000..8a6d45f
--- /dev/null
@@ -0,0 +1,44 @@
+#pragma once
+/*
+*/
+// Windows Header Files:
+#include "base_window.h"
+#include "sf_windows.h"
+#include "icon.h"
+#include "taskbar.h"
+#include "tab_dialog.h"
+
+namespace sf
+{
+
+  struct config_tab_dialog : public tab_dialog_base
+  {
+    config_tab_dialog(
+      sf::base_window& parent_window,
+      HWND tab_hwnd,
+      int tab_id,
+      const std::wstring& menu_name,
+      const std::wstring& name,
+      HINSTANCE inst,
+      LPCTSTR temp);
+    virtual ~config_tab_dialog(){};
+    virtual LRESULT window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam);
+    virtual void enable();
+    virtual void disable();
+  private:
+    void init_config_dialog();
+    void update_config_dialog();
+    void enable_config_dialog(bool value);
+
+    int current_output_driver_index_;
+    int current_input_driver_index_;
+    bool update_config_dialog_;
+    bool edit_output_config_;
+    bool edit_input_config_;
+
+    wasapi_device_manager::device_info::params_t editing_output_params_;
+    wasapi_device_manager::device_info::params_t editing_input_params_;
+
+  };
+}
\ No newline at end of file
diff --git a/wasapi2/directx.ico b/wasapi2/directx.ico
new file mode 100644 (file)
index 0000000..bc43c1b
Binary files /dev/null and b/wasapi2/directx.ico differ
diff --git a/wasapi2/dout.h b/wasapi2/dout.h
new file mode 100644 (file)
index 0000000..360a1a5
--- /dev/null
@@ -0,0 +1,148 @@
+#pragma once\r
+\r
+/* http://vision.kuee.kyoto-u.ac.jp/~nob/doc/win32/win32.html#doc1_42 \r
+       \82æ\82è\94q\8eØ\r
+*/\r
+\r
+\r
+#ifndef STDX_DSTREAM_H\r
+\r
+#define STDX_DSTREAM_H\r
+\r
+namespace sf\r
+{\r
+\r
+#ifdef _DEBUG\r
+  \r
+// VC++ \82Å STLport \82¾\82Æ using std::char_traits; \82Ý\82½\82¢\82È\82Ì\82ª\95K\97v\82©\82à\r
+template <typename Ch_T, typename Tr_T = std::char_traits<Ch_T> >\r
+class basic_dbg_streambuf: public std::basic_stringbuf<Ch_T, Tr_T>\r
+{\r
+public:\r
+  basic_dbg_streambuf()\r
+    {\r
+#ifndef STDX_DSTREAM_BUFFERING\r
+      setbuf(0,0);\r
+#endif\r
+    }\r
+\r
+  virtual ~basic_dbg_streambuf()\r
+    {\r
+      sync();\r
+    }\r
+\r
+protected:\r
+  int sync(void)\r
+    {\r
+      dbg_out(str().c_str());\r
+      pbump(static_cast<int>(pbase() - pptr()));\r
+      return 0;\r
+    }\r
+\r
+  void dbg_out(const Ch_T*);\r
+};\r
+\r
+template <>\r
+inline void basic_dbg_streambuf<char>::dbg_out(const char *str)\r
+{\r
+  ::OutputDebugStringA(str);\r
+}\r
+\r
+template <>\r
+inline void basic_dbg_streambuf<wchar_t>::dbg_out(const wchar_t *str)\r
+{\r
+  ::OutputDebugStringW(str);\r
+}\r
+\r
+template <typename Ch_T, typename Tr_T = std::char_traits<Ch_T> >\r
+class basic_dbg_ostream: public std::basic_ostream<Ch_T, Tr_T>\r
+{\r
+public:\r
+  basic_dbg_ostream() : std::basic_ostream<Ch_T, Tr_T>(new basic_dbg_streambuf<Ch_T, Tr_T>())\r
+    {\r
+    }\r
+\r
+  virtual ~basic_dbg_ostream()\r
+    {\r
+      // flush(); // \95s\97v\82ç\82µ\82¢\81Dhttp://www.tietew.jp/cppll/archive/607\r
+      delete rdbuf();\r
+    }\r
+};\r
+\r
+typedef basic_dbg_streambuf<wchar_t>  wdbg_streambuf;\r
+typedef basic_dbg_ostream<wchar_t> wdstream;\r
+\r
+// \82±\82ê\82ð\92è\8b`\82µ\82Ä\82¨\82­\82Æ\81C dout \82Ì\90é\8c¾\82ª\82¢\82ç\82È\82­\82È\82é\81D\r
+\r
+static wdstream wdout;\r
+#define DOUT(x) wdout << x \r
+}\r
+#else\r
+#define DOUT(x) \r
+#define wdout //\r
+//  struct dummy_wdout {\r
+//    //template <typename R>\r
+//    //inline dummy_wdout& operator<<(const R v) {return *this;};\r
+//\r
+//    //template <typename R>\r
+//    //inline dummy_wdout& operator<<(const R* v) {return *this;};\r
+//\r
+//    //template <typename R>\r
+//    //inline dummy_wdout& operator<<(const R& v) {return *this;};\r
+//\r
+//    //template <typename R>\r
+//    //inline dummy_wdout& operator<<(const R&& v) {return *this;};\r
+//\r
+//    ////template <typename R,int N>\r
+//    ////inline dummy_wdout& operator<<(const R(&a)[N]) {return *this;};\r
+//\r
+//  };\r
+//\r
+//  static dummy_wdout wdout;\r
+//}\r
+//\r
+//template <typename L>\r
+//inline sf::dummy_wdout& operator<<(sf::dummy_wdout& p,const L v) {return p;};\r
+//\r
+//template <typename L>\r
+//inline sf::dummy_wdout& operator<<(sf::dummy_wdout& p,const L& v) {return p;};\r
+//\r
+//template <typename L>\r
+//inline sf::dummy_wdout& operator<<(sf::dummy_wdout& p,const L&& v) {return p;};\r
+//\r
+////template <typename L>\r
+////inline sf::dummy_wdout& operator<<(sf::dummy_wdout& p,const L* v) {return p;};\r
+//\r
+//template <typename L,int N>\r
+//inline sf::dummy_wdout& operator<<(sf::dummy_wdout& p,const L(&a)[N]) {return p;};\r
+//\r
+//template <typename L>\r
+//inline L& operator<<(const L v,sf::dummy_wdout& p) {return v;};\r
+//\r
+//template <typename L>\r
+//inline L& operator<<(sf::dummy_wdout& p,L v) {return v;};\r
+//\r
+//\r
+//template <typename L>\r
+//inline sf::dummy_wdout& operator<<(const L v,sf::dummy_wdout& p) {return p;};\r
+//\r
+//template <typename L>\r
+//inline sf::dummy_wdout& operator<<(const L& v,sf::dummy_wdout& p) {return p;};\r
+//\r
+////template <typename L>\r
+////inline sf::dummy_wdout& operator<<(const L* v,sf::dummy_wdout& p) {return p;};\r
+//\r
+//template <typename L>\r
+//inline sf::dummy_wdout& operator<<(const L&& v,sf::dummy_wdout& p) {return p;};\r
+//\r
+//\r
+//template <typename L,int N>\r
+//inline sf::dummy_wdout& operator<<(const L(&a)[N],sf::dummy_wdout& p) {return p;};\r
+////\r
+//template <typename L>\r
+//inline sf::dummy_wdout& operator<<(sf::dummy_wdout& p , const L *v) {return p;};\r
+\r
+//\r
+}\r
+#endif\r
+#endif // STDX_DSTREAM_
\ No newline at end of file
diff --git a/wasapi2/dpi.cpp b/wasapi2/dpi.cpp
new file mode 100644 (file)
index 0000000..7a3f56c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-10 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+
+#include "StdAfx.h"
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+#include "sf_windows.h"
+#include "dpi.h"
+
+namespace sf {
+  void dpi::init()
+  {
+    if (!init_)
+    {
+      sf::get_dc hdc(0);
+      if (hdc.get())
+      {
+        dpi_x_ = GetDeviceCaps(hdc.get(), LOGPIXELSX);
+        dpi_y_ = GetDeviceCaps(hdc.get(), LOGPIXELSY);
+        ReleaseDC(NULL, hdc.get());
+      }
+      init_ = true;
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/wasapi2/dpi.h b/wasapi2/dpi.h
new file mode 100644 (file)
index 0000000..b37a814
--- /dev/null
@@ -0,0 +1,86 @@
+#pragma once\r
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace sf{\r
+  template <typename T>\r
+  class dpi_t\r
+  {\r
+  public:\r
+    dpi_t() : init_(false), dpi_x_(96), dpi_y_(96) { }\r
+    // \89æ\96Ê\82Ì DPI \82ð\8eæ\93¾\82µ\82Ü\82·\81B\r
+    T dpix() { init(); return dpi_x_; }\r
+    T dpiy() { init(); return dpi_y_; }\r
+\r
+    // \90â\91Î\83s\83N\83Z\83\8b\82Æ\91\8a\91Î\83s\83N\83Z\83\8b\8aÔ\82Ì\95Ï\8a·\82ð\8ds\82¢\82Ü\82·\81B\r
+    T scale_x(T x) { init(); return MulDiv(x, dpi_x_, 96); }\r
+    T scale_y(T y) { init(); return MulDiv(y, dpi_y_, 96); }\r
+    T unscale_x(T x) { init(); return MulDiv(x, 96, dpi_x_); }\r
+    T unscale_y(T y) { init(); return MulDiv(y, 96, dpi_y_); }\r
+\r
+    // \89æ\96Ê\83T\83C\83Y (\91\8a\91Î\83s\83N\83Z\83\8b\92P\88Ê) \82ð\8b\81\82ß\82Ü\82·\81B\r
+    T scaled_screen_width() { return scaled_system_metrix_x(SM_CXSCREEN); }\r
+    T scaled_screen_height() { return scaled_system_metrix_y(SM_CYSCREEN); }\r
+\r
+    // \8el\8ap\8c`\82Ì\83T\83C\83Y\82ð\90â\91Î\83s\83N\83Z\83\8b\82©\82ç\91\8a\91Î\83s\83N\83Z\83\8b\82É\95Ï\8dX\82µ\82Ü\82·\81B\r
+    void scale_rect(RECT *rect_ptr)\r
+    {\r
+      rect_ptr->left = scale_x(rect_ptr->left);\r
+      rect_ptr->right = scale_x(rect_ptr->right);\r
+      rect_ptr->top = scale_y(rect_ptr->top);\r
+      rect_ptr->bottom = scale_y(rect_ptr->bottom);\r
+    }\r
+\r
+    // \89æ\96Ê\89ð\91\9c\93x\82ª\8dÅ\92á\92l (\91\8a\91Î\83s\83N\83Z\83\8b\92P\88Ê) \82ð\96\9e\82½\82µ\82Ä\82¢\82é\82©\82Ç\82¤\82©\82ð\r
+    // \8am\94F\82µ\82Ü\82·\81B\r
+    bool is_resolution_at_least(T xmin, T ymin) \r
+    { \r
+      return (scaled_screen_width() >= xmin) && (scaled_screen_height() >= ymin); \r
+    }\r
+    // \83|\83C\83\93\83\83T\83C\83Y (1/72 \83C\83\93\83`) \82ð\90â\91Î\83s\83N\83Z\83\8b\82É\95Ï\8a·\82µ\82Ü\82·\81B\r
+    T point_to_pixels(int pt) { return MulDiv(pt, dpi_y_, 72); }\r
+    // \83L\83\83\83b\83V\83\85\82³\82ê\82½\83\81\83g\83\8a\83b\83N\82ð\82·\82×\82Ä\96³\8cø\82É\82µ\82Ü\82·\81B\r
+    void invalidate() { init_ = false; }\r
+  private:\r
+    void init();\r
+\r
+    T scaled_system_metrix_x(int nIndex) \r
+    { \r
+      init(); \r
+      return MulDiv(GetSystemMetrics(nIndex), 96, dpi_x_); \r
+    }\r
+\r
+    T scaled_system_metrix_y(int nIndex) \r
+    { \r
+      init(); \r
+      return MulDiv(GetSystemMetrics(nIndex), 96, dpi_y_); \r
+    }\r
+\r
+  private:\r
+    bool init_;\r
+    T dpi_x_;\r
+    T dpi_y_;\r
+  };\r
+\r
+  typedef dpi_t<int> dpi;\r
+}\r
diff --git a/wasapi2/exception.cpp b/wasapi2/exception.cpp
new file mode 100644 (file)
index 0000000..5425c47
--- /dev/null
@@ -0,0 +1,124 @@
+#include "stdafx.h"
+#include "exception.h"
+#include <objbase.h>
+#include <wtypes.h>
+#include <winerror.h>
+#include <avrt.h>
+#include <strsafe.h>
+#include <audioclient.h>
+#include <audiopolicy.h>
+
+
+
+#define BOOST_ASSIGN_MAX_PARAMS 7
+#include <boost/assign.hpp>
+#include <boost/assign/ptr_list_of.hpp>
+#include <boost/assign/ptr_list_inserter.hpp>
+#include <boost/foreach.hpp>
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "sf_memory.h"
+
+using namespace boost;
+
+namespace sf
+{
+//typedef CComPtr<IAudioClient> IAudioClientPtr;
+std::map<HRESULT,std::wstring> com_error_  = boost::assign::list_of<std::pair<HRESULT,std::wstring> >
+    (E_POINTER,L"E_POINTER")
+    (E_INVALIDARG,L"E_INVALIDARG")
+    (DWRITE_E_FILEFORMAT,L"DWRITE_E_FILEFORMAT")
+    (DWRITE_E_UNEXPECTED,L"DWRITE_E_UNEXPECTED")
+    (DWRITE_E_NOFONT,L"DWRITE_E_NOFONT")
+    (DWRITE_E_FILENOTFOUND,L"DWRITE_E_FILENOTFOUND")
+    (DWRITE_E_FILEACCESS,L"DWRITE_E_FILEACCESS")
+    (DWRITE_E_FONTCOLLECTIONOBSOLETE,L"DWRITE_E_FONTCOLLECTIONOBSOLETE")
+    (DWRITE_E_ALREADYREGISTERED,L"DWRITE_E_ALREADYREGISTERED")
+       (AUDCLNT_E_NOT_INITIALIZED,L"AUDCLNT_E_NOT_INITIALIZED")
+       (AUDCLNT_E_ALREADY_INITIALIZED,L"AUDCLNT_E_ALREADY_INITIALIZED")
+    (AUDCLNT_E_WRONG_ENDPOINT_TYPE,L"AUDCLNT_E_WRONG_ENDPOINT_TYPE")
+       (AUDCLNT_E_DEVICE_INVALIDATED,L"AUDCLNT_E_DEVICE_INVALIDATED")
+       (AUDCLNT_E_NOT_STOPPED,L"AUDCLNT_E_NOT_STOPPED")
+       (AUDCLNT_E_BUFFER_TOO_LARGE,L"AUDCLNT_E_BUFFER_TOO_LARGE")
+       (AUDCLNT_E_OUT_OF_ORDER,L"AUDCLNT_E_OUT_OF_ORDER")
+       (AUDCLNT_E_UNSUPPORTED_FORMAT,L"AUDCLNT_E_UNSUPPORTED_FORMAT")
+       (AUDCLNT_E_INVALID_SIZE,L"AUDCLNT_E_INVALID_SIZE")
+       (AUDCLNT_E_DEVICE_IN_USE,L"AUDCLNT_E_DEVICE_IN_USE")
+       (AUDCLNT_E_BUFFER_OPERATION_PENDING,L"AUDCLNT_E_BUFFER_OPERATION_PENDING")
+       (AUDCLNT_E_THREAD_NOT_REGISTERED,L"AUDCLNT_E_THREAD_NOT_REGISTERED")
+       (AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED,L"AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED")
+       (AUDCLNT_E_ENDPOINT_CREATE_FAILED,L"AUDCLNT_E_ENDPOINT_CREATE_FAILED")
+       (AUDCLNT_E_SERVICE_NOT_RUNNING,L"AUDCLNT_E_SERVICE_NOT_RUNNING")
+       (AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED,L"AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED")
+       (AUDCLNT_E_EXCLUSIVE_MODE_ONLY,L"AUDCLNT_E_EXCLUSIVE_MODE_ONLY")
+       (AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL,L"AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL")
+       (AUDCLNT_E_EVENTHANDLE_NOT_SET,L"AUDCLNT_E_EVENTHANDLE_NOT_SET")
+       (AUDCLNT_E_INCORRECT_BUFFER_SIZE,L"AUDCLNT_E_INCORRECT_BUFFER_SIZE")
+  (AUDCLNT_E_CPUUSAGE_EXCEEDED,L"AUDCLNT_E_CPUUSAGE_EXCEEDED")
+  (AUDCLNT_E_BUFFER_ERROR,L"AUDCLNT_E_BUFFER_ERROR")
+  (AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED,L"AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED")
+  (AUDCLNT_E_BUFFER_SIZE_ERROR,L"AUDCLNT_E_BUFFER_SIZE_ERROR")
+  (AUDCLNT_E_INVALID_DEVICE_PERIOD,L"AUDCLNT_E_INVALID_DEVICE_PERIOD")
+       (AUDCLNT_S_BUFFER_EMPTY,L"AUDCLNT_S_BUFFER_EMPTY")
+       (AUDCLNT_S_THREAD_ALREADY_REGISTERED,L"AUDCLNT_S_THREAD_ALREADY_REGISTERED")
+  (AUDCLNT_S_POSITION_STALLED,L"AUDCLNT_S_POSITION_STALLED")
+  (DXGI_ERROR_UNSUPPORTED,L"DXGI_ERROR_UNSUPPORTED ")
+  (DXGI_STATUS_OCCLUDED,L"DXGI_STATUS_OCCLUDED")
+  (DXGI_STATUS_CLIPPED,L"DXGI_STATUS_CLIPPED")
+  ;
+       
+
+win32_error_exception::win32_error_exception(uint32_t hr)
+: std::exception("HRESULT ERROR"),hresult_(hr)
+{
+       local_memory<wchar_t> mem;
+       DWORD 結果 = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,hr,0,(LPWSTR)&mem,0,0);
+       if(結果 != 0){
+               error_ = mem.get();
+       } else {
+               std::map<HRESULT,std::wstring>::iterator it = com_error_.find(hr);
+               if(it != com_error_.end())
+               {
+                       error_ = it->second;
+               } else {
+                       error_ = (boost::wformat(L"0x%x 不明なCOMエラー") % hr).str();
+               }
+#ifdef _DEBUG
+  wdout << L"#### Exception Occured ####" << error_ << std::endl; 
+#endif
+       }
+
+};
+
+win32_error_exception::win32_error_exception()
+{
+       hresult_ = ::GetLastError();
+       local_memory<wchar_t> mem;
+       DWORD rv =  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,hresult_,0,(LPWSTR)&mem,0,0);
+       error_ = mem.get();
+#ifdef _DEBUG
+  wdout << L"#### Exception Occured ####" << error_ << std::endl; 
+#endif
+
+  //Logger::outputDebugPrintf(L"Win32 Error %x %s",hresult_,mem.Get() );
+};
+
+std::wstring win32_error_exception::get_last_error_str(uint32_t err)
+{
+//     DWORD err = ::GetLastError();
+  std::wstring err_str;
+       local_memory<wchar_t> mem;
+       DWORD rv =  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,err,0,(LPWSTR)&mem,0,0);
+       err_str = mem.get();
+#ifdef _DEBUG
+  wdout << L"#### Exception Occured ####" << err_str << std::endl; 
+#endif
+  return err_str;
+}
+
+}
\ No newline at end of file
diff --git a/wasapi2/exception.h b/wasapi2/exception.h
new file mode 100644 (file)
index 0000000..ccf0616
--- /dev/null
@@ -0,0 +1,42 @@
+#pragma once
+
+namespace sf
+{
+///Exception
+       class exception : public std::exception
+       {
+       public:
+               explicit exception(const std::wstring& reason)
+               {
+                       m_reason = reason;
+               };
+               const wchar_t * what() {return m_reason.c_str();};
+               const std::wstring& what_str() { return m_reason;};
+       protected:
+               std::wstring m_reason;
+       };
+
+       class win32_error_exception : std::exception 
+       {
+       public:
+               win32_error_exception(uint32_t hr);
+               win32_error_exception();
+
+               virtual ~win32_error_exception() {};
+               uint32_t hresult() {return hresult_;}
+               std::wstring& error() {return error_;}
+    static std::wstring get_last_error_str(uint32_t err = ::GetLastError());
+  private:
+               uint32_t hresult_;
+               std::wstring error_;
+       };
+
+  template <class Exc = win32_error_exception> struct throw_if_err
+  {
+    inline void operator()(HRESULT hr) {if(hr != S_OK){throw Exc(hr);}}
+    inline void operator()(bool v) {if(!v){throw Exc();}}
+  };
+
+}
+
+#define THROW_IF_ERR(x) sf::throw_if_err<>()(x)
diff --git a/wasapi2/icon.cpp b/wasapi2/icon.cpp
new file mode 100644 (file)
index 0000000..084508c
--- /dev/null
@@ -0,0 +1,264 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+#include "StdAfx.h"\r
+\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+\r
+#include "sf_windows.h"\r
+#include "icon.h"\r
+#include "application.h"\r
+\r
+namespace sf {\r
+  bitmap_holder icon::default_mono_bitmap(CreateBitmap(32,32,1,1,NULL));\r
+\r
+  icon::icon(uint32_t id) \r
+    : icon_((HICON)::LoadImageW(application::instance()->instance_handle(),MAKEINTRESOURCE(id),IMAGE_ICON,0,0,LR_DEFAULTCOLOR))\r
+  {\r
+\r
+  };\r
+\r
+  icon::icon(icon_holder& ic)\r
+  {\r
+    icon_.reset(::CopyIcon(ic.get()));\r
+    analyze();\r
+  }\r
+\r
+  icon::icon(icon_holder&& ic)\r
+  {\r
+    std::swap(ic,icon_);\r
+    analyze();\r
+  }\r
+\r
+  icon::icon(bitmap_holder& bmp_color,int width,int height) \r
+    : width_(width),height_(height)\r
+  {\r
+    BITMAP bmp;\r
+    ICONINFO ii;\r
+    ::GetObjectW(bmp_color.get(),sizeof(BITMAP),&bmp);\r
+    bits_per_pixel_ = bmp.bmBitsPixel;\r
+\r
+    ii.fIcon = TRUE;\r
+    ii.xHotspot = 0;\r
+    ii.yHotspot = 0;\r
+    ii.hbmColor = bmp_color.get();\r
+\r
+    if(width == 32 && height == 32){\r
+      ii.hbmMask = default_mono_bitmap.get();\r
+      icon_.reset(::CreateIconIndirect(&ii));\r
+    } else {\r
+      bitmap_holder hmb(::CreateBitmap(width,height,1,1,NULL));\r
+      ii.hbmMask = hmb.get();\r
+      icon_.reset(::CreateIconIndirect(&ii));\r
+    }\r
+\r
+  }\r
+\r
+  icon::icon(ID2D1BitmapPtr& ptr)\r
+  {\r
+    ID2D1FactoryPtr factory;\r
+    ptr->GetFactory(&factory);\r
+\r
+    D2D1_SIZE_U size(ptr->GetPixelSize());\r
+    // ビットマップヘッダのセットアップ\r
+    BITMAPV5HEADER bi = {0};\r
+    bi.bV5Size           = sizeof(BITMAPV5HEADER);\r
+    bi.bV5Width           = size.width;\r
+    bi.bV5Height          = size.height;\r
+    bi.bV5Planes = 1;\r
+    bi.bV5BitCount = 32;\r
+    bi.bV5Compression = BI_BITFIELDS;\r
+    bi.bV5RedMask   =  0x00FF0000;\r
+    bi.bV5GreenMask =  0x0000FF00;\r
+    bi.bV5BlueMask  =  0x000000FF;\r
+    bi.bV5AlphaMask =  0xFF000000; \r
+\r
+    // デスクトップHDCの取得\r
+    get_dc dc(NULL);\r
+    \r
+    // DIBセクションの作成\r
+    void *bits;// 得られるビットマップ\r
+    bitmap_holder bmp(\r
+      ::CreateDIBSection(\r
+        dc.get(),reinterpret_cast<BITMAPINFO *>(&bi),DIB_RGB_COLORS,&bits,NULL,0));\r
+    { \r
+      // 互換DCの作成\r
+      compatible_dc cdc(dc.get());\r
+      {\r
+        // 描画先への切り替え\r
+        select_object s(cdc.get(),bmp.get());\r
+\r
+        // DC互換レンダーターゲットのセットアップ\r
+        D2D1_RENDER_TARGET_PROPERTIES \r
+          props = D2D1::RenderTargetProperties(\r
+          D2D1_RENDER_TARGET_TYPE_DEFAULT,\r
+          D2D1::PixelFormat(\r
+              DXGI_FORMAT_B8G8R8A8_UNORM,\r
+              D2D1_ALPHA_MODE_PREMULTIPLIED),\r
+          0,\r
+          0,\r
+          D2D1_RENDER_TARGET_USAGE_NONE,\r
+          D2D1_FEATURE_LEVEL_DEFAULT\r
+        );\r
+\r
+        ID2D1DCRenderTargetPtr dcr;\r
+        throw_if_err<>()(factory->CreateDCRenderTarget(&props,&dcr));\r
+        RECT rect = {0,0,size.width,size.height};\r
+        // 互換DCへのバインド\r
+        throw_if_err<>()(dcr->BindDC(cdc.get(),&rect));\r
+        dcr->DrawBitmap(ptr);\r
+      }\r
+    }\r
+    icon(bmp,size.width,size.height);\r
+  };\r
+\r
+\r
+  icon::icon(boost::filesystem::wpath& path)\r
+  {\r
+    icon_.reset(\r
+      reinterpret_cast<HICON>(\r
+        LoadImageW(NULL,path.native().c_str(),IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_LOADFROMFILE)));\r
+  }\r
+\r
+  icon::~icon()\r
+  {\r
+\r
+  }\r
+\r
+  void icon::analyze()\r
+  {\r
+    ::ICONINFOEXW info;\r
+    ::GetIconInfoExW(icon_.get(),&info);\r
+    BITMAP bmp;\r
+    ::GetObjectW(info.hbmColor,sizeof(BITMAP),&bmp);\r
+    width_ = bmp.bmWidth;\r
+    height_ = bmp.bmHeight;\r
+    bits_per_pixel_ = bmp.bmBitsPixel;\r
+  }\r
+\r
+  icon& icon::operator= (icon& i)\r
+  {\r
+    BOOST_ASSERT(icon_ != i.icon_);\r
+    if(icon_ == i.icon_) return *this;\r
+    icon_.reset(::CopyIcon(i.icon_.get()));\r
+    width_ = i.width_;\r
+    height_ = i.height_;\r
+    bits_per_pixel_ = i.bits_per_pixel_;\r
+    return *this;\r
+  }\r
+\r
+  //icon_ptr icon::create_icon()\r
+  //{\r
\r
+  //  // ビットマップヘッダのセットアップ\r
+  //  BITMAPV5HEADER bi = {0};\r
+  //  bi.bV5Size           = sizeof(BITMAPV5HEADER);\r
+  //  bi.bV5Width           = width_;\r
+  //  bi.bV5Height          = height_;\r
+  //  bi.bV5Planes = 1;\r
+  //  bi.bV5BitCount = 32;\r
+  //  bi.bV5Compression = BI_BITFIELDS;\r
+  //  bi.bV5RedMask   =  0x00FF0000;\r
+  //  bi.bV5GreenMask =  0x0000FF00;\r
+  //  bi.bV5BlueMask  =  0x000000FF;\r
+  //  bi.bV5AlphaMask =  0xFF000000; \r
+\r
+  //  // デスクトップHDCの取得\r
+  //  get_dc dc(NULL);\r
+\r
+  //  // DIBセクションの作成\r
+  //  void *bits;// 得られるビットマップ\r
+  //  gdi_object<HBITMAP> bmp(\r
+  //    ::CreateDIBSection(\r
+  //      dc.get(),reinterpret_cast<BITMAPINFO *>(&bi),DIB_RGB_COLORS,&bits,NULL,0));\r
+  //  { \r
+  //    // 互換DCの作成\r
+  //    compatible_dc cdc(dc.get());\r
+  //    {\r
+  //      // 描画先への切り替え\r
+  //      select_object s(cdc.get(),bmp);\r
+\r
+  //      // DC互換レンダーターゲットのセットアップ\r
+  //      D2D1_RENDER_TARGET_PROPERTIES \r
+  //        props = D2D1::RenderTargetProperties(\r
+  //        D2D1_RENDER_TARGET_TYPE_DEFAULT,\r
+  //        D2D1::PixelFormat(\r
+  //            DXGI_FORMAT_B8G8R8A8_UNORM,\r
+  //            D2D1_ALPHA_MODE_PREMULTIPLIED),\r
+  //        0,\r
+  //        0,\r
+  //        D2D1_RENDER_TARGET_USAGE_NONE,\r
+  //        D2D1_FEATURE_LEVEL_DEFAULT\r
+  //      );\r
+\r
+  //      ID2D1DCRenderTargetPtr dcr;\r
+  //      throw_if_err<>()(factory_->CreateDCRenderTarget(&props,&dcr));\r
+  //      RECT rect = {0,0,w,h};\r
+  //      // 互換DCへのバインド\r
+  //      throw_if_err<>()(dcr->BindDC(cdc.get(),&rect));\r
+\r
+  //      // ブラシのセットアップ(背景の赤丸)\r
+  //      ID2D1SolidColorBrushPtr brush_e;\r
+  //      throw_if_err<>()(\r
+  //        dcr->CreateSolidColorBrush(\r
+  //          D2D1::ColorF(D2D1::ColorF::Red,0.8f), &brush_e));\r
+\r
+  //      // アイコンに描画する文字の生成\r
+  //      std::wstring t(L"S.F.\nTimer");\r
+  //      D2D1_RECT_F l = D2D1::RectF(0.0f,0.0f,width_,height_);\r
+  //      // Text Formatの作成\r
+  //      IDWriteTextFormatPtr f;\r
+  //      write_factory_->CreateTextFormat(\r
+  //      L"メイリオ",                // Font family name.\r
+  //      NULL,                       // Font collection (NULL sets it to use the system font collection).\r
+  //      DWRITE_FONT_WEIGHT_REGULAR,\r
+  //      DWRITE_FONT_STYLE_NORMAL,\r
+  //      DWRITE_FONT_STRETCH_NORMAL,\r
+  //      10.0f,\r
+  //      L"ja-jp",\r
+  //      &f\r
+  //      );\r
+  //      f->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);\r
+  //      f->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);\r
+\r
+  //      // 文字描画用ブラシのセットアップ\r
+  //      ID2D1SolidColorBrushPtr brush;\r
+  //      dcr->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &brush);\r
+  //      // 描画開始\r
+  //      dcr->BeginDraw();\r
+  //      // ビットマップクリア\r
+  //      dcr->Clear(D2D1::ColorF(D2D1::ColorF::Black,0.0f));\r
+  //      // 赤丸を描く\r
+  //      dcr->FillEllipse(D2D1::Ellipse(D2D1::Point2F(16.0f,16.0f),14,14),brush_e);\r
+  //      // テキストを表示する\r
+  //      dcr->DrawTextW(t.c_str(),t.size(),f,&l,brush);\r
+  //      // 描画終了\r
+  //      dcr->EndDraw();\r
+  //    }\r
+  //  }\r
+  //}\r
+}\r
diff --git a/wasapi2/icon.h b/wasapi2/icon.h
new file mode 100644 (file)
index 0000000..6addf7e
--- /dev/null
@@ -0,0 +1,100 @@
+#pragma once\r
+/*\r
+==============================================================================\r
+\r
+This file is part of the async\r
+Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+\r
+namespace sf {\r
+\r
+  struct icon_deleter {\r
+    typedef HICON pointer;\r
+    void operator ()(HICON handle) {\r
+      if (handle) {\r
+        ::DestroyIcon(handle);\r
+      }\r
+    }\r
+  };\r
+\r
+  /** icon\83n\83\93\83h\83\8b\82Ì\89ð\95ú\82µ\96Y\82ê\82ð\97\\96h\82·\82é */\r
+  typedef std::unique_ptr<HICON,icon_deleter> icon_holder;\r
+\r
+  /** \r
+  \81@icon\8aÇ\97\9d\83N\83\89\83X\r
+  */\r
+  struct icon\r
+  {\r
+  public:\r
+    icon(){};\r
+    explicit icon(uint32_t id);/// \83\8a\83\\81[\83XID\82©\82ç\83A\83C\83R\83\93\82ð\8dì\90¬\82·\82é\r
+    explicit icon(icon_holder& ic);/// \83A\83C\83R\83\93\83t\83H\83\8b\83_\82©\82ç\83A\83C\83R\83\93\82ð\8dì\90¬\82·\82é\r
+    explicit icon(icon_holder&& ic);/// \89E\95Ó\92l\8eQ\8fÆ\82©\82ç\83A\83C\83R\83\93\82ð\8dì\90¬\82·\82é\r
+    icon(bitmap_holder& bmp_color,int width = ::GetSystemMetrics(SM_CXICON),int height = ::GetSystemMetrics(SM_CYICON));\r
+    icon(ID2D1BitmapPtr& ptr);\r
+    icon(boost::filesystem::wpath& path);\r
+\r
+    virtual ~icon();\r
+\r
+    HICON get() const {return icon_.get();};\r
+\r
+    icon(icon& i) : width_(i.width_),height_(i.height_),bits_per_pixel_(i.bits_per_pixel_)\r
+    {\r
+      icon_.reset(::CopyIcon(i.icon_.get()));\r
+    }\r
+\r
+    icon(icon&& i) : width_(i.width_),height_(i.height_),bits_per_pixel_(i.bits_per_pixel_)\r
+    {\r
+      std::swap(icon_,i.icon_);\r
+    }\r
+\r
+    icon& operator= (icon&& i) \r
+    {\r
+      BOOST_ASSERT(icon_ != i.icon_);\r
+      if(icon_ == i.icon_) return *this;\r
+      std::swap(icon_,i.icon_);\r
+      width_ = i.width_;\r
+      height_ = i.height_;\r
+      bits_per_pixel_ = i.bits_per_pixel_;\r
+      return *this;\r
+    }\r
+\r
+    icon& operator= (icon& i);\r
+\r
+    void swap(icon& i)\r
+    {\r
+      std::swap(icon_,i.icon_);\r
+      std::swap(width_,i.width_);\r
+      std::swap(height_,i.height_);\r
+      std::swap(bits_per_pixel_,i.bits_per_pixel_);\r
+    }\r
+\r
+  private:\r
+\r
+    void analyze();\r
+    //ID2D1DCRenderTargetPtr dcr_;\r
+    //ID2D1BitmapPtr bitmap_;\r
+    int width_;\r
+    int height_;\r
+    int bits_per_pixel_;\r
+    icon_holder icon_;\r
+    static bitmap_holder default_mono_bitmap; \r
+  };\r
+}\r
+\r
diff --git a/wasapi2/info_tab_dialog.cpp b/wasapi2/info_tab_dialog.cpp
new file mode 100644 (file)
index 0000000..0f1951a
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+==============================================================================
+
+Copyright 2005-11 by Satoshi Fujiwara.
+
+async can be redistributed and/or modified under the terms of the
+GNU General Public License, as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+async is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with async; if not, visit www.gnu.org/licenses or write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+Boston, MA 02111-1307 USA
+
+==============================================================================
+*/
+/* ToDo
+
+TODO: リサイズに対応する
+
+*/
+
+#include "stdafx.h"
+#include "resource.h"
+#define BOOST_ASSIGN_MAX_PARAMS 7
+#include <boost/assign.hpp>
+#include <boost/assign/ptr_list_of.hpp>
+#include <boost/assign/ptr_list_inserter.hpp>
+#include <boost/foreach.hpp>
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "sf_windows.h"
+#include "CommDlg.h"
+#include "icon.h"
+#include "timer.h"
+#include "exception.h"
+#include "application.h"
+#include "info_tab_dialog.h"
+
+#define THROW_IFERR(hres) \
+  if (FAILED(hres)) { throw sf::win32_error_exception(hres); }
+
+#ifndef HINST_THISCOMPONENT
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;
+#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
+#endif
+
+namespace sf 
+{
+    info_tab_dialog::info_tab_dialog(base_window& parent_window,HWND tab_hwnd,int tab_id,const std::wstring& menu_name,const std::wstring& name,HINSTANCE inst,LPCTSTR temp)
+      : tab_dialog_base(parent_window,tab_hwnd,tab_id,menu_name,name,inst,temp)
+    {
+      create_device_independent_resources();
+      create();
+      hide();
+    }
+
+    info_tab_dialog::~info_tab_dialog()
+    {
+      discard_device();
+      safe_release(factory_);
+      safe_release(write_factory_);
+    };
+
+    LRESULT info_tab_dialog::window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)
+    {
+      switch(message)
+      {
+      case WM_INITDIALOG:
+        create_device();
+        break;
+      case WM_CTLCOLORDLG:
+      case WM_CTLCOLORSTATIC:
+      case WM_CTLCOLOREDIT:
+      case WM_CTLCOLORLISTBOX:
+      case WM_CTLCOLORBTN:
+        SetBkMode((HDC)wParam,TRANSPARENT);
+        return  (LRESULT)GetStockObject( NULL_BRUSH ); ;
+      case WM_ERASEBKGND:
+        return FALSE;
+      case WM_PAINT:
+        {
+          //create_device();
+
+          { 
+            paint_struct begin_paint(hwnd);
+            //CloseHandle(cb);
+            // 描画コードの呼び出し
+            render();
+
+          }
+        }
+        break;
+      case WM_CLOSE:
+        discard_device();
+        return FALSE;
+      }
+      return FALSE;
+
+    };
+
+    void info_tab_dialog::create_device_independent_resources()
+    {
+      // Direct2DFactory の生成
+      if(!factory_){
+#if defined(DEBUG) || defined(_DEBUG)
+        D2D1_FACTORY_OPTIONS options;
+        options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION ;
+        THROW_IFERR(D2D1CreateFactory(
+          D2D1_FACTORY_TYPE_SINGLE_THREADED,
+          options,
+          &factory_
+          ));
+#else
+        THROW_IFERR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory_));
+#endif
+
+      }
+
+      if(!write_factory_){
+        THROW_IFERR(::DWriteCreateFactory(
+          DWRITE_FACTORY_TYPE_SHARED,
+          __uuidof(IDWriteFactory),
+          reinterpret_cast<IUnknown**>(&write_factory_)
+          ));
+      }
+
+
+      //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory);
+
+      //thunk_proc_ = (WNDPROC)thunk_.getCode();
+      layout_rect_ = D2D1::RectF(0.0f,100.0f,400.0f,100.0f);
+      // Text Formatの作成
+      THROW_IFERR(write_factory_->CreateTextFormat(
+        L"メイリオ",                // Font family name.
+        NULL,                       // Font collection (NULL sets it to use the system font collection).
+        DWRITE_FONT_WEIGHT_REGULAR,
+        DWRITE_FONT_STYLE_NORMAL,
+        DWRITE_FONT_STRETCH_NORMAL,
+        24.0f,
+        L"ja-jp",
+        &write_text_format_
+        ));
+
+    }
+
+    void info_tab_dialog::create_device()
+    {
+      if(!render_target_)
+      {
+
+        HWND waveform_hwnd = GetDlgItem(hwnd_,IDC_WAVEFORM);
+        RECT rc;
+        GetClientRect(waveform_hwnd, &rc);
+        //  GetClientRect(hwnd_, &rc);
+
+        D2D1_SIZE_U size = D2D1::SizeU(
+          rc.right - rc.left,
+          rc.bottom - rc.top
+          );
+
+        const D2D1_PIXEL_FORMAT format =
+          D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
+          D2D1_ALPHA_MODE_PREMULTIPLIED);
+
+        const D2D1_RENDER_TARGET_PROPERTIES target_prop = 
+          D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,format);
+
+        THROW_IFERR(factory_->CreateHwndRenderTarget(
+          target_prop,
+          D2D1::HwndRenderTargetProperties(waveform_hwnd, size,D2D1_PRESENT_OPTIONS_IMMEDIATELY),
+          &render_target_
+          ));
+        //D2D1::HwndRenderTargetProperties(hwnd_, size,D2D1_PRESENT_OPTIONS_IMMEDIATELY),
+        //&render_target_
+        //));
+      }
+    }
+
+    void info_tab_dialog::discard_device()
+    {
+    //safe_release(sampler_state_);
+    //safe_release(shader_res_view_);
+    //safe_release(cb_changes_every_frame_);
+    //safe_release(cb_change_on_resize_);
+    //safe_release(cb_never_changes_);
+    //safe_release(i_buffer_);
+    //safe_release(v_buffer_);
+    //safe_release(p_shader_);
+    //safe_release(input_layout_);
+    //safe_release(v_shader_);
+    // discard_swap_chain_dependent_resources();
+    safe_release(render_target_);
+ /*   safe_release(swap_chain_);
+    safe_release(d3d_context_);
+    safe_release(d3d_device_);
+    safe_release(adapter_);
+ */ 
+    }
+
+    void info_tab_dialog::render()
+    {
+    if (render_target_)
+    {
+      // Retrieve the size of the render target.
+      D2D1_SIZE_F renderTargetSize = render_target_->GetSize();
+      try {
+        render_target_->BeginDraw();
+//        render_target_->PushAxisAlignedClip(layout_rect_,D2D1_ANTIALIAS_MODE_ALIASED);
+      //  render_target_->Clear(D2D1::ColorF(D2D1::ColorF::AliceBlue));
+        //render_target_->FillRectangle(D2D1::RectF(0.0f,0.0f,renderTargetSize.width,renderTargetSize.height),);
+        render_target_->SetTransform(D2D1::Matrix3x2F::Identity());
+        ID2D1SolidColorBrushPtr brush;
+        render_target_->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::OrangeRed), &brush);
+
+        std::wstring m(L"WAVE FORMを描くところ!");
+        render_target_->DrawTextW(
+          m.c_str(),
+          m.size(),
+          write_text_format_,
+          layout_rect_, 
+          brush);
+ //       render_target_->PopAxisAlignedClip();
+        THROW_IFERR(render_target_->EndDraw());
+
+      } catch(sf::win32_error_exception& err)
+      {
+        if(err.hresult() == D2DERR_RECREATE_TARGET)
+        {
+          discard_device();
+          create_device();
+        } else {
+          throw;
+        }
+      } catch(...) {
+        throw;
+      }
+    }
+    }
+
+}
+
diff --git a/wasapi2/info_tab_dialog.h b/wasapi2/info_tab_dialog.h
new file mode 100644 (file)
index 0000000..1e7b1ab
--- /dev/null
@@ -0,0 +1,43 @@
+#pragma once
+/*
+*/
+// Windows Header Files:
+#include "base_window.h"
+#include "sf_windows.h"
+#include "icon.h"
+#include "taskbar.h"
+#include "tab_dialog.h"
+
+namespace sf
+{
+
+  struct info_tab_dialog : public tab_dialog_base
+  {
+    info_tab_dialog(
+      sf::base_window& parent_window,
+      HWND tab_hwnd,
+      int tab_id,
+      const std::wstring& menu_name,
+      const std::wstring& name,
+      HINSTANCE inst,
+      LPCTSTR temp);
+    virtual ~info_tab_dialog();
+    virtual LRESULT window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam);
+    virtual void enable(){};
+    virtual void disable(){};
+  private:
+
+    void create_device_independent_resources();
+    void create_device();
+    void discard_device();
+    void render();
+
+    ID2D1FactoryPtr factory_;
+    ID2D1HwndRenderTargetPtr render_target_;
+    IDWriteFactoryPtr write_factory_;
+    IWICImagingFactoryPtr wic_imaging_factory_;
+    IDWriteTextFormatPtr write_text_format_;
+    D2D1_RECT_F layout_rect_;
+
+  };
+}
\ No newline at end of file
diff --git a/wasapi2/input_thread.cpp b/wasapi2/input_thread.cpp
new file mode 100644 (file)
index 0000000..fd3116e
--- /dev/null
@@ -0,0 +1,216 @@
+/*\r
+==============================================================================\r
+\r
+This file is part of the async\r
+Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+#include "StdAfx.h"\r
+#include <commctrl.h>\r
+\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+\r
+#include "message_loop.h"\r
+#include "sf_com.h"\r
+#include "application.h"\r
+#include "input_thread.h"\r
+#include "dout.h"\r
+#include "async_reader.h"\r
+\r
+using namespace std;\r
+\r
+namespace sf {\r
+\r
+void input_thread_t::thread_main()\r
+{\r
+  // COMの初期化\r
+  sf::com_initialize init(0,multi_threaded);\r
+\r
+  // MMCSSの初期化\r
+  sf::av_mm_thread_characteristics avmm(wstring(L"Pro Audio"));\r
+  avmm.set_priority(AVRT_PRIORITY_HIGH);\r
\r
+  //// input デバイスの初期化\r
+  //wasapi_device_manager::ptr m(wasapi_device_manager::instance());\r
+  //apply_config_(\r
+  // m->current_input_device_index(),\r
+  // m->current_input_device().params\r
+  //);\r
+  change_status(status_pause);\r
+  application& app(*application::instance());\r
+  int status = STATUS_ERROR;\r
+  BYTE *buffer = 0;\r
+  index_ = 0;\r
+  int source_counter ,dest_counter;\r
+  source_counter  = dest_counter = 0;\r
+  //// 出力デバイスが稼働するまで待つ\r
+  //app.output_thread().wait_status(output_thread_t::status_processing,10);\r
+  //apply_config_(\r
+  //wasapi_device_manager::instance()->current_input_device_index(),\r
+  //wasapi_device_manager::instance()->current_input_device().params);\r
+  change_status(status_device_config);\r
+  while(status = status_.load(),status != status_exit)\r
+  {\r
+    // イベントを待つ\r
+    switch(status)\r
+    {\r
+    case status_device_config:\r
+      if(wasapi_input_)\r
+      {\r
+        wasapi_input_->stop();\r
+        dest_counter = 0;\r
+      }\r
+      change_status(status_device_config_ok);\r
+      break;\r
+    case status_process:\r
+      if(!wasapi_input_->is_start()){\r
+        wasapi_input_->start();\r
+      }\r
+      change_status(status_processing);\r
+    case status_processing:\r
+      {\r
+        wasapi_input_->wait();// 入力待ち\r
+        get_buffer g(*wasapi_input_);// キャプチャバッファの取得\r
+        if(g.size() && g != 0)\r
+        {\r
+          source_counter = 0;\r
+          while(source_counter != g.size())\r
+          {\r
+            BYTE * src = g + source_counter * wasapi_input_->get_frame_size();\r
+            int size_byte_src = g.size_byte() - source_counter * wasapi_input_->get_frame_size();\r
+            int size_src = g.size() - source_counter;\r
+\r
+            BYTE * dest = buffer_[index_].get() + dest_counter * app.output_device().get_frame_size();\r
+            int size_byte_dest = app.output_device().get_buffer_byte_size() - dest_counter * app.output_device().get_frame_size();\r
+            int size_dest = app.output_device().get_buffer_size() - dest_counter;\r
+\r
+            if(size_src <= size_dest)\r
+            {\r
+              ::CopyMemory(dest,src,size_byte_src);\r
+              source_counter += size_src;\r
+              dest_counter += size_src;\r
+            } else if(size_src > size_dest)\r
+            {\r
+              ::CopyMemory(dest,src,size_byte_dest);\r
+              source_counter += size_dest;\r
+              dest_counter += size_dest;\r
+            }\r
+            if(dest_counter == app.output_device().get_buffer_size())\r
+            {\r
+              if(ringbuffer_.enqueue(buffer_[index_].get()))\r
+              {\r
+                index_ = (index_ + 1) & (buffer_.size() - 1);\r
+              }\r
+              dest_counter = 0;\r
+            }\r
+          }\r
+        }\r
+      }\r
+      break;\r
+    case status_pause:\r
+      if(wasapi_input_)\r
+      {\r
+        wasapi_input_->stop();\r
+      }\r
+      change_status(status_pause_ok);\r
+      break;\r
+     default:\r
+      WaitForSingleObject(event_.get(),WAIT_TIMEOUT_DEFAULT);\r
+      break;\r
+    }\r
+  }\r
+loop_end:\r
+  ;\r
+  DOUT(L"##### input_threadは終了!" << endl);\r
+  if(wasapi_input_ && wasapi_input_->is_start())\r
+  {\r
+    wasapi_input_->stop();\r
+  }\r
+  wasapi_input_.reset();\r
+};\r
+\r
+void input_thread_t::apply_config(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+{\r
+  if(status() != status_device_config_ok){\r
+    change_and_wait(status_device_config,status_device_config_ok);\r
+  }\r
+  apply_config_(device_index,params);\r
+  init_buffer();\r
+  change_and_wait(status_process,status_processing);\r
+}\r
+\r
+void input_thread_t::apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+{\r
+  \r
+  WAVEFORMATEXTENSIBLE form;\r
+  if(wasapi_input_)\r
+  {\r
+    if(wasapi_input_->is_start())\r
+    {\r
+      wasapi_input_->stop();\r
+    }\r
+    wasapi_input_.reset();\r
+  };\r
+\r
+  //bits_pair bits = {params.bits,params.valid_bits};\r
+  //make_wave_format(form,params.sample_rate,params.channel,bits);\r
+\r
+  try {\r
+    if(params.exclusive_mode)\r
+    {\r
+      if(params.event_mode){\r
+        wasapi_input_.reset(new sf::wasapi_capture_exclusive_event(device_index,params));\r
+      } else {\r
+        wasapi_input_.reset(new sf::wasapi_capture_exclusive_timer(device_index,params));\r
+      };\r
+    } else {\r
+      if(params.event_mode)\r
+      {\r
+        wasapi_input_.reset(new sf::wasapi_capture_shared_event(device_index,params));\r
+      } else {\r
+        wasapi_input_.reset(new sf::wasapi_capture_shared_timer(device_index,params));\r
+      }\r
+    }\r
+  } catch (win32_error_exception& e)\r
+  {\r
+\r
+    //window_->message_box((boost::wformat(L"WASAPI初期化エラーが発生しました。設定パラメータを見なおしてください。%s") % e.error()).str(),wstring(L"WASAPI初期化エラー"));\r
+    throw;\r
+  }\r
+\r
+  wasapi_device_manager::instance()->select_input_device(device_index);\r
+  wasapi_device_manager::instance()->current_input_device().params = params;\r
+\r
+}\r
+\r
+  //void input_thread_t::init_buffer()\r
+  //{\r
+  //  audio_base& in(application::instance()->input_device());\r
+  //  for(int i = 0,size = buffer_.size();i < size;++i)\r
+  //  {\r
+  //    buffer_[i].reset(reinterpret_cast<uint8_t*>(_aligned_malloc(sizeof(uint8_t) * in.get_buffer_byte_size(),16)));\r
+  //  }\r
+  //}\r
+\r
+\r
+}\r
+\r
diff --git a/wasapi2/input_thread.h b/wasapi2/input_thread.h
new file mode 100644 (file)
index 0000000..40f61e0
--- /dev/null
@@ -0,0 +1,59 @@
+#pragma once\r
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+#include "thread_base.h"\r
+\r
+namespace sf {\r
+struct input_thread_t : public thread_base\r
+{\r
+  input_thread_t(){};\r
+  ~input_thread_t(){};\r
+  void thread_main();\r
+// -----------------------------  \r
+// WASAPI入力関係\r
+// -----------------------------  \r
+  enum input_status\r
+  {\r
+    status_device_config,\r
+    status_device_config_ok,\r
+    status_wait_output_active,\r
+    status_wait_output_active_ok,\r
+    status_process,\r
+    status_processing,\r
+    status_pause,\r
+    status_pause_ok,\r
+    status_exit,\r
+    status_error = STATUS_ERROR\r
+  };\r
+\r
+  void apply_config(int device_index,wasapi_device_manager::device_info::params_t& params);\r
+  //void init_buffer();\r
+\r
+  audio_base& device() {return *wasapi_input_.get();}\r
+private:\r
+  // 入力デバイスの設定・変更\r
+  void apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params);\r
+  std::unique_ptr<audio_base> wasapi_input_;\r
+};\r
+}\r
+\r
diff --git a/wasapi2/jumplist.cpp b/wasapi2/jumplist.cpp
new file mode 100644 (file)
index 0000000..3103f21
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-10 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#include "StdAfx.h"
+#include "jumplist.h"
+
+
diff --git a/wasapi2/jumplist.h b/wasapi2/jumplist.h
new file mode 100644 (file)
index 0000000..ae76867
--- /dev/null
@@ -0,0 +1,32 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-10 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+namespace sf{
+struct jumplist
+{
+public:
+  jumplist(){};
+  virtual ~jumplist(){};
+};
+}
+
diff --git a/wasapi2/logger.cpp b/wasapi2/logger.cpp
new file mode 100644 (file)
index 0000000..01e33b7
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+==============================================================================
+
+This file is part of the S.F.Tracker
+Copyright 2005-7 by Satoshi Fujiwara.
+
+S.F.Tracker can be redistributed and/or modified under the terms of the
+GNU General Public License, as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+S.F.Tracker is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with S.F.Tracker; if not, visit www.gnu.org/licenses or write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+Boston, MA 02111-1307 USA
+
+==============================================================================
+*/
+/** @file
+*  @author S.F. (Satoshi Fujiwara)
+*/
+
+#include "stdafx.h"
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+namespace sf {
+
+  struct logger::impl 
+  {
+    impl() : m_log_file("sftracker.log",std::ios_base::out | std::ios_base::trunc ){};
+    ~impl() {m_log_file.close();}
+
+    void write(const boost::wformat & fmt)
+    {
+      write(fmt.str());
+    };
+
+    void write(const std::wistream & st)
+    {
+      {   
+        //mutex_type::scoped_lock lock_(m_mutex);
+        m_log_file << st << std::endl;
+      }
+      boost::gregorian::date dt = boost::gregorian::day_clock::local_day();
+
+    };
+
+    void write(const std::wstring & mes) 
+    {   
+      write(mes.c_str());
+    }
+
+    void write(const TCHAR * mes) 
+    {   
+      //mutex_type::scoped_lock lock_(m_mutex);
+      m_log_file << mes << std::endl;
+      m_log_file.flush();
+    }   
+  private:
+    std::wofstream m_log_file;
+    //mutex_type m_mutex;
+  };
+
+  logger::logger() : m_impl(new logger::impl())
+  {
+  }
+  void logger::write(const boost::wformat & fmt)
+  {
+    m_impl->write(fmt);
+  };
+
+  void logger::write(const std::wstring & mes) 
+  {   
+    m_impl->write(mes);
+  }
+
+  void logger::write(const TCHAR * mes) 
+  {   
+    m_impl->write(mes);
+  }   
+
+  void logger::write(const std::wistream & st)
+  {
+    m_impl->write(st);
+  }
+
+  logger::~logger()
+  {
+
+  }
+
+  void debug_out(const char * file_name,const int line,boost::wformat& fmt)
+  {
+    OutputDebugString((boost::wformat(_T("%s(%d) %s \n")) % std::wstring(sf::code_converter<char,wchar_t>(file_name)) % line % fmt).str().c_str());
+  };
+
+  void debug_out(const char * file_name,const int line,const std::wstring& str)
+  {
+    OutputDebugString((boost::wformat(_T("%s(%d) %s \n")) % std::wstring(sf::code_converter<char,wchar_t>(file_name)) % line % str).str().c_str());
+  };
+
+  void debug_out(const char * file_name,const int line,const char* str)
+  {
+    OutputDebugString((boost::wformat(_T("%s(%d) %s \n")) % std::wstring(sf::code_converter<char,wchar_t>(file_name)) %  line % sf::code_converter<char,wchar_t>(str)).str().c_str());
+  }
+
+  void debug_outW(const char * file_name,const int line,const wchar_t* str)
+  {
+    OutputDebugString((boost::wformat(_T("%s(%d) %s \n")) % std::wstring(sf::code_converter<char,wchar_t>(file_name)) % line % str).str().c_str());
+  };
+
+}
diff --git a/wasapi2/logger.h b/wasapi2/logger.h
new file mode 100644 (file)
index 0000000..dd0b08c
--- /dev/null
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "boost/date_time/gregorian/gregorian.hpp"
+#include "boost/date_time/posix_time/posix_time.hpp"
+#include "singleton.h"
+
+namespace sf {
+
+  struct logger : public singleton<logger>
+  {
+  public:
+    logger();
+    ~logger();
+    void write(const boost::wformat & fmt);
+    void write(const std::wstring & mes);
+    void write(const TCHAR * mes);
+    void write(const std::wistream & st);
+  private:
+    struct impl;
+    std::shared_ptr<impl> m_impl;
+  };
+
+  void debug_out(const char * file_name,const int line,boost::wformat& fmt);
+  void debug_out(const char * file_name,const int line,const std::wstring& str);
+  void debug_out(const char * file_name,const int line,const char* str);
+  void debug_out(const char * file_name,const int line,const wchar_t* str);
+}
+
+#define WRITE_LOG(s) \
+  sf::logger::instance()->write(boost::wformat(_T("%s %s %6d %s")) % boost::posix_time::second_clock::local_time() % (TCHAR*)sf::ca2t(__FILE__) % __LINE__ % (s))
+
+#ifdef _DEBUG
+#define SFTRACE(x) sf::debug_out(__FILE__,__LINE__,(x))
+#else 
+#define SFTRACE(x) 
+#endif
+
diff --git a/wasapi2/message_loop.h b/wasapi2/message_loop.h
new file mode 100644 (file)
index 0000000..37c3b90
--- /dev/null
@@ -0,0 +1,92 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the S.F.Tracker
+   Copyright 2005-7 by Satoshi Fujiwara.
+
+   S.F.Tracker can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   S.F.Tracker is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with S.F.Tracker; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+/** @file
+ *  @brief 
+ *  @author S.F. (Satoshi Fujiwara)
+ */
+namespace sf {
+       struct run_message_loop
+       {
+               run_message_loop(){};
+               inline WPARAM operator()()
+               {
+                       MSG msg;
+                       while (GetMessage(&msg, NULL, 0, 0))
+                       {
+                               TranslateMessage(&msg);
+                               DispatchMessage(&msg);
+                       }
+      return msg.wParam;
+               }
+
+               ~run_message_loop(void){};
+       };
+
+       struct peek_message_loop
+       {
+               typedef boost::function<void ()> func_type;
+               explicit peek_message_loop(func_type func)  {func_ =  func;};
+               inline WPARAM operator()()
+               {
+                       MSG msg = {0};
+                       while( WM_QUIT != msg.message )
+                       {
+                               if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
+                               {
+                                       TranslateMessage( &msg );
+                                       DispatchMessage( &msg );
+                               }
+                               else
+                               {
+                                       func_();  // Do some rendering
+                               }
+                       }
+      return msg.wParam;
+               };
+       private:
+               func_type func_;
+       };
+
+  struct dialog_message_loop
+       {
+               dialog_message_loop(HWND dialog) : dialog_(dialog) {};
+               inline WPARAM operator()()
+               {
+                       MSG msg;
+                       while (GetMessage(&msg, NULL, 0, 0))
+                       {
+        if(IsDialogMessage(dialog_,&msg) == FALSE)
+        {
+                                 TranslateMessage(&msg);
+                                 DispatchMessage(&msg);
+        }
+                       }
+      return msg.wParam;
+               }
+               ~dialog_message_loop(){};
+  private:
+    HWND dialog_;
+
+       };
+}
diff --git a/wasapi2/mixer_thread.cpp b/wasapi2/mixer_thread.cpp
new file mode 100644 (file)
index 0000000..b937f5d
--- /dev/null
@@ -0,0 +1,121 @@
+/*\r
+==============================================================================\r
+\r
+This file is part of the async\r
+Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+#include "StdAfx.h"\r
+#include <commctrl.h>\r
+\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+\r
+#include "message_loop.h"\r
+#include "sf_com.h"\r
+#include "application.h"\r
+#include "mixer_thread.h"\r
+#include "dout.h"\r
+#include "async_reader.h"\r
+\r
+using namespace std;\r
+\r
+namespace sf {\r
+\r
+\r
+void mixer_thread_t::thread_main()\r
+{\r
+  // TODO:ミキサーの実装\r
+  // COMの初期化\r
+  sf::com_initialize init(0,multi_threaded);\r
+\r
+  // MMCSSの初期化\r
+  //av_mm_thread_characteristics avmm(wstring(L"Pro Audio"));\r
+  //avmm.set_priority(AVRT_PRIORITY::AVRT_PRIORITY_HIGH);\r
+  int status;\r
+  application& app(*application::instance());\r
+\r
+  // 出力デバイスが稼働するまで待つ\r
+  //app.output_thread().wait_status(output_thread_t::status_processing,10);\r
+  // バッファ初期化\r
+  //init_buffer();\r
+  change_status(status_config);\r
+  while(status = status_.load(),status !=status_exit)\r
+  {\r
+  switch(status)\r
+  {\r
+  case status_config:\r
+    {\r
+      change_status(status_config_ok);\r
+    }\r
+    break;\r
+  case status_process:\r
+    {\r
+      init_buffer();\r
+      change_status(status_processing);\r
+    }\r
+  case status_processing:\r
+    {\r
+      Sleep(app.output_device().get_buffer_duration() / 20000);\r
+      BYTE *in(0),*reader(0);\r
+      app.input_ringbuffer().dequeue(in);\r
+      app.reader_ringbuffer().dequeue(reader);\r
+      int size(app.output_device().get_buffer_byte_size());\r
+      BYTE *dest(buffer_[index_].get());\r
+      if(in != 0 && reader != 0)\r
+      {\r
+        ::CopyMemory(dest,in,size);\r
+        size = size / app.output_device().get_frame_size();\r
+        WORD *destw((WORD*)dest),*srcw((WORD*)reader);\r
+        for(int i = 0;i < size;++i)\r
+        {\r
+          *destw++ += *srcw++;\r
+          *destw++ += *srcw++;\r
+        }\r
+      } else if(in != 0)\r
+      {\r
+        ::CopyMemory(dest,in,size);\r
+      } else if(reader != 0)\r
+      {\r
+        ::CopyMemory(dest,reader,size);\r
+      } else {\r
+        ::ZeroMemory(dest,size);\r
+      }\r
+      \r
+      while(!ringbuffer_.enqueue(buffer_[index_].get()))\r
+      {\r
+        Sleep(app.output_device().get_buffer_duration() / 20000);\r
+      }\r
+\r
+      index_ = (index_ + 1) & (buffer_.size() -1 );\r
+\r
+    }\r
+    break;\r
+  case status_pause:\r
+    change_status(status_pause_ok);\r
+    break;\r
+  default:\r
+    WaitForSingleObject(event_.get(),WAIT_TIMEOUT);\r
+  }\r
+  }\r
+}\r
+}\r
+\r
diff --git a/wasapi2/mixer_thread.h b/wasapi2/mixer_thread.h
new file mode 100644 (file)
index 0000000..e42da2f
--- /dev/null
@@ -0,0 +1,46 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-10 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#include "thread_base.h"
+
+namespace sf {
+struct mixer_thread_t : public thread_base
+{
+  mixer_thread_t(){};
+  ~mixer_thread_t(){};
+  void thread_main();
+  enum mixer_status
+  {
+    status_config,
+    status_config_ok,
+    status_process,
+    status_processing,
+    status_pause,
+    status_pause_ok,
+    status_exit,
+    status_error = STATUS_ERROR
+  };
+private:
+};
+}
+
diff --git a/wasapi2/output_thread.cpp b/wasapi2/output_thread.cpp
new file mode 100644 (file)
index 0000000..f863dd5
--- /dev/null
@@ -0,0 +1,299 @@
+/*\r
+==============================================================================\r
+\r
+This file is part of the async\r
+Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+#include "StdAfx.h"\r
+#include <commctrl.h>\r
+\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+\r
+#include "message_loop.h"\r
+#include "sf_com.h"\r
+#include "application.h"\r
+#include "dout.h"\r
+#include "async_reader.h"\r
+#include "output_thread.h"\r
+\r
+\r
+using namespace std;\r
+using namespace boost;\r
+\r
+namespace sf {\r
+\r
+  /// WASAPI出力スレッド\r
+  void output_thread_t::thread_main()\r
+  {\r
+    // COMの初期化\r
+    sf::com_initialize init(0,multi_threaded);\r
+\r
+    // MMCSSの初期化\r
+    sf::av_mm_thread_characteristics avmm(wstring(L"Pro Audio"));\r
+    avmm.set_priority(AVRT_PRIORITY_HIGH);\r
+    //apply_config_(\r
+    //  wasapi_device_manager::instance()->current_output_device_index(),\r
+    //  wasapi_device_manager::instance()->current_output_device().params);\r
+    BYTE* reader_buffer,*input_buffer,*mix_buffer;\r
+    uint32_t status;\r
+    size_t size_of_buffer = 0;\r
+    size_t remaining_of_buffer =  0;\r
+    BYTE* wasapi_buffer = 0;\r
+    size_t remaining_of_wasapi_buffer = 0;\r
+    memory_block_t mix_work;\r
+\r
+    bool wasapi_ready = false;\r
+\r
+    //if(wasapi_output_->is_enabled())\r
+    //{\r
+    //  change_status(status_processing);\r
+    //} else {\r
+      change_status(status_device_config);\r
+    //}\r
+\r
+    application& app(*application::instance());\r
+\r
+\r
+    while(status = status_.load(std::memory_order_acquire), (status != status_exit ))\r
+    { \r
+      try {\r
+        switch (status)\r
+        {\r
+        case status_device_config:\r
+          // 出力デバイスの変更\r
+          if(wasapi_output_ && wasapi_output_->is_start())\r
+          {\r
+            wasapi_output_->stop();\r
+          }\r
+          remaining_of_buffer = 0;\r
+          change_status(status_device_config_ok);\r
+          break;\r
+        case status_process:\r
+          mix_work.reset(reinterpret_cast<BYTE*>(_aligned_malloc(sizeof(uint8_t) * wasapi_output_->get_buffer_byte_size(),16))); \r
+          change_status(status_processing);\r
+          // fall through\r
+        case status_processing:\r
+          {\r
+            size_of_buffer = wasapi_output_->get_buffer_size();\r
+            assert(wasapi_output_->is_enabled());\r
+            // 処理されたバイト数\r
+            if(remaining_of_buffer == 0) // データ残り0なら\r
+            {\r
+              //リングバッファから新たにデータを読み込む\r
+              //if(!app.mixer_ringbuffer().dequeue(reader_buffer)) // 読み込めない場合\r
+              int size = wasapi_output_->get_buffer_byte_size();\r
+              if(!app.reader_ringbuffer().dequeue(reader_buffer)) reader_buffer = 0;\r
+              if(!app.input_ringbuffer().dequeue(input_buffer)) input_buffer = 0;\r
+              if(input_buffer != 0 && reader_buffer != 0)\r
+              {\r
+                ::CopyMemory(mix_work.get(),input_buffer,size);\r
+                size = size / app.output_device().get_frame_size();\r
+                WORD *destw((WORD*)mix_work.get()),*srcw((WORD*)reader_buffer);\r
+                for(int i = 0;i < size;++i)\r
+                {\r
+                  *destw++ += *srcw++;\r
+                  *destw++ += *srcw++;\r
+                }\r
+              } else if(input_buffer != 0)\r
+              {\r
+                ::CopyMemory(mix_work.get(),input_buffer,size);\r
+              } else if(reader_buffer != 0)\r
+              {\r
+                ::CopyMemory(mix_work.get(),reader_buffer,size);\r
+              } else {\r
+                get_buffer g(*wasapi_output_.get(),size_of_buffer);\r
+                               if(g.size() != 0){\r
+                                       ::ZeroMemory(g.get(),g.size_byte());\r
+                               }\r
+                goto copy_end;\r
+              }\r
+              mix_buffer = mix_work.get();\r
+              remaining_of_buffer = size_of_buffer;\r
+            }\r
+\r
+            // WASAPIからバッファアドレスを取得する\r
+            { get_buffer g(*wasapi_output_.get(),size_of_buffer);\r
+            wasapi_buffer = g;\r
+            remaining_of_wasapi_buffer = g.size();// バッファのサイズ必ずしも\r
+            // 要求したバイトが取得できるとはかぎらない\r
+\r
+            if(remaining_of_buffer == remaining_of_wasapi_buffer)\r
+            {\r
+              // バッファの残りとWASAPIバッファの残りが同じとき\r
+              const uint32_t size_copy(remaining_of_wasapi_buffer * wasapi_output_->get_frame_size());\r
+              ::CopyMemory(wasapi_buffer,mix_buffer,size_copy);\r
+              remaining_of_buffer = 0;\r
+              remaining_of_wasapi_buffer = 0; \r
+            } else if(remaining_of_buffer > remaining_of_wasapi_buffer)\r
+            {\r
+              // バッファの残り>WASAPIバッファの残り\r
+              const uint32_t size_copy(remaining_of_wasapi_buffer * wasapi_output_->get_frame_size());\r
+              ::CopyMemory(wasapi_buffer,mix_buffer,size_copy);\r
+              mix_buffer += size_copy;\r
+              remaining_of_buffer -= remaining_of_wasapi_buffer;\r
+              remaining_of_wasapi_buffer = 0;\r
+            } else if(remaining_of_buffer < remaining_of_wasapi_buffer)\r
+            {\r
+              // バッファの残り<WASAPIバッファの残り\r
+              const uint32_t size_copy(remaining_of_buffer * wasapi_output_->get_frame_size());\r
+              ::CopyMemory(wasapi_buffer,mix_buffer,size_copy);\r
+              wasapi_buffer +=  size_copy;\r
+              remaining_of_wasapi_buffer -= remaining_of_buffer;\r
+\r
+              int size = wasapi_output_->get_buffer_byte_size();\r
+              if(!app.reader_ringbuffer().dequeue(reader_buffer)) reader_buffer = 0;\r
+              if(!app.output_ringbuffer().dequeue(input_buffer)) input_buffer = 0;\r
+\r
+              if(input_buffer != 0 && reader_buffer != 0)\r
+              {\r
+                ::CopyMemory(mix_work.get(),input_buffer,size_of_buffer);\r
+                size = size_of_buffer / app.output_device().get_frame_size();\r
+                WORD *destw((WORD*)mix_work.get()),*srcw((WORD*)reader_buffer);\r
+                for(int i = 0;i < size;++i)\r
+                {\r
+                  *destw++ += *srcw++;\r
+                  *destw++ += *srcw++;\r
+                }\r
+              } else if(input_buffer != 0)\r
+              {\r
+                ::CopyMemory(mix_work.get(),input_buffer,size);\r
+              } else if(reader_buffer != 0)\r
+              {\r
+                ::CopyMemory(mix_work.get(),reader_buffer,size);\r
+              } else {\r
+                memset(wasapi_buffer,0,remaining_of_wasapi_buffer * wasapi_output_->get_frame_size());\r
+                continue;\r
+              }\r
+              mix_buffer = mix_work.get();\r
+              {\r
+                const uint32_t size_copy(remaining_of_wasapi_buffer * wasapi_output_->get_frame_size());\r
+                ::CopyMemory(wasapi_buffer,mix_buffer,size_copy);\r
+                mix_buffer += size_copy;\r
+                remaining_of_buffer = size_of_buffer - remaining_of_wasapi_buffer;\r
+              }\r
+            }\r
+            }\r
+copy_end:\r
+            if(!wasapi_output_->is_start())\r
+            {\r
+              wasapi_output_->start();\r
+            }\r
+\r
+            if(wasapi_output_->get_current_padding() == size_of_buffer)\r
+            {\r
+              wasapi_output_->wait();\r
+            } else {\r
+              DOUT(L"XXXX No Wait !!!! XXXX" << std::endl);\r
+            }\r
+          }\r
+          break;\r
+        default:\r
+          WaitForSingleObject(event_.get(),WAIT_TIMEOUT);\r
+          break;\r
+        }\r
+      } catch (win32_error_exception& e) {\r
+        error_ = (wformat(L"出力スレッドでエラーが発生しました。:%s %x") % e.error() % e.hresult()).str();\r
+        change_status(status_error);\r
+      } catch (...) {\r
+        error_ = L"出力スレッドで不明なエラーが発生しました。";\r
+        change_status(status_error);\r
+      }\r
+    }\r
+loop_end:\r
+    if(wasapi_output_){\r
+      if(wasapi_output_->is_start())\r
+      {\r
+        wasapi_output_->stop();\r
+      }\r
+      wasapi_output_.reset();\r
+    }\r
+    DOUT(L"***** output_threadは終了!" << std::endl);\r
+  };\r
+\r
+  void output_thread_t::apply_config(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+  {\r
+    if(status() != status_device_config_ok){ \r
+      change_and_wait(status_device_config,status_device_config_ok);\r
+    }\r
+\r
+    apply_config_(device_index,params);\r
+\r
+    change_and_wait(status_process,status_processing);\r
+\r
+    //if(reader_ && status_.load() == reader_ready){\r
+    //  reader_->reset_data_position();\r
+    //  reader_index_ = 0;\r
+    //}\r
+  }\r
+\r
+  void output_thread_t::apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+  {\r
+\r
+    //  assert(status_.load() == reader_stop);\r
+\r
+    // 出力スレッドを設定変更状態にする\r
+\r
+    WAVEFORMATEXTENSIBLE form;\r
+\r
+    if(wasapi_output_)\r
+    {\r
+      if(wasapi_output_->is_start())\r
+      {\r
+        wasapi_output_->stop();\r
+      }\r
+      wasapi_output_.reset();\r
+    };\r
+\r
+    try {\r
+      if(params.exclusive_mode)\r
+      {\r
+        if(params.event_mode){\r
+          wasapi_output_.reset(new sf::wasapi_exclusive_event(device_index,params));\r
+        } else {\r
+          wasapi_output_.reset(new sf::wasapi_exclusive_timer(device_index,params));\r
+        };\r
+      } else {\r
+        if(params.event_mode)\r
+        {\r
+          wasapi_output_.reset(new sf::wasapi_shared_event(device_index,params));\r
+        } else {\r
+          wasapi_output_.reset(new sf::wasapi_shared_timer(device_index,params));\r
+        }\r
+      }\r
+    } catch (win32_error_exception& e)\r
+    {\r
+\r
+      //window_->message_box((boost::wformat(L"WASAPI初期化エラーが発生しました。設定パラメータを見なおしてください。%s") % e.error()).str(),wstring(L"WASAPI初期化エラー"));\r
+      throw;\r
+    }\r
+\r
+    wasapi_device_manager::instance()->select_output_device(device_index);\r
+    wasapi_device_manager::instance()->current_output_device().params = params;\r
+\r
+    // バッファのアロケート\r
+    init_buffer();\r
+\r
+\r
+  }\r
+}\r
+\r
diff --git a/wasapi2/output_thread.h b/wasapi2/output_thread.h
new file mode 100644 (file)
index 0000000..b867cd9
--- /dev/null
@@ -0,0 +1,68 @@
+#pragma once\r
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+#include "singleton.h"\r
+#include "exception.h"\r
+#include "ring_buffer.h"\r
+#include "wasapi.h"\r
+#include "thread_base.h"\r
+\r
+namespace sf {\r
+struct output_thread_t : public thread_base\r
+{\r
+public:\r
+  struct exception\r
+    : public sf::win32_error_exception \r
+  {\r
+    exception(uint32_t hr) : win32_error_exception(hr) {};\r
+    exception() : win32_error_exception() {} ;\r
+  };\r
+\r
+  output_thread_t() {};\r
+  ~output_thread_t(){};\r
+\r
+  void thread_main();\r
+\r
+// ----------------------------\r
+// WASAPI出力関係\r
+// ----------------------------\r
+// 出力デバイスの設定・変更\r
+  enum output_status\r
+  {\r
+    status_device_config,\r
+    status_device_config_ok,\r
+    status_process,\r
+    status_processing,\r
+    status_pause,\r
+    status_exit,\r
+    status_error = STATUS_ERROR\r
+  };\r
+  void apply_config(int device_index,wasapi_device_manager::device_info::params_t& params);\r
+  audio_base& device() {return *wasapi_output_.get();}\r
+private:\r
+  void apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params);\r
+\r
+  std::unique_ptr<audio_base> wasapi_output_;\r
+};\r
+}\r
+\r
diff --git a/wasapi2/reader_thread.cpp b/wasapi2/reader_thread.cpp
new file mode 100644 (file)
index 0000000..48d9de6
--- /dev/null
@@ -0,0 +1,214 @@
+/*\r
+==============================================================================\r
+\r
+This file is part of the async\r
+Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+#include "StdAfx.h"\r
+#include <commctrl.h>\r
+\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+\r
+#include "message_loop.h"\r
+#include "sf_com.h"\r
+#include "dout.h"\r
+#include "async_reader.h"\r
+#include "application.h"\r
+#include "reader_thread.h"\r
+\r
+using namespace std;\r
+\r
+namespace sf {\r
+\r
+  void reader_thread_t::thread_main()\r
+  {\r
+    // COMの初期化\r
+    sf::com_initialize init(0,multi_threaded);\r
+    application& app(*application::instance().get());\r
+    while(true)\r
+    {\r
+      switch(status_.load(std::memory_order_acquire))\r
+      {\r
+      case status_config:\r
+        change_status(status_config_ok);\r
+        break;\r
+      case status_ready:\r
+        DOUT(L"@@@@ reader_thread_t:ready @@@@  " << std::endl);\r
+        change_status(status_ready_ok);\r
+        break;\r
+      case status_exit:\r
+        DOUT(L"@@@@ reader_thread_t:exit @@@@  " << std::endl);\r
+        goto loop_end;\r
+        break;\r
+      case status_play:\r
+        {\r
+//          init_buffer();\r
+          change_status(status_play_ok);\r
+        }\r
+      case status_play_ok:\r
+        {\r
+          DOUT(L"@@@@ reader_thread_t:read_file @@@@  " << std::endl);\r
+          audio_base& out(app.output_device());\r
+          while(status_.load(std::memory_order_acquire) == status_play_ok)\r
+          {\r
+            if(reader_->more_data_available() || not_enqueue_)\r
+            {\r
+              if(!not_enqueue_){              \r
+                uint32_t size = reader_->data_bytes_remaining() >  out.get_buffer_byte_size()\r
+                  ?  out.get_buffer_byte_size() : reader_->data_bytes_remaining();\r
+                if(size == 0 && repeat_mode_)\r
+                {\r
+                  reader_->reset_data_position();\r
+                  size = (reader_->data_bytes_remaining() >  out.get_buffer_byte_size())\r
+                    ?  out.get_buffer_byte_size() : reader_->data_bytes_remaining();\r
+                }\r
+\r
+                reader_->read_data(buffer_[index_].get(),sizeof(uint8_t) * size);\r
+                //reader_->\r
+\r
+                // ここに変換処理を入れる\r
+                position_ += size;\r
+                if(position_ > reader_->total_data_bytes() && repeat_mode_)\r
+                {\r
+                  position_ -= reader_->total_data_bytes();\r
+                };\r
+\r
+                reader_->wait();\r
+                if(size < out.get_buffer_byte_size())\r
+                {\r
+                  memset(buffer_[index_].get() + size,0,out.get_buffer_byte_size() - size);\r
+                }\r
+              }\r
+\r
+              not_enqueue_ = false;\r
+\r
+              while(!ringbuffer_.enqueue(buffer_[index_].get()))\r
+              {\r
+                //wdout << L"++++ queue max ++++ : " << index_ << std::endl;\r
+                if(status_.load() != status_play_ok)\r
+                {\r
+                  if(status_.load(std::memory_order_relaxed) == status_pause_ok)\r
+                  {\r
+                    not_enqueue_ = true;\r
+                  }\r
+                  break;\r
+                } else {\r
+                  Sleep(1);\r
+                }\r
+              }\r
+\r
+              ;\r
+              //#ifdef _DEBUG\r
+              //            wdout << boost::wformat(L"index:%d address:%x 差分:%x") \r
+              //            % index_ % buffer_[index_].get()\r
+              //            % (buffer_[(index_ + 1) & (buffer_.size() - 1)].get() - buffer_[index_].get())\r
+              //            << std::endl; \r
+              //#endif\r
+              if(!not_enqueue_){\r
+                index_ = (++index_) & (buffer_.size() - 1);\r
+              }\r
+\r
+            } else {\r
+              status_.store(status_end);\r
+              break;\r
+            }\r
+          }\r
+        }\r
+        break;\r
+      case status_pause:\r
+        DOUT(boost::wformat(L"**pause** index:%d address:%x") % index_ % buffer_[index_].get() << std::endl);\r
+        change_status(status_pause_ok);\r
+        break;\r
+      case status_end:\r
+        app.reader_end();\r
+        reader_->reset_data_position();\r
+        ringbuffer_.reset();\r
+        position_ = 0;\r
+        change_status(status_end_ok);\r
+        break;\r
+      case status_seek:\r
+        reader_->seek(position_);\r
+        ringbuffer_.reset();\r
+        index_ = 0;\r
+        change_status(status_seek_ok);\r
+        break;\r
+      case status_stop:\r
+        DOUT(L"reader_thread_t **stop**" << std::endl);\r
+        reader_->reset_data_position();\r
+        ringbuffer_.reset();\r
+        position_ = 0;\r
+        change_status(status_stop_ok);\r
+        break;\r
+      default:\r
+        WaitForSingleObject(event_.get(),WAIT_TIMEOUT_DEFAULT);\r
+        break;\r
+      }\r
+    }\r
+loop_end:\r
+    ;\r
+    DOUT(L"##### reader_thread_tは終了!" << std::endl);\r
+  }\r
+\r
+  void reader_thread_t::setup(const std::wstring& file_path)\r
+  {\r
+    change_and_wait(status_config,status_config_ok);\r
+    source_file_path_ = file_path;\r
+    reader_.reset(new async_reader(file_path,repeat_mode_));\r
+    init_buffer();\r
+    position_ = 0;\r
+    change_and_wait(status_ready,status_ready_ok);\r
+  };\r
+\r
+  void reader_thread_t::position(uint64_t pos)\r
+  {\r
+    uint64_t  div = reader_->get_wave_format().Format.nChannels * reader_->get_wave_format().Format.wBitsPerSample / 8;\r
+    position_ = (pos / div) * div;\r
+    status_backup_ = status_.load();\r
+\r
+    change_and_wait(status_seek,status_seek_ok);\r
+    change_and_wait(status_backup_ - 1,status_backup_);\r
+  }\r
+\r
+  void reader_thread_t::pause()\r
+  {\r
+    if(status_.load() == status_pause_ok)\r
+    {\r
+      read_file();\r
+    } else {\r
+      change_and_wait(status_pause,status_pause_ok);\r
+    }\r
+  }\r
+\r
+  void reader_thread_t::read_file()\r
+  {\r
+    change_and_wait(status_play,status_play_ok);\r
+  }\r
+\r
+  void reader_thread_t::stop()\r
+  {\r
+    change_and_wait(status_stop,status_stop_ok);\r
+  }\r
+\r
+}\r
+\r
+\r
diff --git a/wasapi2/reader_thread.h b/wasapi2/reader_thread.h
new file mode 100644 (file)
index 0000000..e410862
--- /dev/null
@@ -0,0 +1,91 @@
+#pragma once\r
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+#include "thread_base.h"\r
+\r
+namespace sf {\r
+struct reader_thread_t : public thread_base\r
+{\r
+public:\r
+  struct exception\r
+    : public sf::win32_error_exception \r
+  {\r
+    exception(uint32_t hr) : win32_error_exception(hr) {};\r
+    exception() : win32_error_exception() {} ;\r
+  };\r
+\r
+  reader_thread_t() : repeat_mode_(false) {};\r
+  ~reader_thread_t(){};\r
+\r
+  void thread_main();\r
\r
+//  void init_buffer(buffer_t& buffer);\r
+  \r
+//---------------------------------------\r
+// ファイル読取り関係\r
+//---------------------------------------\r
+public:\r
+  enum reader_status\r
+  {\r
+    status_config,\r
+    status_config_ok,\r
+    status_ready,\r
+    status_ready_ok,\r
+    status_stop,\r
+    status_stop_ok,\r
+    status_play,\r
+    status_play_ok,\r
+    status_end,\r
+    status_end_ok,\r
+    status_pause,\r
+    status_pause_ok,\r
+    status_seek,\r
+    status_seek_ok,\r
+    status_rew,\r
+    status_rew_ok,\r
+    status_ff,\r
+    status_ff_ok,\r
+    status_exit,\r
+    status_fail = STATUS_ERROR\r
+  }; \r
+\r
+  void setup(const std::wstring& file_path);\r
+  void read_file();\r
+  void pause();\r
+  void stop();\r
+  uint64_t position() { return position_;};\r
+  void position(uint64_t pos);\r
+  uint64_t size() { return reader_->total_data_bytes(); }\r
+  void repeat_mode(bool v) { repeat_mode_ = v ;reader_->repeat_mode(v);}\r
+  const bool repeat_mode() const {return repeat_mode_;}\r
+\r
+private:\r
+  std::wstring source_file_path_;\r
+  std::unique_ptr<async_reader> reader_;\r
+  uint64_t position_;//,output_counter_;\r
+  uint32_t status_backup_;\r
+  bool repeat_mode_;// リピートモード\r
+  bool not_enqueue_;\r
+};\r
+}\r
+\r
diff --git a/wasapi2/resource.h b/wasapi2/resource.h
new file mode 100644 (file)
index 0000000..f8c1f14
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef IDC_STATIC
+#define IDC_STATIC (-1)
+#endif
+
+#define IDI_ICON1                               100
+#define IDD_MAINDIALOG                          102
+#define IDD_INFO                                104
+#define IDD_CONFIG                              106
+#define IDD_SEQ                                 108
+#define IDC_EDIT1                               1000
+#define IDC_FILE                                1000
+#define IDC_MIN_MAX_LATENCY                     1000
+#define IDC_LATENCY                             1001
+#define IDC_SCROLLBAR1                          1001
+#define IDC_SLIDER                              1001
+#define IDC_CHANNEL                             1002
+#define IDC_EDIT2                               1002
+#define IDC_WAVEFORM                            1002
+#define IDC_APPLY                               1003
+#define IDC_EDIT3                               1003
+#define IDC_INFO                                1003
+#define IDC_EDIT4                               1004
+#define IDC_INPUT_CHANNEL                       1004
+#define IDC_EVENT_MODE                          1005
+#define IDC_PLAY                                1005
+#define IDC_SEQ_AREA                            1005
+#define IDC_REPEAT_CHECK                        1006
+#define IDC_PAUSE                               1007
+#define IDC_EXC_MODE                            1008
+#define IDC_STOP                                1009
+#define IDC_TAB                                 1011
+#define IDC_ENDPOINT_DEVICE                     1017
+#define IDC_SAMPLE_BIT                          1018
+#define IDC_VALID_SAMPLE_BITS                   1019
+#define IDC_SAMPLE_RATE                         1020
+#define IDC_CANCEL                              40000
+#define IDS_STRING1                             40000
+#define IDC_INPUT_ENDPOINT_DEVICE               40010
+#define IDC_INPUT_SAMPLE_BIT                    40011
+#define IDC_INPUT_VALID_SAMPLE_BITS             40012
+#define IDC_INPUT_EXC_MODE                      40014
+#define IDC_INPUT_EVENT_MODE                    40015
+#define IDC_INPUT_SAMPLE_RATE                   40017
+#define IDC_INPUT_LATENCY                       40018
+#define IDC_INPUT_MIN_MAX_LATENCY               40019
diff --git a/wasapi2/ring_buffer.cpp b/wasapi2/ring_buffer.cpp
new file mode 100644 (file)
index 0000000..97a12d6
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-10 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#if defined(_WIN64)
+TRACE("_WIN64 is defined.\n");
+#endif
+
+#include "StdAfx.h"
+#include "ring_buffer.h"
+
+namespace sf {
+  memory_block_t block;
+  buffer_t buffer;
+  ringbuffer_t r;
+}
diff --git a/wasapi2/ring_buffer.h b/wasapi2/ring_buffer.h
new file mode 100644 (file)
index 0000000..a695693
--- /dev/null
@@ -0,0 +1,51 @@
+#pragma once\r
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+#include <malloc.h>\r
+#include <atomic>\r
+#include <boost/lockfree/ringbuffer.hpp>\r
+namespace sf {\r
+\r
+\r
+  // アラインされたメモリの解放\r
+  struct buffer_deleter{\r
+    void operator()(uint8_t *mem)\r
+    {\r
+      _aligned_free(mem);\r
+    };\r
+  };\r
+\r
+  // バッファメモリのスマートポインタ\r
+  // アラインされたメモリを想定\r
+  typedef std::unique_ptr<uint8_t,buffer_deleter> memory_block_t;\r
+\r
+  // メモリブロックの配列\r
+  // ストレージからのデータはここに一時的に格納する\r
+  // この配列値のunique_ptrをget()してリングバッファに渡す\r
+  typedef boost::array<memory_block_t,16> buffer_t;\r
+\r
+  // リングバッファ マルチスレッド対応\r
+  typedef boost::lockfree::ringbuffer<uint8_t* ,8> ringbuffer_t;\r
+\r
+}\r
+\r
diff --git a/wasapi2/sample_rate_converter.cpp b/wasapi2/sample_rate_converter.cpp
new file mode 100644 (file)
index 0000000..8f40789
--- /dev/null
@@ -0,0 +1,46 @@
+#include "StdAfx.h"
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+#include "sample_rate_converter.h"
+#include "exception.h"
+#include "code_converter.h"
+
+#ifdef _DEBUG
+#pragma comment(lib,"src_d.lib")
+#else
+#pragma comment(lib,"src.lib")
+#endif
+namespace sf {
+
+
+sample_rate_converter::sample_rate_converter(double input_rate,double output_rate,int channel,int converter_type) : state_(0)
+{
+  int error = 0;
+  state_ = src_new(converter_type,channel,&error);
+  if(error)
+  {
+    throw sf::exception((wchar_t*)(sf::code_converter<char,wchar_t>(src_strerror(error))));
+  }
+  ZeroMemory(&data_,sizeof(SRC_DATA));
+  data_.src_ratio = output_rate / input_rate;
+}
+
+void sample_rate_converter::apply(float * in,float * out,size_t size)
+{
+  data_.data_in = in;
+  data_.data_out = out;
+  data_.input_frames = data_.output_frames = size;
+  src_process(state_,&data_);
+};
+
+sample_rate_converter::~sample_rate_converter()
+{
+  if(state_)
+  {
+    src_delete(state_);
+  }
+}
+}
diff --git a/wasapi2/sample_rate_converter.h b/wasapi2/sample_rate_converter.h
new file mode 100644 (file)
index 0000000..4d007c7
--- /dev/null
@@ -0,0 +1,49 @@
+#pragma once
+/*
+  ==============================================================================
+
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#include "audio_filter.h"
+#include "samplerate.h"
+namespace sf
+{
+class sample_rate_converter :
+  public audio_filter
+{
+public:
+   enum
+      {    
+          BEST_QUALITY       = 0,
+          MEDIUM_QUALITY     = 1,
+          SINC_FASTEST            = 2,
+          ZERO_ORDER_HOLD         = 3,
+          LINEAR                  = 4
+      } ;
+  sample_rate_converter(double input_rate,double output_rate,int channel,int converter_type = BEST_QUALITY);
+  ~sample_rate_converter();
+  void apply(float * in,float * out,size_t size);
+  void end_of_data(bool value) {data_.end_of_input = value?1:0;}
+  void reset(){ src_reset(state_);};
+private:
+  SRC_STATE* state_;
+  SRC_DATA data_;
+};
+}
+
diff --git a/wasapi2/seq_tab_dialog.cpp b/wasapi2/seq_tab_dialog.cpp
new file mode 100644 (file)
index 0000000..de577f6
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+==============================================================================
+
+Copyright 2005-11 by Satoshi Fujiwara.
+
+async can be redistributed and/or modified under the terms of the
+GNU General Public License, as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+async is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with async; if not, visit www.gnu.org/licenses or write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+Boston, MA 02111-1307 USA
+
+==============================================================================
+*/
+/* ToDo
+
+TODO: リサイズに対応する
+
+*/
+
+#include "stdafx.h"
+#include "resource.h"
+#define BOOST_ASSIGN_MAX_PARAMS 7
+#include <boost/assign.hpp>
+#include <boost/assign/ptr_list_of.hpp>
+#include <boost/assign/ptr_list_inserter.hpp>
+#include <boost/foreach.hpp>
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "sf_windows.h"
+#include "CommDlg.h"
+#include "icon.h"
+#include "timer.h"
+#include "exception.h"
+#include "application.h"
+#include "seq_tab_dialog.h"
+
+#define THROW_IFERR(hres) \
+  if (FAILED(hres)) { throw sf::win32_error_exception(hres); }
+
+#ifndef HINST_THISCOMPONENT
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;
+#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
+#endif
+
+namespace sf 
+{
+  seq_tab_dialog::seq_tab_dialog
+    (sequencer& seq,base_window& parent_window,
+    HWND tab_hwnd,int tab_id,const std::wstring& menu_name,
+    const std::wstring& name,HINSTANCE inst,LPCTSTR temp)
+    : seq_(seq),tab_dialog_base(parent_window,tab_hwnd,tab_id,menu_name,name,inst,temp)
+  {
+    create_device_independent_resources();
+    create();
+    hide();
+  }
+
+  seq_tab_dialog::~seq_tab_dialog()
+  {
+    discard_device();
+    safe_release(factory_);
+    safe_release(write_factory_);
+  };
+
+  LRESULT seq_tab_dialog::window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)
+  {
+    switch(message)
+    {
+    case WM_INITDIALOG:
+      create_device();
+      break;
+    case WM_SIZE:
+      //resize();
+      break;
+    case WM_CTLCOLORDLG:
+    case WM_CTLCOLORSTATIC:
+    case WM_CTLCOLOREDIT:
+    case WM_CTLCOLORLISTBOX:
+    case WM_CTLCOLORBTN:
+      SetBkMode((HDC)wParam,TRANSPARENT);
+      return  (LRESULT)GetStockObject( NULL_BRUSH ); ;
+    case WM_ERASEBKGND:
+      return FALSE;
+    case WM_PAINT:
+      {
+
+        { 
+          paint_struct begin_paint(hwnd);
+          //CloseHandle(cb);
+          // 描画コードの呼び出し
+          render();
+
+        }
+      }
+      break;
+    case WM_CLOSE:
+      discard_device();
+      return FALSE;
+    }
+    return FALSE;
+
+  };
+
+  //void wm_
+
+  void seq_tab_dialog::create_device_independent_resources()
+  {
+    // Direct2DFactory の生成
+    if(!factory_){
+#if defined(DEBUG) || defined(_DEBUG)
+      D2D1_FACTORY_OPTIONS options;
+      options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION ;
+      THROW_IFERR(D2D1CreateFactory(
+        D2D1_FACTORY_TYPE_SINGLE_THREADED,
+        options,
+        &factory_
+        ));
+#else
+      THROW_IFERR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory_));
+#endif
+
+    }
+
+    if(!write_factory_){
+      THROW_IFERR(::DWriteCreateFactory(
+        DWRITE_FACTORY_TYPE_SHARED,
+        __uuidof(IDWriteFactory),
+        reinterpret_cast<IUnknown**>(&write_factory_)
+        ));
+    }
+
+
+    //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory);
+
+    //thunk_proc_ = (WNDPROC)thunk_.getCode();
+    layout_rect_ = D2D1::RectF(0.0f,100.0f,400.0f,100.0f);
+    // Text Formatの作成
+    THROW_IFERR(write_factory_->CreateTextFormat(
+      L"MS GOTHIC",                // Font family name.
+      NULL,                       // Font collection (NULL sets it to use the system font collection).
+      DWRITE_FONT_WEIGHT_BOLD,
+      DWRITE_FONT_STYLE_NORMAL,
+      DWRITE_FONT_STRETCH_NORMAL,
+      12.0f,
+      L"ja-jp",
+      &write_text_format_
+      ));
+
+  }
+
+  void seq_tab_dialog::create_device()
+  {
+    if(!render_target_)
+    {
+
+      HWND waveform_hwnd = GetDlgItem(hwnd_,IDC_SEQ_AREA);
+      RECT rc;
+      GetClientRect(waveform_hwnd, &rc);
+      //  GetClientRect(hwnd_, &rc);
+
+      D2D1_SIZE_U size = D2D1::SizeU(
+        rc.right - rc.left,
+        rc.bottom - rc.top
+        );
+
+      const D2D1_PIXEL_FORMAT format =
+        D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
+        D2D1_ALPHA_MODE_PREMULTIPLIED);
+
+      const D2D1_RENDER_TARGET_PROPERTIES target_prop = 
+        D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,format);
+
+      THROW_IFERR(factory_->CreateHwndRenderTarget(
+        target_prop,
+        D2D1::HwndRenderTargetProperties(waveform_hwnd, size,D2D1_PRESENT_OPTIONS_IMMEDIATELY),
+        &render_target_
+        ));
+      //D2D1::HwndRenderTargetProperties(hwnd_, size,D2D1_PRESENT_OPTIONS_IMMEDIATELY),
+      //&render_target_
+      //));
+    }
+  }
+
+  void seq_tab_dialog::discard_device()
+  {
+    //safe_release(sampler_state_);
+    //safe_release(shader_res_view_);
+    //safe_release(cb_changes_every_frame_);
+    //safe_release(cb_change_on_resize_);
+    //safe_release(cb_never_changes_);
+    //safe_release(i_buffer_);
+    //safe_release(v_buffer_);
+    //safe_release(p_shader_);
+    //safe_release(input_layout_);
+    //safe_release(v_shader_);
+    // discard_swap_chain_dependent_resources();
+    safe_release(render_target_);
+    /*   safe_release(swap_chain_);
+    safe_release(d3d_context_);
+    safe_release(d3d_device_);
+    safe_release(adapter_);
+    */ 
+  }
+
+  void seq_tab_dialog::render()
+  {
+    create_device();
+
+    if (render_target_ && !(render_target_->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED) )
+    {
+      // Retrieve the size of the render target.
+      D2D1_SIZE_F renderTargetSize = render_target_->GetSize();
+      try {
+        render_target_->BeginDraw();
+        //        render_target_->PushAxisAlignedClip(layout_rect_,D2D1_ANTIALIAS_MODE_ALIASED);
+        //  render_target_->Clear(D2D1::ColorF(D2D1::ColorF::AliceBlue));
+        //render_target_->FillRectangle(D2D1::RectF(0.0f,0.0f,renderTargetSize.width,renderTargetSize.height),);
+        render_target_->SetTransform(D2D1::Matrix3x2F::Identity());
+        ID2D1SolidColorBrushPtr brush;
+        render_target_->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::OrangeRed), &brush);
+
+        std::wstring m(L"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzアイウエオカキクケコ\n1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzアイウエオカキクケコ\n");
+        render_target_->DrawTextW(
+          m.c_str(),
+          m.size(),
+          write_text_format_,
+          layout_rect_, 
+          brush);
+        //       render_target_->PopAxisAlignedClip();
+        THROW_IFERR(render_target_->EndDraw());
+
+      } catch(sf::win32_error_exception& err)
+      {
+        if(err.hresult() == D2DERR_RECREATE_TARGET)
+        {
+          discard_device();
+ //         create_device();
+        } else {
+          throw;
+        }
+      } catch(...) {
+        throw;
+      }
+    }
+  }
+
+  void seq_tab_dialog::resize()
+  {
+    discard_device();
+    tab_dialog_base::resize();
+    HWND hwnd_seq = GetDlgItem(hwnd_,IDC_SEQ_AREA);
+    
+    RECT rect_dlg,rect_win;
+    GetClientRect(hwnd_,&rect_dlg);
+    //InflateRect(&rect_dlg,-2,-2);
+    GetWindowRect(hwnd_,&rect_win);
+
+    SetWindowPos(hwnd_seq,0,
+      0,0,
+      rect_dlg.right - rect_dlg.left,
+      rect_dlg.bottom - rect_dlg.top,
+      SWP_NOZORDER);
+    layout_rect_ = D2D1::RectF(rect_dlg.left,rect_dlg.top,rect_dlg.right,rect_dlg.bottom);
+  };
+
+
+}
+
diff --git a/wasapi2/seq_tab_dialog.h b/wasapi2/seq_tab_dialog.h
new file mode 100644 (file)
index 0000000..bd1b9e6
--- /dev/null
@@ -0,0 +1,70 @@
+#pragma once
+/*
+*/
+// Windows Header Files:
+#include "base_window.h"
+#include "sf_windows.h"
+#include "icon.h"
+#include "taskbar.h"
+#include "tab_dialog.h"
+#include "sequencer.h"
+
+namespace sf
+{
+
+  struct seq_tab_dialog : public tab_dialog_base
+  {
+    seq_tab_dialog(
+      sequencer& seq,
+      sf::base_window& parent_window,
+      HWND tab_hwnd,
+      int tab_id,
+      const std::wstring& menu_name,
+      const std::wstring& name,
+      HINSTANCE inst,
+      LPCTSTR temp);
+    virtual ~seq_tab_dialog();
+    virtual LRESULT window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam);
+    virtual void enable(){};
+    virtual void disable(){};
+    virtual void resize();
+
+    struct text 
+    {
+      text(float x,float y,IDWriteTextLayout* layout)
+      {
+        position_.x = x;
+        position_.y = y;
+        layout_.Attach(layout);
+      }
+
+      const D2D1_POINT_2F& position(){return position_;}
+      IDWriteTextLayoutPtr& layout(){return layout_;}
+
+      void position(float x,float y)
+      {
+        position_.x = x;
+        position_.y = y;
+      }
+    private:
+      D2D1_POINT_2F position_;
+      IDWriteTextLayoutPtr layout_;
+    };
+
+  private:
+
+    void create_device_independent_resources();
+    void create_device();
+    void discard_device();
+    void render();
+
+    ID2D1FactoryPtr factory_;
+    ID2D1HwndRenderTargetPtr render_target_;
+    IDWriteFactoryPtr write_factory_;
+    IWICImagingFactoryPtr wic_imaging_factory_;
+    IDWriteTextFormatPtr write_text_format_;
+    D2D1_RECT_F layout_rect_;
+    sequencer& seq_;
+    std::vector<text*> texts_;
+  };
+}
\ No newline at end of file
diff --git a/wasapi2/sequence_dialog.cpp b/wasapi2/sequence_dialog.cpp
new file mode 100644 (file)
index 0000000..35f5d18
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+==============================================================================
+
+Copyright 2005-11 by Satoshi Fujiwara.
+
+async can be redistributed and/or modified under the terms of the
+GNU General Public License, as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+async is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with async; if not, visit www.gnu.org/licenses or write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+Boston, MA 02111-1307 USA
+
+==============================================================================
+*/
+/* ToDo
+
+TODO: リサイズに対応する
+
+*/
+
+#include "stdafx.h"
+#include "resource.h"
+#define BOOST_ASSIGN_MAX_PARAMS 7
+#include <boost/assign.hpp>
+#include <boost/assign/ptr_list_of.hpp>
+#include <boost/assign/ptr_list_inserter.hpp>
+#include <boost/foreach.hpp>
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "sf_windows.h"
+#include "toplevel_window.h"
+#include "CommDlg.h"
+#include "icon.h"
+#include "timer.h"
+#include "exception.h"
+#include "application.h"
+
+#define THROW_IFERR(hres) \
+  if (FAILED(hres)) { throw sf::win32_error_exception(hres); }
+
+#ifndef HINST_THISCOMPONENT
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;
+#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
+#endif
+
+namespace sf 
+{
+}
+
diff --git a/wasapi2/sequencer.cpp b/wasapi2/sequencer.cpp
new file mode 100644 (file)
index 0000000..4dd6011
--- /dev/null
@@ -0,0 +1,66 @@
+/*\r
+==============================================================================\r
+\r
+This file is part of the async\r
+Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+\r
+// SDK\82Ì\83T\83\93\83v\83\8b\82ð\89ü\91¢\82µ\82½\8dì\82Á\82½\82à\82Ì\81B\93à\97e\82Í\82Ù\82Ú\82»\82Ì\82Ü\82Ü\82¾\82ª\81A\94ñ\93¯\8aú\93Ç\82Ý\8d\9e\82Ý\82É\r
+// \91Î\89\9e\82³\82¹\82½\81B\r
+\r
+#include "stdafx.h"\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+#include <stdio.h>\r
+#include <assert.h>\r
+#include <wtypes.h>\r
+#include <mmreg.h>\r
+#include <ks.h>\r
+#include <ksmedia.h>\r
+#include "stdafx.h"\r
+#include "sequencer.h"\r
+using namespace std;\r
+\r
+namespace sf\r
+{\r
+  song_t::song_t()\r
+    :\r
+    time_base_(960),// \83^\83C\83\80\83x\81[\83X(\8el\95ª\89¹\95\84\82Ì\95ª\89ð\94\)\r
+    tempo_(120),// \83e\83\93\83|\r
+    denominator_(4),// \95ª\95ê\r
+    numerator_(4),// \95ª\8eq\r
+    key_(0)// \92²\r
+  {\r
+\r
+  }\r
+\r
+  sequencer::sequencer() :\r
+    current_tempo_(120),\r
+    current_denominator_(4),\r
+    current_numerator_(4),\r
+    current_pos_(0),\r
+    current_key_(0),\r
+    current_meas_(0)\r
+  {\r
+\r
+  }\r
+}\r
diff --git a/wasapi2/sequencer.h b/wasapi2/sequencer.h
new file mode 100644 (file)
index 0000000..bbcb88b
--- /dev/null
@@ -0,0 +1,193 @@
+#pragma once\r
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+#include <audioclient.h>\r
+#include "exception.h"\r
+#include "audio_source.h"\r
+#include "sf_memory.h"\r
+#include "audio_processor.h"\r
+\r
+namespace sf {\r
+\r
+//#pragma pack(push,8)\r
+\r
+  struct sequencer;\r
+\r
+  struct command_base \r
+  {\r
+    //virtual void process(sequencer& s);\r
+  };\r
+\r
+  struct seq_event\r
+  {\r
+\r
+    uint64_t step() {return step_;}\r
+    std::unique_ptr<command_base>& command() {return command_;}\r
+\r
+    void step(uint64_t v) {step_ = v;}\r
+  private:\r
+    uint64_t step_;\r
+    std::unique_ptr<command_base> command_;\r
+  };\r
+\r
+  struct track_base \r
+  {\r
+    const std::wstring& name() {return name_;}\r
+    const std::wstring& comment() {return comment_;}\r
+\r
+    void name(const std::wstring& v) {name_ = v;}\r
+    void comment(const std::wstring& v) {comment_ = v;}\r
+\r
+  private:\r
+    std::wstring name_;\r
+    std::wstring comment_;\r
+  };\r
+\r
+  struct track : public track_base\r
+  {\r
+    uint64_t step() {return step_;}// \83X\83e\83b\83v\83I\83t\83Z\83b\83g\r
+    int32_t key() {return key_;}// \83L\81[\83I\83t\83Z\83b\83g\r
+    uint32_t midi_channel() {return midi_channel_;}// MIDI\83`\83\83\83\93\83l\83\8b\r
+    audio_processor* processor() {return processor_;}// \83I\81[\83f\83B\83I\83G\83\93\83W\83\93\82Ö\82Ì\8eQ\8fÆ\r
+    std::vector<seq_event>& events() {return events_;}// \83C\83x\83\93\83g\r
+\r
+    void step(uint64_t v) {step_ = v;}// \83X\83e\83b\83v\83I\83t\83Z\83b\83g\r
+    void key(int32_t v) {key_ = v;}// \83L\81[\83I\83t\83Z\83b\83g\r
+    void midi_channel(uint32_t v) {midi_channel_ = v;}// MIDI\83`\83\83\83\93\83l\83\8b\r
+    void processor(audio_processor* v) {processor_ = v;}// \83I\81[\83f\83B\83I\83G\83\93\83W\83\93\82Ö\82Ì\8eQ\8fÆ\r
+\r
+  private:\r
+    uint64_t step_;// \83X\83e\83b\83v\83I\83t\83Z\83b\83g\r
+    int32_t key_;// \83L\81[\83I\83t\83Z\83b\83g\r
+    uint32_t midi_channel_;// MIDI\83`\83\83\83\93\83l\83\8b\r
+    audio_processor* processor_;// \83I\81[\83f\83B\83I\83G\83\93\83W\83\93\82Ö\82Ì\8eQ\8fÆ\r
+    std::vector<seq_event> events_;// \83C\83x\83\93\83g\r
+  };\r
+\r
+  struct pattern : public command_base\r
+  {\r
+\r
+    const std::wstring& name() {return name_;}\r
+    const std::wstring& comment() {return comment_;}\r
+    int32_t key() {return key_;}// \83L\81[\83I\83t\83Z\83b\83g\r
+    uint32_t step() {return step_;}// \83X\83e\83b\83v\83I\83t\83Z\83b\83g\r
+    std::vector<track_base>& tracks() {return tracks_;}// \r
+\r
+    void name(const std::wstring v) {name_ = v;}\r
+    void comment(const std::wstring v) {comment_ = v;}\r
+    void key(int32_t v) {key_ = v;}// \83L\81[\83I\83t\83Z\83b\83g\r
+    void step(uint32_t v) {step_ = v;}// \83X\83e\83b\83v\83I\83t\83Z\83b\83g\r
+  private:\r
+    std::wstring name_;\r
+    std::wstring comment_;\r
+    int32_t key_;// \83L\81[\83I\83t\83Z\83b\83g\r
+    uint32_t step_;// \83X\83e\83b\83v\83I\83t\83Z\83b\83g\r
+    std::vector<track_base> tracks_;// \r
+  };\r
+\r
+  struct song_t \r
+  {\r
+    song_t();\r
+    \r
+    std::wstring& name() {return name_;}\r
+    std::wstring& comment() {return comment_;}\r
+    uint32_t time_base(){return time_base_;}// \83^\83C\83\80\83x\81[\83X(\8el\95ª\89¹\95\84\82Ì\95ª\89ð\94\)\r
+    uint32_t tempo(){return tempo_;}// \83e\83\93\83|\r
+    uint32_t denominator(){return denominator_;}// \95ª\95ê\r
+    uint32_t numerator(){return numerator_;}// \95ª\8eq\r
+    int32_t key(){return key_;}// \92²\r
+    std::vector<pattern>& patterns(){return patterns_;}// \83p\83^\81[\83\93\94z\97ñ\r
+\r
+    void name(std::wstring& v) {name_ = v;}\r
+    void comment(std::wstring& v) {comment_ = v;}\r
+    void time_base(uint32_t v) {time_base_ = v;}// \83^\83C\83\80\83x\81[\83X(\8el\95ª\89¹\95\84\82Ì\95ª\89ð\94\)\r
+    void tempo(uint32_t v) {tempo_ = v;}// \83e\83\93\83|\r
+    void denominator(uint32_t v) {denominator_ = v;}// \95ª\95ê\r
+    void numerator(uint32_t v) {numerator_ = v;}// \95ª\8eq\r
+    void key(int32_t v) {key_ = v;}// \92²\r
+\r
+  private:\r
+    std::wstring name_;\r
+    std::wstring comment_;\r
+    uint32_t time_base_;// \83^\83C\83\80\83x\81[\83X(\8el\95ª\89¹\95\84\82Ì\95ª\89ð\94\)\r
+    uint32_t tempo_;// \83e\83\93\83|\r
+    uint32_t denominator_;// \95ª\95ê\r
+    uint32_t numerator_;// \95ª\8eq\r
+    int32_t key_;// \92²\r
+    std::vector<pattern> patterns_;// \83p\83^\81[\83\93\94z\97ñ\r
+  };\r
+\r
+  struct note_command : public command_base\r
+  {\r
+    note_command(uint32_t n,uint32_t g,uint32_t v) \r
+      : note_(n),gate_time_(g),velocity_(v) {};\r
+\r
+    uint32_t note() {return note_;};\r
+    uint32_t gate_time() {return gate_time_;};\r
+    uint32_t velocity() {return velocity_;};\r
+\r
+    void note(uint32_t v) {note_ = v;}\r
+    void gate_time(uint32_t v) {gate_time_ = v;}\r
+    void velocity(uint32_t v) {velocity_ = v;}\r
+\r
+  private:\r
+    uint32_t note_;\r
+    uint32_t gate_time_;\r
+    uint32_t velocity_;\r
+  };\r
+\r
+//#pragma pack(pop)\r
+\r
+  class sequencer : public audio_source\r
+  {\r
+  public:\r
+\r
+    sequencer();\r
+    ~sequencer(){};\r
+    virtual bool seekable(){return true;};\r
+    virtual bool stream_status(){return true;};\r
+    virtual WAVEFORMATEXTENSIBLE &get_wave_format() {return WAVEFORMATEXTENSIBLE();};\r
+    virtual bool more_data_available(){return false;};\r
+    virtual void read_data(BYTE *buffer, uint64_t numbytes){};\r
+    virtual void reset_data_position(){};\r
+    virtual uint64_t total_data_bytes(){return 0;};\r
+    virtual void seek(uint64_t pos){};\r
+    virtual uint64_t data_bytes_remaining(){return 0;};\r
+    virtual HANDLE raw_handle(){return 0;};\r
+    virtual void wait(int timer = -1){};\r
+    song_t& song() {return song_;};\r
+\r
+  private:\r
+    \r
+    uint32_t current_tempo_;\r
+    uint32_t current_denominator_;// \95ª\95ê\r
+    uint32_t current_numerator_;// \95ª\8eq\r
+    uint64_t current_pos_;// \8dÄ\90\83|\83W\83V\83\87\83\93\r
+    uint32_t current_key_;// \83L\81[\83I\83t\83Z\83b\83g\r
+    uint32_t current_meas_;\r
+    song_t song_;\r
+  };\r
+}\r
+\r
\r
+\r
diff --git a/wasapi2/sf_com.cpp b/wasapi2/sf_com.cpp
new file mode 100644 (file)
index 0000000..f547713
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+  ==============================================================================
+
+   This file is part of the S.F.Tracker
+   Copyright 2005-7 by Satoshi Fujiwara.
+
+   S.F.Tracker can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   S.F.Tracker is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with S.F.Tracker; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+/** @file
+ *  @brief util
+ *  @author S.F. (Satoshi Fujiwara)
+ */
+
+#include "stdafx.h"
+#include <objbase.h>
+#include "sf_com.h"
+namespace sf {
+
+    struct com_initialize::impl
+    {
+               impl(void * reserved,unsigned int init) : hr(::CoInitializeEx(reserved,init))
+        {
+        }
+
+        ~impl()
+        {
+                       if(hr == S_OK){
+                   ::CoUninitialize();
+                       }
+        }
+       private:
+               HRESULT hr;
+    };
+
+    com_initialize::com_initialize(void * reserved,unsigned int  init)
+        : m_impl(new com_initialize::impl(reserved,init))
+    {
+    };
+
+       //template <typename ComClass,typename ComInterface> boost::intrusive_ptr<ComInterface> com_creator<ComClass,ComInterface>::create_instance()
+       //{
+       //      ComClass * com_ptr;
+       //      CoCreateInstance( __uuidof(ComClass), NULL,
+       //                       CLSCTX_ALL, __uuidof(ComInterface),
+       //                       (void**)&com_ptr);
+       //      return instrusive_ptr<ComClass>(com_ptr,false);
+       //};
+
+
+}
\ No newline at end of file
diff --git a/wasapi2/sf_com.h b/wasapi2/sf_com.h
new file mode 100644 (file)
index 0000000..7316cc6
--- /dev/null
@@ -0,0 +1,111 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the Shooting3
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+/** @file
+ *  @brief util
+ *  @author S.F. (Satoshi Fujiwara)
+ */
+#include "objbase.h"
+
+
+
+namespace sf 
+{
+  template <class COM_SMART_PTR > inline void safe_release(COM_SMART_PTR& ptr)
+  {
+    if(ptr)
+    {
+      ptr.Release();
+    }
+  };
+    enum com_init 
+    {
+        multi_threaded  = 0x0,
+        apartment_threaded = 0x2,
+        disable_ole1dde   = 0x4,
+        speed_over_memory = 0x8
+    };
+
+    struct com_initialize
+    {
+        struct impl;
+        com_initialize(void * reserved ,unsigned int init);
+        com_initialize(){com_initialize(0,multi_threaded);};
+        ~com_initialize() {};
+    private:
+        std::shared_ptr<impl> m_impl;
+    };
+
+       template <typename ComClass,typename ComInterface> 
+                 boost::intrusive_ptr<ComInterface> create_instance()
+                 {
+                       ComInterface * com_ptr;
+                       CoCreateInstance( __uuidof(ComClass), NULL,
+                                        CLSCTX_ALL, __uuidof(ComInterface),
+                                        (void**)&com_ptr);
+                       return boost::intrusive_ptr<ComInterface>(com_ptr,false);
+
+                 };
+                       template <typename COMInterface> 
+               struct IUnknownImpl : public COMInterface 
+               {
+                       IUnknownImpl() : ref_(1) {}; 
+                       virtual ~IUnknownImpl() {};
+                       ULONG __stdcall AddRef()
+                       {
+                               return InterlockedIncrement(&ref_);
+                       }
+
+                       ULONG __stdcall Release()
+                       {
+                               ULONG ref = InterlockedDecrement(&ref_);
+                               if (0 == ref)
+                               {
+                                       delete this;
+                               }
+                               return ref;
+                       }
+
+                       HRESULT __stdcall QueryInterface(REFIID riid, VOID **ppObj)
+                       {
+                               if (IID_IUnknown == riid)
+                               {
+                                       AddRef();
+                                       *ppObj = (IUnknown*)this;
+                               }
+                               else if (__uuidof(COMInterface) == riid)
+                               {
+                                       AddRef();
+                                       *ppObj = (COMInterface*)this;
+                               }
+                               else
+                               {
+                                       *ppObj = NULL;
+                                       return E_NOINTERFACE;
+                               }
+                               return S_OK;
+                       }
+               private:
+                       LONG ref_;
+               };
+}
\ No newline at end of file
diff --git a/wasapi2/sf_memory.h b/wasapi2/sf_memory.h
new file mode 100644 (file)
index 0000000..3bca7f5
--- /dev/null
@@ -0,0 +1,115 @@
+#pragma once
+namespace sf {
+// policy class
+struct heap_memory_free_policy
+{
+template< typename T >
+void operator()( const T* AMemory ) const
+{
+if( NULL != AMemory )
+::HeapFree( ::GetProcessHeap(), 0, AMemory );
+}
+};
+// policy class
+struct local_memory_free_policy
+{
+template< typename T >
+void operator()( const T* AMemory ) const
+{
+if( NULL != AMemory )
+::LocalFree( AMemory );
+}
+};
+// policy class
+struct co_task_memory_free_policy
+{
+template< typename T >
+void operator()( const T* AMemory ) const
+{
+if( NULL != AMemory )
+::CoTaskMemFree( AMemory );
+}
+};
+// base guard class
+template< typename T,class TFreePolicy >
+class base_memory
+{
+private:
+T *FMemory;
+
+public:
+base_memory( T* AMemory = NULL )
+: FMemory( AMemory ) {}
+
+virtual ~base_memory( void )
+{ reset(); }
+
+T* release( void )
+{
+T *tmp = FMemory;
+FMemory = NULL;
+return tmp;
+}
+
+void reset( T* AMemory = NULL )
+{
+if( AMemory != FMemory )
+{
+if( NULL != FMemory )
+TFreePolicy( FMemory );
+
+FMemory = AMemory;
+}
+}
+
+T* get( void )
+{ return FMemory; }
+
+T* operator ->(void)
+{
+  return FMemory;
+}
+
+T** operator&( void )
+{ return &FMemory; }
+
+};
+template< typename T >
+class heap_memory : public base_memory< T, 
+heap_memory_free_policy >
+{
+public:
+heap_memory( T* AMemory = NULL )
+: base_memory< T, heap_memory_free_policy >( AMemory )
+{ }
+};
+template< typename T >
+class local_memory : public base_memory< T, 
+local_memory_free_policy >
+{
+public:
+local_memory( T* AMemory = NULL )
+: base_memory< T, local_memory_free_policy >( AMemory )
+{ }
+};
+template< typename T >
+class co_task_memory : public base_memory< T, co_task_memory_free_policy >
+{
+public:
+co_task_memory( T* AMemory = NULL )
+: base_memory< T, co_task_memory_free_policy >( AMemory )
+{ }
+};
+
+struct handle_deleter {
+  typedef HANDLE pointer;
+  void operator ()(HANDLE handle) {
+      if (handle != INVALID_HANDLE_VALUE) {
+          CloseHandle(handle);
+      }
+  }
+};
+
+typedef std::unique_ptr<HANDLE,handle_deleter> handle_holder;
+
+};
diff --git a/wasapi2/sf_windows.cpp b/wasapi2/sf_windows.cpp
new file mode 100644 (file)
index 0000000..08ebeef
--- /dev/null
@@ -0,0 +1,247 @@
+#include "stdafx.h"
+#define BOOST_ASSIGN_MAX_PARAMS 7
+#include <boost/assign.hpp>
+#include <boost/assign/ptr_list_of.hpp>
+#include <boost/assign/ptr_list_inserter.hpp>
+#include <boost/foreach.hpp>
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "sf_windows.h"
+#include "exception.h"
+
+
+
+#define THROW_IFERR(hres) \
+  if (FAILED(hres)) { throw sf::win32_error_exception(hres); }
+
+#ifndef HINST_THISCOMPONENT
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;
+#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
+#endif
+using namespace std;
+
+namespace sf 
+{
+  template <typename ProcType> 
+  LRESULT base_win32_window<ProcType>::window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)
+  {
+
+    switch (message)
+    {
+    case WM_NCCREATE:
+      return on_nccreate(reinterpret_cast<CREATESTRUCT*>(lParam));
+    case WM_CREATE:
+      return on_create(reinterpret_cast<CREATESTRUCT*>(lParam));
+    case WM_INITDIALOG:
+      return on_init_dialog(reinterpret_cast<HWND>(wParam),lParam);
+    case WM_SIZE:
+      return on_size(wParam,LOWORD(lParam),HIWORD(lParam)) ;
+    case WM_PAINT:
+      return on_paint();
+    case WM_DISPLAYCHANGE:
+      return on_display_change(wParam,LOWORD(lParam),HIWORD(lParam));
+    case WM_ERASEBKGND:
+      return on_erase_backgroud(reinterpret_cast<HDC>(wParam));
+    case WM_HSCROLL:
+      return on_hscroll(LOWORD(wParam),HIWORD(wParam),reinterpret_cast<HWND>(lParam));
+    case WM_VSCROLL:
+      return on_vscroll(LOWORD(wParam),HIWORD(wParam),reinterpret_cast<HWND>(lParam));
+    case WM_LBUTTONDOWN:
+      return on_left_mouse_button_down(
+        wParam,dpi_.scale_x(
+          GET_X_LPARAM(lParam)),dpi_.scale_y(GET_Y_LPARAM(lParam)))
+          ;
+      ;
+    case WM_LBUTTONUP:
+      return on_left_mouse_button_up(
+        wParam,dpi_.scale_x(
+          GET_X_LPARAM(lParam)),dpi_.scale_y(GET_Y_LPARAM(lParam)))
+          ;
+    case WM_LBUTTONDBLCLK:
+      return on_left_mouse_button_double_click(wParam,
+        dpi_.scale_x(
+          GET_X_LPARAM(lParam)),dpi_.scale_y(GET_Y_LPARAM(lParam)))
+          ;
+    case WM_MOUSEMOVE:
+      {
+         return on_mouse_move(wParam,
+        dpi_.scale_x(
+          GET_X_LPARAM(lParam)),dpi_.scale_y(GET_Y_LPARAM(lParam)))
+          ;
+        //                                     on_mouse_move(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam),wParam); 
+      }
+    case WM_MOUSEWHEEL:
+      return on_mouse_wheel(GET_KEYSTATE_WPARAM(wParam),GET_WHEEL_DELTA_WPARAM(wParam),
+        dpi_.scale_x(
+          GET_X_LPARAM(lParam)),dpi_.scale_y(GET_Y_LPARAM(lParam)))
+          ;
+    case WM_MOUSELEAVE:
+      return on_mouse_leave() ;
+    case WM_KEYDOWN:
+      return on_key_down(wParam,lParam & 0xffff0000,LOWORD(lParam)) ;
+    case WM_KEYUP:
+      return on_key_up(wParam,lParam & 0xffff0000,LOWORD(lParam)) ;
+    case WM_APPCOMMAND:
+      return on_app_command(GET_APPCOMMAND_LPARAM(lParam),GET_DEVICE_LPARAM(lParam),GET_KEYSTATE_LPARAM(lParam));
+    case WM_COMMAND:
+      return on_command(wParam,lParam);
+    case WM_DESTROY:
+      return on_destroy();
+    case WM_CLOSE:
+      return on_close();
+    case WM_TIMER:
+      return on_timer(wParam);
+    case WM_NOTIFY:
+      return on_notify(reinterpret_cast<NMHDR*>(lParam));
+    }
+
+    // 他のWindowメッセージを派生クラス側でフックできるようにする
+    return other_window_proc(hwnd,message,wParam,lParam);
+
+  };
+  
+   template <typename ProcType> 
+  void base_win32_window<ProcType>::register_class (
+    const wchar_t * menu_name,
+    uint32_t        style ,
+    int32_t     cbClsExtra,
+    int32_t   cbWndExtra,
+    HICON       hIcon ,
+    HCURSOR     hCursor,
+    HBRUSH      hbrBackground ,
+    HICON       hIconSm
+    )          
+  {
+    wnd_class_.reset(new sf::window_class_ex(menu_name,name_,HINST_THISCOMPONENT,thunk_proc_,style,cbClsExtra,cbWndExtra,hIcon,hCursor,hbrBackground,hIconSm));
+  }
+
+  /** デフォルト設定 */
+  template <typename ProcType> 
+  void base_win32_window<ProcType>::register_class()
+  {
+    wnd_class_.reset(new sf::window_class_ex(0,name_,HINST_THISCOMPONENT,thunk_proc_));
+  }
+
+  template <typename ProcType> 
+  void base_win32_window<ProcType>::create_window()
+  {
+    // Create the application window.
+    //
+    // Because the CreateWindow function takes its size in pixels, we
+    // obtain the system DPI and use it to scale the window size.
+    //FLOAT dpiX, dpiY;
+    //factory_->GetDesktopDpi(&dpiX, &dpiY);
+
+
+    // Windowを作成する
+    CreateWindow(
+      name_.c_str(),
+      title_.c_str(),
+      WS_OVERLAPPEDWINDOW,
+      CW_USEDEFAULT,
+      CW_USEDEFAULT,
+      static_cast<uint32_t>(dpi_.scale_x(width_)),
+      static_cast<uint32_t>(dpi_.scale_y(height_)),
+      NULL,
+      NULL,
+      HINST_THISCOMPONENT,
+      this
+      );
+    ::GetWindowPlacement(hwnd_,&wp_);
+  }
+
+  //void base_win32_window::show() 
+  //{
+  //  //HRESULT hr = S_OK;
+  //  //BOOL enable;
+  //  //DwmIsCompositionEnabled (&enable);
+  //  //if(enable){
+  //  //   //Create and populate the BlurBehind structre
+  //  //   DWM_BLURBEHIND bb = {0};
+  //  //   //Enable Blur Behind and Blur Region;
+  //  //   bb.dwFlags = DWM_BB_ENABLE;
+  //  //   bb.fEnable = true;
+  //  //   bb.hRgnBlur = NULL;
+
+  //  //   //Enable Blur Behind
+  //  //   hr = DwmEnableBlurBehindWindow(hwnd_, &bb);
+  //  //}
+  //  ::ShowWindow(hwnd_,SW_SHOW);
+  //  ::GetWindowPlacement(&wp_);
+  //}
+
+
+  template <typename ProcType> 
+  void base_win32_window<ProcType>::update() {::UpdateWindow(hwnd_);}
+
+  template <typename ProcType> 
+  base_win32_window<ProcType>::~base_win32_window()
+  {
+
+  }
+
+  template <typename ProcType> 
+  base_win32_window<ProcType>::base_win32_window(const std::wstring& title,const std::wstring& name,bool fit_to_display,float width,float height)
+    : title_(title),name_(name),fit_to_display_(fit_to_display),width_(width),height_(height),thunk_(this,base_win32_window::WndProc),hwnd_(0)
+  {
+    memset(&wp_,0,sizeof(wp_));
+    wp_.length = sizeof(WINDOWPLACEMENT);
+    thunk_proc_ = (WNDPROC)thunk_.getCode();
+    //create_device_independent_resources();
+  }
+
+  template struct base_win32_window<WNDPROC>;
+  template struct base_win32_window<DLGPROC>;
+
+  //ID2D1FactoryPtr base_win32_window::factory() { return impl_->factory();};
+  //ID2D1HwndRenderTargetPtr base_win32_window::render_target() { return impl_->render_target();};
+  //IDWriteFactoryPtr base_win32_window::write_factory() {return impl_->write_factory();};
+
+  subclass_window::subclass_window(HWND hwnd) 
+    : base_win32_window (
+      std::wstring(L""),std::wstring(L""),false,0,0
+    ),is_subclassed_(false)
+  {
+    attach(hwnd);
+  }
+
+  subclass_window::subclass_window()
+    : base_win32_window (
+      std::wstring(L""),std::wstring(L""),false,0,0
+    ),is_subclassed_(false)
+  {
+
+  }
+
+  subclass_window::~subclass_window()
+  {
+    detatch();
+  }
+
+  void subclass_window::attach(HWND hwnd)
+  {
+    if(is_subclassed_)
+      detatch();
+
+    hwnd_ = hwnd;
+    proc_backup_ = reinterpret_cast<WNDPROC>(::GetWindowLongPtrW(hwnd_,GWLP_WNDPROC));
+    SetWindowLongPtrW(hwnd_,GWLP_WNDPROC,reinterpret_cast<LONG_PTR>(thunk_proc_));
+    is_subclassed_ = true;
+  }
+
+  void subclass_window::detatch()
+  {
+    if(is_subclassed_)
+    {
+      SetWindowLongPtrW(hwnd_,GWLP_WNDPROC,reinterpret_cast<LONG_PTR>(proc_backup_));
+      is_subclassed_ = false;
+    }
+  }
+}
+
diff --git a/wasapi2/sf_windows.h b/wasapi2/sf_windows.h
new file mode 100644 (file)
index 0000000..71351d5
--- /dev/null
@@ -0,0 +1,571 @@
+#pragma once\r
+/*\r
+*/\r
+// Windows Header Files:\r
+#include "exception.h"\r
+#include "base_window.h"\r
+#include "dpi.h"\r
+#define XBYAK64\r
+#include "xbyak.h"\r
+#include "windows.h"\r
+#include "windowsx.h"\r
+#include "CommCtrl.h"\r
+#include <type_traits>\r
+//#include <boost/type_traits/is_same.hpp>\r
+// DLLのリンク\r
+#pragma comment(lib,"d2d1.lib")\r
+#pragma comment(lib,"winmm.lib")\r
+#pragma comment(lib,"dwrite.lib")\r
+#pragma comment(lib,"dwmapi.lib")\r
+\r
+//#include "input.h"\r
+\r
+// Direct Write\r
+\r
+_COM_SMARTPTR_TYPEDEF(IDWriteFactory , __uuidof(IDWriteFactory));\r
+_COM_SMARTPTR_TYPEDEF(IDWriteGdiInterop , __uuidof(IDWriteGdiInterop));\r
+_COM_SMARTPTR_TYPEDEF(IDWriteFontFace , __uuidof(IDWriteFontFace));\r
+_COM_SMARTPTR_TYPEDEF(IDWriteFont , __uuidof(IDWriteFont));\r
+_COM_SMARTPTR_TYPEDEF(IDWriteFontFamily , __uuidof(IDWriteFontFamily));\r
+_COM_SMARTPTR_TYPEDEF(IDWriteFontCollection , __uuidof(IDWriteFontCollection));\r
+_COM_SMARTPTR_TYPEDEF(IDWriteLocalizedStrings , __uuidof(IDWriteLocalizedStrings));\r
+_COM_SMARTPTR_TYPEDEF(IDWriteTextFormat, __uuidof(IDWriteTextFormat));\r
+_COM_SMARTPTR_TYPEDEF(IDWriteTextLayout, __uuidof(IDWriteTextLayout));\r
+_COM_SMARTPTR_TYPEDEF(IDWriteFontFile,__uuidof(IDWriteTextLayout));\r
+//_COM_SMARTPTR_TYPEDEF(IDWriteFontFile,__uuidof(IDWriteTextLayout));\r
+\r
+// Direct2D\r
+\r
+_COM_SMARTPTR_TYPEDEF(ID2D1Factory,__uuidof(ID2D1Factory));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1HwndRenderTarget , __uuidof(ID2D1HwndRenderTarget));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1BitmapRenderTarget , __uuidof(ID2D1BitmapRenderTarget));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1GdiInteropRenderTarget , __uuidof(ID2D1GdiInteropRenderTarget));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1DCRenderTarget , __uuidof(ID2D1DCRenderTarget));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1PathGeometry , __uuidof(ID2D1PathGeometry));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1LinearGradientBrush , __uuidof(ID2D1LinearGradientBrush));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1GradientStopCollection , __uuidof(ID2D1GradientStopCollection));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1SolidColorBrush , __uuidof(ID2D1SolidColorBrush));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1BitmapBrush , __uuidof(ID2D1BitmapBrush));\r
+_COM_SMARTPTR_TYPEDEF(ID2D1Bitmap , __uuidof(ID2D1Bitmap));\r
+\r
+// WIC\r
+\r
+_COM_SMARTPTR_TYPEDEF(IWICImagingFactory, __uuidof(IWICImagingFactory));\r
+_COM_SMARTPTR_TYPEDEF(IWICBitmapDecoder,__uuidof(IWICBitmapDecoder));\r
+_COM_SMARTPTR_TYPEDEF(IWICBitmapFrameDecode,__uuidof(IWICBitmapFrameDecode));\r
+_COM_SMARTPTR_TYPEDEF(IWICStream,__uuidof(IWICStream));\r
+_COM_SMARTPTR_TYPEDEF(IWICFormatConverter,__uuidof(IWICFormatConverter));\r
+_COM_SMARTPTR_TYPEDEF(IWICBitmapScaler,__uuidof(IWICBitmapScaler));\r
+_COM_SMARTPTR_TYPEDEF(ITaskbarList3,__uuidof(ITaskbarList3));\r
+\r
+// DXGI \r
+\r
+_COM_SMARTPTR_TYPEDEF(IDXGISwapChain,__uuidof(IDXGISwapChain));\r
+_COM_SMARTPTR_TYPEDEF(IDXGIFactory1,__uuidof(IDXGIFactory1));\r
+_COM_SMARTPTR_TYPEDEF(IDXGIAdapter1,__uuidof(IDXGIAdapter1));\r
+_COM_SMARTPTR_TYPEDEF(IDXGIDevice1,__uuidof(IDXGIDevice1));\r
+_COM_SMARTPTR_TYPEDEF(IDXGIKeyedMutex,__uuidof(IDXGIKeyedMutex));\r
+_COM_SMARTPTR_TYPEDEF(IDXGIObject,__uuidof(IDXGIObject));\r
+_COM_SMARTPTR_TYPEDEF(IDXGIDeviceSubObject,__uuidof(IDXGIDeviceSubObject));\r
+_COM_SMARTPTR_TYPEDEF(IDXGISurface1,__uuidof(IDXGISurface1));\r
+_COM_SMARTPTR_TYPEDEF(IDXGIOutput,__uuidof(IDXGIOutput));\r
+//_COM_SMARTPTR_TYPEDEF(IDXGI,__uuidof(IDXGI));\r
+//_COM_SMARTPTR_TYPEDEF(IDXGI,__uuidof(IDXGI));\r
+\r
+// Direct3D\r
+\r
+_COM_SMARTPTR_TYPEDEF(ID3D11Device,__uuidof(ID3D11Device));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11DeviceContext,__uuidof(ID3D11DeviceContext));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11RenderTargetView,__uuidof(ID3D11RenderTargetView));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11DepthStencilView,__uuidof(ID3D11DepthStencilView));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11VertexShader,__uuidof(ID3D11VertexShader));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11PixelShader,__uuidof(ID3D11PixelShader));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11InputLayout,__uuidof(ID3D11InputLayout));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11Buffer,__uuidof(ID3D11Buffer));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11Texture2D,__uuidof(ID3D11Texture2D));\r
+_COM_SMARTPTR_TYPEDEF(ID3DBlob,__uuidof(ID3DBlob));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11ShaderResourceView,__uuidof(ID3D11ShaderResourceView));\r
+_COM_SMARTPTR_TYPEDEF(ID3D11SamplerState,__uuidof(ID3D11SamplerState));\r
+\r
+\r
+\r
+namespace sf{\r
+\r
+ /* inline template <class Exc = win32_error_exception> void throw_if_err<>()(HRESULT hr)\r
+  {\r
+    if(hr != S_OK){throw Exc(hr);}\r
+  };*/\r
+\r
+\r
+  ID2D1BitmapPtr load_bitmap_from_file(\r
+    ID2D1HwndRenderTargetPtr render_target,\r
+    IWICImagingFactoryPtr wic_factory,\r
+    std::wstring uri,\r
+    uint32_t destination_width = 0,\r
+    uint32_t destination_height = 0\r
+    );\r
+\r
+  /** WNDCLASSEXラッパクラス */\r
+  struct window_class_ex\r
+  {\r
+    window_class_ex(\r
+      const wchar_t*  menu_name ,\r
+      const std::wstring&  class_name ,\r
+      HINSTANCE   hInstance = NULL,\r
+      WNDPROC     lpfnWndProc = ::DefWindowProcW,\r
+      uint32_t        style = CS_HREDRAW | CS_VREDRAW,\r
+      int32_t     cbClsExtra  = 0,\r
+      int32_t     cbWndExtra = sizeof(LONG_PTR), \r
+      HICON       hIcon = ::LoadIcon(NULL,IDI_APPLICATION),\r
+      HCURSOR     hCursor = ::LoadCursor(NULL, IDC_ARROW),\r
+      HBRUSH      hbrBackground = ::CreateSolidBrush(0xff000000),\r
+      HICON       hIconSm = NULL\r
+      ) : is_register_(false)\r
+    {\r
+\r
+      if(::GetClassInfoExW(hInstance,class_name.c_str(),&wndclass_) == 0)\r
+      {\r
+        if(::GetLastError() == ERROR_CLASS_DOES_NOT_EXIST)\r
+        { \r
+          ::ZeroMemory(&wndclass_,sizeof(wndclass_));\r
+          wndclass_.lpszMenuName = (LPCWSTR)menu_name;\r
+          wndclass_.lpszClassName = class_name.c_str();\r
+          wndclass_.cbSize = sizeof(::WNDCLASSEXW);\r
+          wndclass_.cbWndExtra = cbWndExtra;\r
+          wndclass_.hInstance = hInstance;\r
+          wndclass_.lpfnWndProc = lpfnWndProc;\r
+          wndclass_.style = style;\r
+          wndclass_.cbClsExtra = cbClsExtra;\r
+          wndclass_.hIcon = hIcon;\r
+          wndclass_.hCursor = hCursor;\r
+          wndclass_.hbrBackground = hbrBackground;\r
+          wndclass_.hIconSm = hIconSm;\r
+          atom_ = ::RegisterClassExW(&wndclass_) ;\r
+          BOOST_ASSERT(atom_ != 0);\r
+          is_register_ = true;\r
+        } else {\r
+          throw win32_error_exception();\r
+        }\r
+      } else {\r
+        is_register_ = false;\r
+      }\r
+    };\r
+\r
+    ~window_class_ex()\r
+    {\r
+      if(is_register_){\r
+        ::UnregisterClassW(wndclass_.lpszClassName,wndclass_.hInstance);\r
+      }\r
+    }\r
+\r
+  private:\r
+    bool is_register_;\r
+    ATOM atom_;\r
+    ::WNDCLASSEXW wndclass_;\r
+  };\r
+\r
+  struct get_dc {\r
+    get_dc(HWND hwnd) : hwnd_(hwnd),hdc_(GetDC(hwnd)) {}\r
+    HDC get(){return hdc_;}\r
+    ~get_dc(){::ReleaseDC(hwnd_,hdc_);}\r
+  private:\r
+    HDC hdc_;\r
+    HWND hwnd_;\r
+  };\r
+\r
+  struct compatible_dc {\r
+    compatible_dc(HDC hdc) : hdc_(::CreateCompatibleDC(hdc)){}; \r
+    ~compatible_dc(){::DeleteDC(hdc_);};\r
+    HDC get() { return hdc_;};\r
+  private:\r
+    HDC hdc_;\r
+  };\r
+\r
+  struct ref_dc {\r
+    ref_dc(HDC& hdc) : hdc_(hdc) {};\r
+    ~ref_dc(){};\r
+    HDC get() { return hdc_;};\r
+  private:\r
+    HDC& hdc_;\r
+  };\r
+\r
+  struct d2_dc {\r
+    d2_dc(ID2D1GdiInteropRenderTargetPtr& ptr,D2D1_DC_INITIALIZE_MODE mode) :hdc_(0),ptr_(ptr)\r
+    {\r
+      hr_ = ptr->GetDC(mode,&hdc_);\r
+    };\r
+    ~d2_dc(){ptr_->ReleaseDC(NULL);};\r
+    HDC get() { return hdc_;};\r
+  private:\r
+    HRESULT hr_;\r
+    HDC hdc_;\r
+    ID2D1GdiInteropRenderTargetPtr& ptr_;\r
+  };\r
+\r
+  template <typename Holder>\r
+  struct device_context\r
+  {\r
+    explicit device_context(Holder* holder) : holder_(holder){};\r
+    ~device_context() {}\r
+    operator HDC(){return holder_->get();}\r
+  private:\r
+    std::unique_ptr<Holder> holder_;\r
+  };\r
+\r
+  //struct handle_holder : boost::noncopyable\r
+  //{\r
+  //  explicit handle_holder(HANDLE handle) : handle_(handle) {};\r
+  //  ~handle_holder(){if(handle_) ::CloseHandle(handle_);}\r
+  //  operator HANDLE(){return handle_;}\r
+  //private:\r
+  //  HANDLE handle_;\r
+  //};\r
+\r
+\r
+  struct HBITMAP_deleter {\r
+    typedef HBITMAP pointer;\r
+    void operator ()(HBITMAP handle) {\r
+        if (handle) {\r
+           ::DeleteObject(handle);\r
+        }\r
+    }\r
+  };\r
+\r
+  //template <typename Handle,typename Handle_Deleter>\r
+  //struct handle_holder {\r
+  //  typedef boost::unique_ptr<Handle,Handle_Deleter> holder_type;\r
+  //  handle_holder(Handle handle) : holder_(handle) {}\r
+  //  operator Handle(){return holder_->get();}\r
+  //private:\r
+  //  holder_type holder_;\r
+  //};\r
+\r
+  typedef std::unique_ptr<HBITMAP,HBITMAP_deleter> bitmap_holder;\r
+\r
+  typedef device_context<d2_dc> d2_dc_type;\r
+\r
+  struct paint_struct \r
+  {\r
+    paint_struct(HWND hwnd) : hwnd_(hwnd)\r
+    {\r
+      ::BeginPaint(hwnd,&paintstruct_);\r
+    }\r
+    ~paint_struct() {::EndPaint(hwnd_,&paintstruct_);}\r
+    PAINTSTRUCT* operator->(){return &paintstruct_;}\r
+  private:\r
+    HWND hwnd_;\r
+    PAINTSTRUCT paintstruct_;\r
+  };\r
+\r
+  // GDI オブジェクト管理テンプレート\r
+  template <class GdiObject> \r
+    struct gdi_object: boost::noncopyable\r
+  {\r
+    explicit gdi_object(GdiObject obj) : gdiobj_(obj) {}\r
+    ~gdi_object(){::DeleteObject(gdiobj_);}\r
+    operator GdiObject(){return gdiobj_;}\r
+  private:\r
+    GdiObject gdiobj_;\r
+  };\r
+\r
+  //\r
+  struct select_object \r
+  {\r
+    select_object(HDC dc,HGDIOBJ o) : dc_(dc),o_(::SelectObject(dc,o)) {}\r
+    ~select_object(){::SelectObject(dc_,o_);}\r
+  private:\r
+    HDC dc_;\r
+    HGDIOBJ o_;\r
+  };\r
+  \r
+  // Direct2D BeginDrawヘルパ関数\r
+  template <typename T >\r
+  struct begin_draw\r
+  {\r
+    typedef std::function<void(HRESULT hr)> err_handler_type;\r
+\r
+    begin_draw(T& render_target,err_handler_type& handler)\r
+      : render_target_(render_target) ,\r
+        is_end_(false),handler_(handler)\r
+    {render_target->BeginDraw();}\r
+\r
+    ~begin_draw(){ \r
+      HRESULT hr = S_OK;\r
+      hr = render_target_->EndDraw();\r
+      if( hr != S_OK)\r
+      {\r
+        handler_(hr);\r
+      }\r
+    }\r
+  private:\r
+    T& render_target_;\r
+    err_handler_type handler_;\r
+  };\r
+\r
+  struct mouse\r
+  {\r
+    mouse() : x_(0.0f),y_(0.0f),left_button_(false),middle_button_(false),right_button_(false){}\r
+  private:\r
+    float x_,y_;\r
+    bool left_button_,middle_button_,right_button_;\r
+  };\r
+\r
+  // 普通はDefWindowProcW\r
+  template <typename ProcType>\r
+  inline LRESULT def_wnd_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)\r
+  {\r
+    return ::DefWindowProcW(hwnd,message,wParam,lParam);\r
+  };\r
+\r
+  // DLFPROCはTRUEを返す。\r
+  template <>\r
+  inline LRESULT def_wnd_proc<DLGPROC>(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)\r
+  {\r
+    return FALSE;\r
+  };\r
+\r
+  /** window ベースクラス */\r
+  template <typename ProcType = WNDPROC>\r
+  struct base_win32_window : public base_window \r
+  {\r
+    typedef ProcType proc_t;\r
+\r
+    operator HWND() const {return hwnd_;};\r
+    \r
+    virtual void * raw_handle() const {return hwnd_;};\r
+//    virtual void show(uint32_t show_flag);\r
+\r
+    virtual void show() {\r
+      ::ShowWindow(hwnd_,SW_SHOW);\r
+      ::GetWindowPlacement(hwnd_,&wp_);\r
+    }\r
+\r
+    // Window を画面から隠す\r
+    virtual bool is_show() {\r
+      return ( wp_.showCmd == SW_SHOWMAXIMIZED \r
+        || wp_.showCmd == SW_SHOWMINIMIZED\r
+        || wp_.showCmd == SW_SHOWNORMAL );\r
+    };\r
+\r
+    //\r
+    virtual void hide()\r
+    {\r
+      ::ShowWindow(hwnd_,SW_HIDE);\r
+      ::GetWindowPlacement(hwnd_,&wp_);\r
+    };\r
+\r
+    virtual void text(std::wstring& text)\r
+    {\r
+      ::SetWindowTextW(*this,text.c_str());\r
+    };\r
+\r
+    virtual void send_message(uint32_t message,uint32_t wparam,uint32_t lparam )\r
+    {\r
+      ::SendNotifyMessage(hwnd_,message,wparam,lparam);\r
+    }\r
+\r
+    virtual void post_message(uint32_t message,uint32_t wparam,uint32_t lparam )\r
+    {\r
+      ::PostMessage(hwnd_,message,wparam,lparam);\r
+    }\r
+\r
+    virtual void message_box(const std::wstring& text,const std::wstring& caption,uint32_t type = MB_OK)\r
+    {\r
+      ::MessageBox(hwnd_,text.c_str(),caption.c_str(),type);\r
+    }\r
+\r
+    \r
+    virtual void update();\r
+\r
+  protected:\r
+    \r
+    base_win32_window(\r
+      const std::wstring& title,\r
+      const std::wstring& name,bool fit_to_display,\r
+      float width,float height);\r
+\r
+   \r
+    ~base_win32_window();\r
+\r
+    void register_class (\r
+      const wchar_t* menu_name,\r
+      uint32_t style, \r
+      int32_t     cbClsExtra  = 0,\r
+      int32_t     cbWndExtra  = sizeof(LONG_PTR),\r
+      HICON       hIcon = ::LoadIcon(NULL,IDI_APPLICATION),\r
+      HCURSOR     hCursor = ::LoadCursor(NULL, IDC_ARROW),\r
+      HBRUSH      hbrBackground = ::CreateSolidBrush(0xff000000),\r
+      HICON       hIconSm = NULL\r
+      );               \r
+\r
+    /** デフォルト設定 */\r
+    void register_class();\r
+    void create_window();\r
+  public:\r
+    // SetWindowLong API\r
+    void set_long(int index,long data)\r
+    {\r
+      SetLastError(0);\r
+      if(::SetWindowLongW(hwnd_,index,data) == 0)\r
+      {\r
+        long err = 0;\r
+        if( (err = GetLastError()) != 0){\r
+          SetLastError(err);\r
+          throw sf::win32_error_exception();\r
+        }\r
+      };\r
+    }\r
+\r
+    void set_pos(\r
+      HWND hwnd_insert_after,  // 配置順序のハンドル\r
+      int x,                 // 横方向の位置\r
+      int y,                 // 縦方向の位置\r
+      int cx,                // 幅\r
+      int cy,                // 高さ\r
+      UINT flags            // ウィンドウ位置のオプション\r
+      )\r
+    {\r
+      BOOL res = SetWindowPos(hwnd_,hwnd_insert_after,x,y,cx,cy,flags);\r
+      if(!res)\r
+      {\r
+        throw win32_error_exception();\r
+      }\r
+    }\r
+\r
+    bool invalidate_rect(bool erase = false,const RECT * rect_ptr = 0)\r
+    {\r
+      return ::InvalidateRect(*this,rect_ptr,erase) == TRUE;\r
+    }\r
+\r
+    void enable_control(uint32_t id,bool enable)\r
+    {\r
+      ::EnableWindow(GetDlgItem(hwnd_,id),enable?TRUE:FALSE);\r
+    }\r
+\r
+    void enable_control(HWND hwnd,uint32_t id,bool enable)\r
+    {\r
+      ::EnableWindow(GetDlgItem(hwnd,id),enable?TRUE:FALSE);\r
+    };\r
+\r
+    virtual LRESULT window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam);\r
+    virtual LRESULT other_window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)\r
+    {\r
+      return def_wnd_proc<ProcType>(hwnd,message,wParam,lParam);\r
+    };\r
+    \r
+    // デフォルトウィンドウメッセージハンドラ\r
+    virtual LRESULT on_nccreate(CREATESTRUCT *p) { return std::is_same<proc_t,WNDPROC>::value?1:FALSE;}\r
+    virtual LRESULT on_create(CREATESTRUCT *p) { return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    virtual LRESULT on_init_dialog(HWND default_focus_ctrl,LPARAM data) {return TRUE;}\r
+    virtual LRESULT on_size(uint32_t flag,uint32_t width,uint32_t height) {return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    //virtual LRESULT \r
+    virtual LRESULT on_paint() {return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    virtual LRESULT on_display_change(uint32_t bpp,uint32_t h_resolution,uint32_t v_resolution) { return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    virtual LRESULT on_erase_backgroud(HDC dc) {return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    virtual LRESULT on_hscroll(uint32_t state,uint32_t position,HWND ctrl_hwnd) {return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    virtual LRESULT on_vscroll(uint32_t state,uint32_t position,HWND ctrl_hwnd) {return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    virtual LRESULT on_left_mouse_button_down(uint32_t mouse_key,int x,int y ) { return std::is_same<proc_t,WNDPROC>::value?0:FALSE; }\r
+    virtual LRESULT on_left_mouse_button_up(uint32_t mouse_key,int x,int y) { return std::is_same<proc_t,WNDPROC>::value?0:FALSE; }\r
+    virtual LRESULT on_left_mouse_button_double_click(uint32_t mouse_key,int x,int y) { return std::is_same<proc_t,WNDPROC>::value?0:FALSE; }\r
+    virtual LRESULT on_mouse_move(uint32_t mouse_key,int x,int y) {return std::is_same<proc_t,WNDPROC>::value?0:FALSE; }\r
+    virtual LRESULT on_mouse_wheel(uint32_t mouse_key,int delta,int x,int y) {  return std::is_same<proc_t,WNDPROC>::value?0:FALSE; }\r
+    //virtual bool on_mouse_enter(uint32_t mouse_key,int x,int y) {  return false; }\r
+    virtual LRESULT on_mouse_leave() {  return std::is_same<proc_t,WNDPROC>::value?0:FALSE; }\r
+    virtual LRESULT on_destroy(){return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    virtual LRESULT on_close(){return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    virtual LRESULT on_set_cursor() { return std::is_same<proc_t,WNDPROC>::value?0:FALSE; }\r
+    virtual LRESULT on_key_down(uint32_t vkey,uint32_t ext_key,uint32_t repeat) { return std::is_same<proc_t,WNDPROC>::value?0:FALSE; }\r
+    virtual LRESULT on_key_up(uint32_t vkey,uint32_t ext_key,uint32_t repeat) { return std::is_same<proc_t,WNDPROC>::value?0:FALSE; }\r
+    virtual LRESULT on_app_command(uint32_t command,uint32_t device,uint32_t keystate) {return std::is_same<proc_t,WNDPROC>::value?0:FALSE;}\r
+    virtual LRESULT on_command(uint32_t wparam, uint32_t lparam)  { return std::is_same<proc_t,WNDPROC>::value?0:FALSE; } \r
+    virtual LRESULT on_timer(uint32_t timer_id)  { return std::is_same<proc_t,WNDPROC>::value?0:FALSE; } \r
+    virtual LRESULT on_notify(NMHDR* nmhdr)  { return std::is_same<proc_t,WNDPROC>::value?0:FALSE; } \r
+\r
+ protected:\r
+    static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+    {\r
+      base_win32_window* ptr = reinterpret_cast<base_win32_window*>(hwnd);\r
+      hwnd = ptr->hwnd_;\r
+      // TODO: メッセージハンドラを拡張可能にする。\r
+      return ptr->window_proc(hwnd,message,wParam,lParam);\r
+    };\r
+\r
+    // thisとhwndをつなぐthunkクラス\r
+    struct hwnd_this_thunk : public Xbyak::CodeGenerator {\r
+      hwnd_this_thunk(base_win32_window* impl,ProcType proc)\r
+      {\r
+        // rcxにhwndが格納されているので、それをimpl->hwndに保存\r
+//        mov(ptr[&(impl->hwnd_)],rcx); // <-- エラー発生部分\r
+               mov(rax,(size_t)&impl->hwnd_);  // <-- 訂正\r
+        mov(ptr[rax],rcx);                             // <-- 訂正\r
+        // 代わりにthisのアドレスをrcxに格納\r
+        mov(rcx,(LONG_PTR)impl);\r
+        // r10にproc(Window プロシージャ)へのアドレスを格納\r
+        mov(r10,(LONG_PTR)proc);\r
+        // Window プロシージャへへジャンプ\r
+        jmp(r10);\r
+      }\r
+    };\r
+\r
+    HWND hwnd_;\r
+    hwnd_this_thunk thunk_;\r
+    std::wstring title_;\r
+    std::wstring name_;\r
+    float width_,height_;\r
+    bool fit_to_display_;\r
+    std::shared_ptr<sf::window_class_ex> wnd_class_;\r
+    ProcType thunk_proc_;\r
+    dpi dpi_;\r
+    WINDOWPLACEMENT wp_;\r
+   };\r
+  \r
+   typedef base_win32_window<> base_win32_window_t;\r
+   typedef base_win32_window<DLGPROC> base_win32_dialog_t;\r
+\r
+  /// サブクラスウィンドウ\r
+  struct subclass_window : public base_win32_window_t\r
+  {\r
+    subclass_window(HWND hwnd);\r
+    subclass_window();\r
+    void attach(HWND hwnd);\r
+    void detatch();\r
+    ~subclass_window();\r
+    virtual LRESULT window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam) \r
+    {\r
+      return CallWindowProc(proc_backup_,hwnd,message,wParam,lParam);\r
+    };\r
+  protected:\r
+    bool is_subclassed_;\r
+    WNDPROC proc_backup_;\r
+  };\r
+\r
+struct av_mm_thread_characteristics\r
+{\r
+  av_mm_thread_characteristics(std::wstring& str) : task_name_(str)\r
+  {\r
+    handle_ = ::AvSetMmThreadCharacteristicsW(str.c_str(),(LPDWORD)&task_index_);\r
+  }\r
+\r
+  bool set_priority(AVRT_PRIORITY p){return (::AvSetMmThreadPriority(handle_,p) == TRUE);}\r
+\r
+  ~av_mm_thread_characteristics()\r
+  {\r
+    ::AvRevertMmThreadCharacteristics(handle_);\r
+  }\r
+\r
+private:\r
+  std::wstring task_name_;\r
+  uint32_t task_index_;\r
+  HANDLE handle_;\r
+};\r
+\r
+struct widget\r
+{\r
+  void draw();\r
+  float x_,y_;\r
+};\r
+\r
+typedef sf::begin_draw<ID2D1BitmapRenderTargetPtr> begin_draw_bitmap;\r
+typedef sf::begin_draw<ID2D1HwndRenderTargetPtr> begin_draw_hwnd;\r
+  \r
+}
\ No newline at end of file
diff --git a/wasapi2/singleton.h b/wasapi2/singleton.h
new file mode 100644 (file)
index 0000000..0ca7b46
--- /dev/null
@@ -0,0 +1,55 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-7 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+/** @file
+ *  @brief 
+ *  @author S.F. (Satoshi Fujiwara)
+ */
+#include <boost/thread.hpp>
+#include <boost/shared_ptr.hpp>
+namespace sf {
+    template<typename BaseClass,template <class> class PointerType = std::shared_ptr > struct singleton 
+    {
+        typedef PointerType<BaseClass> ptr;
+        friend  BaseClass;
+        static ptr& instance()
+        {
+            boost::call_once(init,flag_);
+            return instance_;
+        };
+
+
+        singleton(){};
+    private:
+        singleton(const singleton& );
+               static void init(){instance_.reset(new BaseClass);};
+        static PointerType<BaseClass> instance_;
+        static boost::once_flag flag_;
+    };
+
+    template<class BaseClass,template <class> class PointerType> boost::once_flag singleton<BaseClass,PointerType>::flag_ = BOOST_ONCE_INIT;
+    template<class BaseClass,template <class> class PointerType> PointerType<BaseClass> singleton<BaseClass,PointerType>::instance_;
+};
+
+
diff --git a/wasapi2/stdafx.cpp b/wasapi2/stdafx.cpp
new file mode 100644 (file)
index 0000000..f685e04
--- /dev/null
@@ -0,0 +1,7 @@
+// stdafx.cpp : 標準インクルードのみを含むソース ファイルです。\r
+// STed2.pch は、プリコンパイル済みヘッダーになります。\r
+//  stdafx.obj にはプリコンパイル型情報が含まれます。\r
+\r
+#include "stdafx.h"\r
+// TODO: このファイルではなく、STDAFX.H で必要な\r
+// 追加ヘッダーを参照してください。\r
diff --git a/wasapi2/stdafx.h b/wasapi2/stdafx.h
new file mode 100644 (file)
index 0000000..f242b4d
--- /dev/null
@@ -0,0 +1,143 @@
+// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、または\r
+// 参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル\r
+// を記述します。\r
+//\r
+\r
+\r
+#pragma once\r
+#include <SDKDDKVer.h>\r
+\r
+#ifndef UNICODE\r
+#define UNICODE\r
+#endif\r
+// STL\r
+\r
+#define DIRECTINPUT_VERSION 0x0800\r
+#define BOOST_ALL_NO_LIB\r
+\r
+#include <stdint.h>\r
+#include <tchar.h>\r
+#include <iostream>\r
+#include <fstream>\r
+#include <exception>\r
+#include <memory>\r
+#include <string>\r
+#include <map>\r
+#include <locale>\r
+#include <fstream>\r
+#include <algorithm>\r
+#include <functional>\r
+#include <thread>\r
+\r
+// Boost\r
+#include <boost/archive/xml_woarchive.hpp>\r
+#include <boost/archive/xml_wiarchive.hpp>\r
+//#include <boost/archive/text_woarchive.hpp>\r
+//#include <boost/archive/text_wiarchive.hpp>\r
+//#include <boost/archive/text_oarchive.hpp>\r
+//#include <boost/archive/text_iarchive.hpp>\r
+//#include <boost/archive/binary_woarchive.hpp>\r
+//#include <boost/archive/binary_wiarchive.hpp>\r
+//#include <boost/archive/binary_oarchive.hpp>\r
+//#include <boost/archive/binary_iarchive.hpp>\r
+\r
+#include <boost/serialization/export.hpp>\r
+//#include <boost/serialization/is_abstract.hpp>\r
+#include <boost/serialization/version.hpp>\r
+#include <boost/serialization/serialization.hpp>\r
+#include <boost/serialization/split_member.hpp>\r
+#include <boost/serialization/string.hpp>\r
+#include <boost/serialization/shared_ptr.hpp>\r
+#include <boost/serialization/vector.hpp>\r
+#include <boost/serialization/nvp.hpp>\r
+#include <boost/serialization/void_cast.hpp>\r
+\r
+#include <boost/scoped_ptr.hpp> \r
+#include <boost/scoped_array.hpp> \r
+#include <boost/shared_ptr.hpp> \r
+#include <boost/shared_array.hpp> \r
+#include <boost/intrusive_ptr.hpp>\r
+#include <boost/format.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+#include <boost/array.hpp>\r
+//#include <boost/thread.hpp>\r
+#include <boost/optional.hpp>\r
+#include <boost/bind.hpp>\r
+#include <boost/function.hpp>\r
+#include <boost/variant.hpp>\r
+#include <boost/any.hpp>\r
+#include <boost/signals2.hpp>\r
+#include <boost/tuple/tuple.hpp>\r
+#include <boost/ptr_container/ptr_container.hpp>\r
+//#include <boost/thread/condition.hpp>\r
+//#include <boost/serialization/ptr_vector.hpp>\r
+#include <boost/ptr_container/ptr_array.hpp>\r
+#include <boost/ptr_container/serialize_ptr_container.hpp>\r
+//#include "serialization.h"\r
+#include <boost/filesystem/path.hpp>\r
+#include <boost/filesystem/operations.hpp>\r
+#include <boost/filesystem/convenience.hpp>\r
+#include <boost/filesystem/fstream.hpp>\r
+#include "sf_com.h"\r
+//#include <d3d10_1.h>\r
+//#include <d3d10.h>\r
+//#include <d3d11.h>\r
+//#include <d3dx10.h>\r
+//#include <d3dx11.h>\r
+#include "dinput.h"\r
+#include <wincodec.h>\r
+#include <windows.h>\r
+#include <windowsx.h>\r
+#include <wincodec.h>\r
+#include <wincodecsdk.h>\r
+\r
+#include <comdef.h>\r
+#include "avrt.h"\r
+#include "mmsystem.h"\r
+\r
+// Direct Input\r
+\r
+#include "dinput.h"\r
+\r
+\r
+// DXGI\r
+\r
+#include "dxgi.h"\r
+\r
+// Direct3D\r
+\r
+#include "d3d11.h"\r
+//#include "d3dx11.h"\r
+//#include <d3dx11effect.h>\r
+//#include <d3dxGlobal.h>\r
+#include <d3dcompiler.h>\r
+#include <DirectXMath.h>\r
+\r
+// Direct2D\r
+\r
+#include <d2d1.h>\r
+#include <d2d1helper.h>\r
+\r
+// Direct Write\r
+\r
+#include <dwrite.h>\r
+\r
+// DWM\r
+\r
+#include "dwmapi.h" \r
+#include "Shobjidl.h"\r
+\r
+#include <wincodec.h>\r
+#include <wincodecsdk.h>\r
+\r
+//#include "exception.h"\r
+//#include "singleton.h"\r
+//#include "code_converter.h"\r
+//#include "logger.h"\r
+\r
+\r
+// TODO: プログラムに必要な追加ヘッダーをここで参照してください。\r
+#include "code_converter.h"\r
+#include "logger.h"\r
+#include "dout.h"\r
+//#include "dxerr.h"\r
diff --git a/wasapi2/tab_dialog.cpp b/wasapi2/tab_dialog.cpp
new file mode 100644 (file)
index 0000000..424b85c
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+==============================================================================
+
+Copyright 2005-11 by Satoshi Fujiwara.
+
+async can be redistributed and/or modified under the terms of the
+GNU General Public License, as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+async is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with async; if not, visit www.gnu.org/licenses or write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+Boston, MA 02111-1307 USA
+
+==============================================================================
+*/
+/* ToDo
+
+TODO: リサイズに対応する
+
+*/
+
+#include "stdafx.h"
+#include "resource.h"
+#define BOOST_ASSIGN_MAX_PARAMS 7
+#include <boost/assign.hpp>
+#include <boost/assign/ptr_list_of.hpp>
+#include <boost/assign/ptr_list_inserter.hpp>
+#include <boost/foreach.hpp>
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "sf_windows.h"
+#include "tab_dialog.h"
+#include "CommDlg.h"
+#include "icon.h"
+#include "timer.h"
+#include "exception.h"
+#include "application.h"
+
+#define THROW_IFERR(hres) \
+  if (FAILED(hres)) { throw sf::win32_error_exception(hres); }
+
+#ifndef HINST_THISCOMPONENT
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;
+#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
+#endif
+
+namespace sf 
+{
+    tab_dialog_base::tab_dialog_base(sf::base_window& parent_window,HWND tab_hwnd,int tab_id,const std::wstring& menu_name,const std::wstring& name,HINSTANCE inst,LPCTSTR temp)
+      : base_win32_dialog_t(menu_name,name,false,0,0),parent_window_(parent_window)
+      ,tab_hwnd_(tab_hwnd),tab_id_(tab_id),inst_(inst),temp_(temp)
+    {
+
+    }
+
+    void tab_dialog_base::create()
+    {
+      hwnd_ =  CreateDialogW(inst_,temp_,(HWND)parent_window_.raw_handle(),thunk_proc_);
+      BOOST_ASSERT(hwnd_ != NULL);
+      if(hwnd_ == NULL)
+      {
+        throw win32_error_exception();
+      }
+
+      resize();
+    }
+
+    void tab_dialog_base::resize()
+    {
+      
+      DWORD dwDlgBase = GetDialogBaseUnits();
+      int cxMargin = LOWORD(dwDlgBase) / 4; 
+      int cyMargin = HIWORD(dwDlgBase) / 8;
+      RECT rci;
+      TabCtrl_GetItemRect(tab_hwnd_,0,&rci);
+      RECT r;
+      GetClientRect(tab_hwnd_,&r);
+      RECT rw;
+      GetWindowRect(tab_hwnd_,&rw);
+      POINT pt = {rw.left,rw.top + rci.bottom};
+      ScreenToClient((HWND)parent_window_.raw_handle(),&pt);
+
+      set_pos(HWND_TOP,
+        pt.x + cxMargin,
+        pt.y + cyMargin,
+        r.right - cxMargin * 2 - 1,
+        r.bottom - rci.bottom - cyMargin * 2 - 1
+        ,SWP_NOZORDER 
+        );
+    }
+}
+
diff --git a/wasapi2/tab_dialog.h b/wasapi2/tab_dialog.h
new file mode 100644 (file)
index 0000000..815d22b
--- /dev/null
@@ -0,0 +1,34 @@
+#pragma once\r
+/*\r
+*/\r
+// Windows Header Files:\r
+#include "sf_windows.h"\r
+#include "icon.h"\r
+#include "base_window.h"\r
+#include "taskbar.h"\r
+\r
+namespace sf\r
+{\r
+\r
+  struct tab_dialog_base;\r
+  typedef std::shared_ptr<tab_dialog_base> tab_dialog_ptr;\r
+\r
+  /** toplevel ウィンドウクラス */\r
+  /* このクラスは、create_tab_dialog 関数からのみ生成可能 */\r
+  struct tab_dialog_base : public base_win32_dialog_t\r
+  {\r
+    tab_dialog_base(sf::base_window& parent_window,HWND tab_hwnd,int tab_id,const std::wstring& menu_name,const std::wstring& name,HINSTANCE inst,LPCTSTR temp);\r
+    virtual ~tab_dialog_base(){};\r
+    virtual void create() ;\r
+    virtual void enable() = 0;\r
+    virtual void disable() = 0;\r
+    virtual void resize();\r
+  private:\r
+\r
+    base_window& parent_window_;\r
+    HWND tab_hwnd_;\r
+    int tab_id_;\r
+    HINSTANCE inst_;\r
+    LPCTSTR temp_;\r
+  };\r
+}
\ No newline at end of file
diff --git a/wasapi2/taskbar.cpp b/wasapi2/taskbar.cpp
new file mode 100644 (file)
index 0000000..175e7c9
--- /dev/null
@@ -0,0 +1,98 @@
+#include "StdAfx.h"
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "sf_windows.h"
+#include "taskbar.h"
+
+
+namespace sf {
+
+const int taskbar::none = TBPF_NOPROGRESS;
+const int taskbar::indeterminate = TBPF_INDETERMINATE;
+const int taskbar::normal = TBPF_NORMAL;
+const int taskbar::error = TBPF_ERROR;
+const int taskbar::paused = TBPF_PAUSED;
+
+long  taskbar::register_message()
+{
+  return ::RegisterWindowMessage(L"TaskbarButtonCreated");
+}
+
+struct taskbar::impl
+{
+  typedef throw_if_err<sf::taskbar::exception> throw_if_err_;
+
+  impl(){}
+  ~impl()
+  {
+    discard();
+  }
+
+  void create() {
+    throw_if_err_()(taskbar_.CreateInstance(CLSID_TaskbarList));
+  }
+  bool is_create() const 
+  {
+    return (taskbar_ != 0);
+  }
+  void discard()
+  {
+    safe_release(taskbar_);
+  }
+    
+  void overlay_icon(const sf::base_window& w,const sf::icon& ic,const std::wstring& description)
+  {
+    throw_if_err_()(taskbar_->SetOverlayIcon(reinterpret_cast<HWND>(w.raw_handle()),ic.get(),description.c_str()));
+  }
+
+  void progress_state(const sf::base_window& w,TBPFLAG state)
+  {
+    throw_if_err_()(taskbar_->SetProgressState(reinterpret_cast<HWND>(w.raw_handle()),state));
+  }
+
+  void progress_value(const sf::base_window& w,boost::uint64_t completed, boost::uint64_t total)
+  {
+    throw_if_err_()(taskbar_->SetProgressValue(reinterpret_cast<HWND>(w.raw_handle()),completed,total));
+  }
+
+  void add_thumb_buttons(const sf::base_window& w,const std::vector<THUMBBUTTON>& tbs){
+      taskbar_->ThumbBarAddButtons(reinterpret_cast<HWND>(w.raw_handle()),tbs.size(),const_cast<LPTHUMBBUTTON>(&(tbs[0])));
+  };
+
+  void update_thumb_buttons(const sf::base_window& w,const std::vector<THUMBBUTTON>& tbs){
+      taskbar_->ThumbBarUpdateButtons(reinterpret_cast<HWND>(w.raw_handle()),tbs.size(),const_cast<LPTHUMBBUTTON>(&(tbs[0])));
+  };
+
+private:
+  _COM_SMARTPTR_TYPEDEF(ITaskbarList4,__uuidof(ITaskbarList4));
+  ITaskbarList4Ptr taskbar_;
+};
+
+   
+taskbar::taskbar() : impl_(new sf::taskbar::impl()) {}
+taskbar::~taskbar() { discard();};
+
+void taskbar::create(){impl_->create();};
+bool taskbar::is_create() const {return impl_->is_create();};
+void taskbar::discard(){impl_->discard();};
+void taskbar::overlay_icon(const sf::base_window& w,const icon& ic,const std::wstring& description){impl_->overlay_icon(w,ic,description);};
+void taskbar::progress_state(const sf::base_window& w,int state){impl_->progress_state(w,(TBPFLAG)state);};
+void taskbar::progress_value(const sf::base_window& w,boost::uint64_t completed, boost::uint64_t total){impl_->progress_value(w,completed,total);};
+void taskbar::add_thumb_buttons(const sf::base_window& w,const thumb_button_manager& tm){
+  BOOST_ASSERT(!tm.is_added);
+  impl_->add_thumb_buttons(w,tm.thumbbuttons_);
+  tm.is_added = true;
+};
+void taskbar::update_thumb_buttons(const sf::base_window& w,const thumb_button_manager& tm){
+  BOOST_ASSERT(tm.is_added);
+  if(tm.is_added){
+    impl_->update_thumb_buttons(w,tm.thumbbuttons_);
+  }
+};
+
+}
\ No newline at end of file
diff --git a/wasapi2/taskbar.h b/wasapi2/taskbar.h
new file mode 100644 (file)
index 0000000..97ccb0d
--- /dev/null
@@ -0,0 +1,161 @@
+#pragma once\r
+\r
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+#include "exception.h"\r
+#include "icon.h"\r
+\r
+namespace sf\r
+{\r
+  \r
+  ///** インターフェース */\r
+  //struct thumb_button : boost::noncopyable\r
+  //{\r
+  //  typedef std::shared_ptr<thumb_button> ptr;\r
+  //  static ptr create_thumb_button();\r
+  //  virtual void show()  = 0;\r
+  //  virtual void hide()  = 0;\r
+  //  virtual void enable() = 0;\r
+  //  virtual void disable() = 0;\r
+  //private:\r
+  //  thumb_button();\r
+  //};\r
+\r
+  struct taskbar;\r
+\r
+  /** サムネイルボタン管理 */\r
+  struct thumb_button_manager\r
+  {\r
+    friend struct taskbar;\r
+    // Thumb Buttonは最大7個まで\r
+    static const int THUMB_BUTTON_MAX = 7;\r
+\r
+    // THUMBBUTTON構造体操作クラス\r
+    struct thumb_button {\r
+\r
+      // コンストラクタ\r
+      thumb_button(uint32_t id ,const icon& i,const std::wstring& tool_tip,THUMBBUTTON& t) : thumb_(t)\r
+      {\r
+        BOOST_ASSERT(tool_tip.size() < 259);\r
+        memset(&thumb_,0,sizeof(THUMBBUTTON));\r
+        thumb_.dwMask = THB_ICON | THB_TOOLTIP | THB_FLAGS;\r
+        thumb_.hIcon = i.get();\r
+        thumb_.iId = id;\r
+        std::copy(tool_tip.begin(),tool_tip.end(),thumb_.szTip);\r
+        //thumb_.szTip = const_cast<wchar_t*>(tool_tip_.c_str());\r
+      }\r
+      \r
+      // 今回はプロパティ・チェイニングなアクセス方法にしてみた。\r
+      /** アイコン */\r
+      thumb_button& set_icon(icon& ic) {thumb_.hIcon = ic.get(); return *this;};\r
+      /** IDのセット */\r
+      thumb_button& id(uint32_t v) {thumb_.iId = v; return *this;}\r
+      /** ツールチップ */\r
+      thumb_button& tool_tip(const std::wstring& v) {\r
+        BOOST_ASSERT(v.size() < 259);\r
+        std::copy(v.begin(),v.end(),thumb_.szTip);\r
+        thumb_.szTip[v.size()] = L'\0';\r
+        return *this;\r
+      }\r
+      /** 有効化・無効化 */\r
+      thumb_button& enable(bool v){v?(thumb_.dwFlags &= ~THBF_ENABLED):(thumb_.dwFlags |= THBF_DISABLED); return *this;}\r
+      /** クリックされたらサムネイルを閉じるか */\r
+      thumb_button& dismission_click(bool v){ v?(thumb_.dwFlags |= THBF_DISMISSONCLICK):(thumb_.dwFlags &= ~THBF_DISMISSONCLICK); return *this;}\r
+      /** ボタンの外枠を描画するかどうか */\r
+      thumb_button& no_background(bool v){v?(thumb_.dwFlags |= THBF_NOBACKGROUND):(thumb_.dwFlags &= ~THBF_NOBACKGROUND);return *this;}\r
+      /** 隠すか・表示するか */\r
+      thumb_button& hidden(bool v){v?(thumb_.dwFlags |= THBF_HIDDEN):(thumb_.dwFlags &= ~ THBF_HIDDEN);return *this;}\r
+      /** ボタンアクションを起こすかどうか。ボタンを通知目的で使用する際に用いる。*/\r
+      thumb_button& no_interacive(bool v){v?(thumb_.dwFlags |= THBF_NONINTERACTIVE):(thumb_.dwFlags &= ~THBF_NONINTERACTIVE);return *this;}\r
+\r
+    private:\r
+      THUMBBUTTON& thumb_;\r
+    };\r
+    \r
+    thumb_button_manager() : is_added(false) {}\r
+\r
+    // Thumb Buttonは7個までに制限されている\r
+    thumb_button&  add_thumb_button(uint32_t id,const icon& i,const std::wstring& str)\r
+    {\r
+      // 事前条件\r
+      BOOST_ASSERT(thumb_buttons_.size() < 7 && is_added == false);\r
+      if(!is_added){\r
+        thumbbuttons_.push_back(THUMBBUTTON());\r
+        thumb_buttons_.push_back(thumb_button(id,i,str, (thumbbuttons_.at(thumbbuttons_.size() - 1))));\r
+      }\r
+      return thumb_buttons_.at(thumb_buttons_.size() - 1);\r
+    }\r
+\r
+    thumb_button& at(uint32_t i){\r
+      BOOST_ASSERT(i < thumb_buttons_.size());\r
+      return thumb_buttons_.at(i);\r
+    }\r
+\r
+    size_t size() const {return thumb_buttons_.size();}\r
+  private:\r
+    mutable bool is_added;\r
+    // メモリ配列を合わせるためにこうした。\r
+    std::vector<THUMBBUTTON> thumbbuttons_;\r
+    std::vector<thumb_button> thumb_buttons_;\r
+    //typedef boost::ptr_vector<thumb_button> thumb_buttons;\r
+  };\r
+\r
+  /** タスクバーAPIのラップクラス。本来であればインターフェースにする方が良いかもしれないけれど */\r
+  struct taskbar : boost::noncopyable\r
+  {\r
+    struct exception\r
+     : public sf::win32_error_exception \r
+    {\r
+      exception(uint32_t hr) : win32_error_exception(hr) {};\r
+      exception() : win32_error_exception() {} ;\r
+    };\r
+\r
+     taskbar();\r
+    ~taskbar();\r
+    void create();\r
+    void discard();\r
+    void overlay_icon(const sf::base_window& w,const icon& ic,const std::wstring& description);\r
+    void progress_state(const sf::base_window& w,int state);\r
+    void progress_value(const sf::base_window& w,boost::uint64_t completed, boost::uint64_t total);\r
+\r
+    void add_thumb_buttons(const sf::base_window& w,const thumb_button_manager& tm);\r
+    void update_thumb_buttons(const sf::base_window& w,const thumb_button_manager& tm);\r
+    bool is_create() const;\r
+\r
+    static long register_message();\r
+\r
+    static const int none;\r
+    static const int indeterminate;\r
+    static const int normal;\r
+    static const int error;\r
+    static const int paused;\r
+\r
+  private:\r
+    struct impl;\r
+    std::shared_ptr<impl> impl_;\r
+    friend struct impl;\r
+  };\r
+\r
+}\r
+\r
diff --git a/wasapi2/thread_base.cpp b/wasapi2/thread_base.cpp
new file mode 100644 (file)
index 0000000..733d6de
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+==============================================================================
+
+This file is part of the async
+Copyright 2005-10 by Satoshi Fujiwara.
+
+async can be redistributed and/or modified under the terms of the
+GNU General Public License, as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+async is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with async; if not, visit www.gnu.org/licenses or write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+Boston, MA 02111-1307 USA
+
+==============================================================================
+*/
+#include "StdAfx.h"
+#include <commctrl.h>
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "message_loop.h"
+#include "sf_com.h"
+#include "dout.h"
+#include "async_reader.h"
+#include "application.h"
+#include "thread_base.h"
+
+using namespace std;
+
+namespace sf {
+
+    void thread_base::init_buffer()
+    {
+      audio_base& out(application::instance()->output_device());
+      ringbuffer_.reset();
+      for(int i = 0,size = buffer_.size();i < size;++i)
+      {
+        buffer_[i].reset(reinterpret_cast<uint8_t*>(_aligned_malloc(sizeof(uint8_t) * out.get_buffer_byte_size(),16)));
+      }
+      index_ = 0;
+    }
+
+}
+
+
diff --git a/wasapi2/thread_base.h b/wasapi2/thread_base.h
new file mode 100644 (file)
index 0000000..6809c3c
--- /dev/null
@@ -0,0 +1,108 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-10 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#include "singleton.h"
+#include "exception.h"
+#include "ring_buffer.h"
+#include "sf_memory.h"
+namespace sf 
+{
+  struct thread_base 
+  {
+    struct wait_exception
+      : public sf::exception 
+    {
+      wait_exception() : exception(L"wait_error") {}
+    };
+
+    thread_base() : event_(::CreateEventEx(NULL, NULL, 0,EVENT_MODIFY_STATE | SYNCHRONIZE))
+    {
+      status_.store(0, std::memory_order_seq_cst);
+    }
+
+    virtual ~thread_base(){};
+
+    void execute()
+    {
+      thread_ = std::thread(boost::bind(&thread_base::thread_main,this));
+    }
+
+    virtual void thread_main() = 0;
+
+    void join ()
+    {
+      if(thread_.joinable())
+      {
+        thread_.join();
+      }
+    }
+    // \8fó\91Ô\82Ì\95Ï\8dX
+    void change_status(int value,std::memory_order o = std::memory_order_seq_cst)
+    {
+      status_.store(value,o);
+      DOUT(L"change_status()" << std::endl);
+    }
+
+    void change_and_wait(int value,int wait_value,std::memory_order o = std::memory_order_seq_cst)
+    {
+      change_status(value,o);
+      PulseEvent(event_.get());
+      wait_status(wait_value);
+    }
+
+    int status(std::memory_order o = std::memory_order_seq_cst)
+    {
+      return status_.load(o);
+    };
+
+    virtual void init_buffer();
+
+    void wait_status(int value,int ms = 1,std::memory_order o = std::memory_order_seq_cst)
+    {
+      DOUT(L"wait_status()" << std::endl);
+      int s;
+      while(s = status_.load(o),s != value)
+      {
+        if(s < STATUS_ERROR)
+        {
+          throw wait_exception();
+        };
+        Sleep(ms);
+      }
+    };
+
+    ringbuffer_t& ringbuffer() {return ringbuffer_;}
+
+    static const int STATUS_ERROR = -1;
+    static const size_t Q_SIZE = 8;
+    static const int WAIT_TIMEOUT_DEFAULT = 100; 
+  protected:
+    std::thread thread_;
+    std::atomic<int> status_;
+    buffer_t buffer_;
+    handle_holder event_;
+    uint32_t index_;
+    ringbuffer_t  ringbuffer_;
+    std::wstring error_;
+  };
+}
diff --git a/wasapi2/timer.cpp b/wasapi2/timer.cpp
new file mode 100644 (file)
index 0000000..a56af47
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+
+#include "StdAfx.h"
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "sf_windows.h"
+#include "timer.h"
+
+namespace sf {
+timer::timer(sf::base_window& window,uint32_t timeout) : window_(window),timeout_(timeout),timer_id_(0)
+{
+
+}
+void timer::start(){
+  if(!::SetTimer(reinterpret_cast<HWND>(window_.raw_handle()),(UINT_PTR)&timer_id_,timeout_,NULL)){
+    throw timer::exception();
+  };
+};
+
+void timer::reader_stop()
+{
+  if(timer_id_)
+  {
+    ::KillTimer(reinterpret_cast<HWND>(window_.raw_handle()),(UINT_PTR)&timer_id_);
+    timer_id_ = 0;
+  }
+};
+
+}
diff --git a/wasapi2/timer.h b/wasapi2/timer.h
new file mode 100644 (file)
index 0000000..7a342d3
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#pragma once
+#include "base_window.h"
+namespace sf{
+struct timer
+{
+  struct exception
+    : public sf::win32_error_exception 
+  {
+    exception(uint32_t hr) : win32_error_exception(hr) {};
+    exception() : win32_error_exception() {} ;
+  };
+
+  timer(sf::base_window& window,uint32_t timeout);
+  void start();
+  void reader_stop();
+  ~timer(){reader_stop();};
+private:
+  sf::base_window& window_;
+  uint32_t timer_id_;
+  uint32_t timeout_;
+};
+}
+
diff --git a/wasapi2/toplevel_window.cpp b/wasapi2/toplevel_window.cpp
new file mode 100644 (file)
index 0000000..58b21fa
--- /dev/null
@@ -0,0 +1,1121 @@
+/*\r
+==============================================================================\r
+\r
+Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+/* ToDo\r
+\r
+TODO: リサイズに対応する\r
+\r
+*/\r
+\r
+#include "stdafx.h"\r
+#include "resource.h"\r
+#define BOOST_ASSIGN_MAX_PARAMS 7\r
+#include <boost/assign.hpp>\r
+#include <boost/assign/ptr_list_of.hpp>\r
+#include <boost/assign/ptr_list_inserter.hpp>\r
+#include <boost/foreach.hpp>\r
+\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+\r
+#include "sf_windows.h"\r
+#include "toplevel_window.h"\r
+#include "CommDlg.h"\r
+#include "icon.h"\r
+#include "timer.h"\r
+#include "exception.h"\r
+#include "application.h"\r
+#include "config_tab_dialog.h"\r
+#include "info_tab_dialog.h"\r
+#include "seq_tab_dialog.h"\r
+\r
+//#pragma comment( lib, "dxguid.lib" )\r
+//#pragma comment( lib, "d3d11.lib" )\r
+//#pragma comment( lib, "d3dx11.lib" )\r
+//#pragma comment( lib, "dxgi.lib" )\r
+//#pragma comment( lib, "d3dx9.lib" )   \r
+#pragma comment( lib, "Shlwapi.lib" ) \r
+\r
+#define THROW_IFERR(hres) \\r
+  if (FAILED(hres)) { throw sf::win32_error_exception(hres); }\r
+\r
+#ifndef HINST_THISCOMPONENT\r
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;\r
+#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)\r
+#endif\r
+\r
+namespace sf \r
+{\r
+\r
+  HRESULT EnableBlurBehind(HWND hwnd)\r
+  {\r
+    HRESULT hr = S_OK;\r
+\r
+    //Create and populate the BlurBehind structre\r
+    DWM_BLURBEHIND bb = {0};\r
+    //Enable Blur Behind and Blur Region;\r
+    bb.dwFlags = DWM_BB_ENABLE;\r
+    bb.fEnable = true;\r
+    bb.hRgnBlur = NULL;\r
+\r
+    //Enable Blur Behind\r
+    hr = DwmEnableBlurBehindWindow(hwnd, &bb);\r
+    if (SUCCEEDED(hr))\r
+    {\r
+      //do more things\r
+    }\r
+    return hr;\r
+  }\r
+\r
+  // 汎用情報格納用\r
+  struct mode_info \r
+  {\r
+    mode_info(const std::wstring& n,const std::wstring& d) : name(n),description(d) {}\r
+    std::wstring name;\r
+    std::wstring description;\r
+  };\r
+\r
+  // ディスプレイモード\r
+  struct display_mode \r
+  {\r
+    display_mode(const std::wstring& n,const std::wstring& d) : name(n),description(d) {}\r
+    std::wstring name;\r
+    std::wstring description;\r
+  };\r
+\r
+  std::vector<mode_info> display_modes = \r
+    boost::assign::list_of<mode_info>\r
+    (L"DXGI_FORMAT_UNKNOWN",L"フォーマットが不明")\r
+    (L"DXGI_FORMAT_R32G32B32A32_TYPELESS",L"4 成分、128 ビット型なしフォーマット 1")\r
+    (L"DXGI_FORMAT_R32G32B32A32_FLOAT",L"4 成分、128 ビット浮動小数点フォーマット 1")\r
+    (L"DXGI_FORMAT_R32G32B32A32_UINT",L"4 成分、128 ビット符号なし整数フォーマット 1")\r
+    (L"DXGI_FORMAT_R32G32B32A32_SINT",L"4 成分、128 ビット符号付き整数フォーマット 1")\r
+    (L"DXGI_FORMAT_R32G32B32_TYPELESS",L"3 成分、96 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_R32G32B32_FLOAT",L"3 成分、96 ビット浮動小数点フォーマット")\r
+    (L"DXGI_FORMAT_R32G32B32_UINT",L"3 成分、96 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R32G32B32_SINT",L"3 成分、96 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R16G16B16A16_TYPELESS",L"4 成分、64 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_R16G16B16A16_FLOAT",L"4 成分、64 ビット浮動小数点フォーマット")\r
+    (L"DXGI_FORMAT_R16G16B16A16_UNORM",L"4 成分、64 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R16G16B16A16_UINT",L"4 成分、64 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R16G16B16A16_SNORM",L"4 成分、64 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R16G16B16A16_SINT",L"4 成分、64 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R32G32_TYPELESS",L"2 成分、64 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_R32G32_FLOAT",L"2 成分、64 ビット浮動小数点フォーマット")\r
+    (L"DXGI_FORMAT_R32G32_UINT",L"2 成分、64 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R32G32_SINT",L"2 成分、64 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R32G8X24_TYPELESS",L"2 成分、64 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_D32_FLOAT_S8X24_UINT",L"32 ビット浮動小数点成分、および 2 つの符号なし整数成分です (追加の 32 ビットを含む)。")\r
+    (L"DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",L"32 ビット浮動小数点成分、および 2 つの型なし成分です (追加の 32 ビットを含む)。")\r
+    (L"DXGI_FORMAT_X32_TYPELESS_G8X24_UINT",L"32 ビット型なし成分、および 2 つの符号なし整数成分です (追加の 32 ビットを含む)。")\r
+    (L"DXGI_FORMAT_R10G10B10A2_TYPELESS",L"4 成分、32 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_R10G10B10A2_UNORM",L"4 成分、32 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R10G10B10A2_UINT",L"4 成分、32 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R11G11B10_FLOAT",L"3 成分、32 ビット浮動小数点フォーマット")\r
+    (L"DXGI_FORMAT_R8G8B8A8_TYPELESS",L"3 成分、32 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_R8G8B8A8_UNORM",L"4 成分、32 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",L"4 成分、32 ビット符号なし正規化整数 sRGB フォーマット")\r
+    (L"DXGI_FORMAT_R8G8B8A8_UINT",L"4 成分、32 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R8G8B8A8_SNORM",L"3 成分、32 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R8G8B8A8_SINT",L"3 成分、32 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R16G16_TYPELESS",L"2 成分、32 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_R16G16_FLOAT",L"2 成分、32 ビット浮動小数点フォーマット")\r
+    (L"DXGI_FORMAT_R16G16_UNORM",L"2 成分、32 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R16G16_UINT",L"2 成分、32 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R16G16_SNORM",L"2 成分、32 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R16G16_SINT",L"2 成分、32 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R32_TYPELESS",L"1 成分、32 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_D32_FLOAT",L"1 成分、32 ビット浮動小数点フォーマット")\r
+    (L"DXGI_FORMAT_R32_FLOAT",L"1 成分、32 ビット浮動小数点フォーマット")\r
+    (L"DXGI_FORMAT_R32_UINT",L"1 成分、32 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R32_SINT",L"1 成分、32 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R24G8_TYPELESS",L"2 成分、32 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_D24_UNORM_S8_UINT",L"深度チャンネルに 24 ビット、ステンシル チャンネルに 8 ビットを使用する 32 ビット Z バッファー フォーマット")\r
+    (L"DXGI_FORMAT_R24_UNORM_X8_TYPELESS",L"1 成分、24 ビット符号なし正規化整数と追加の型なし 8 ビットを含む、32 ビット フォーマット")\r
+    (L"DXGI_FORMAT_X24_TYPELESS_G8_UINT",L"1 成分、24 ビット型なしフォーマットと追加の 8 ビット符号なし整数成分を含む、32 ビット フォーマット")\r
+    (L"DXGI_FORMAT_R8G8_TYPELESS",L"2 成分、16 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_R8G8_UNORM",L"2 成分、16 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R8G8_UINT",L"2 成分、16 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R8G8_SNORM",L"2 成分、16 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R8G8_SINT",L"2 成分、16 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R16_TYPELESS",L"1 成分、16 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_R16_FLOAT",L"1 成分、16 ビット浮動小数点フォーマット")\r
+    (L"DXGI_FORMAT_D16_UNORM",L"1 成分、16 ビット符号なし正規化整数フォーマット")\r
+    (L"DXGI_FORMAT_R16_UNORM",L"1 成分、16 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R16_UINT",L"1 成分、16 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R16_SNORM",L"1 成分、16 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R16_SINT",L"1 成分、16 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R8_TYPELESS",L"1 成分、8 ビット型なしフォーマット")\r
+    (L"DXGI_FORMAT_R8_UNORM",L"1 成分、8 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R8_UINT",L"1 成分、8 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R8_SNORM",L"1 成分、8 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_R8_SINT",L"1 成分、8 ビット符号付き整数フォーマット")\r
+    (L"DXGI_FORMAT_A8_UNORM",L"1 成分、8 ビット符号なし整数フォーマット")\r
+    (L"DXGI_FORMAT_R1_UNORM",L"1 成分、1 ビット符号なし正規化整数フォーマット 2.")\r
+    (L"DXGI_FORMAT_R9G9B9E5_SHAREDEXP",L"4 成分、32 ビット浮動小数点フォーマット 2.")\r
+    (L"DXGI_FORMAT_R8G8_B8G8_UNORM",L"4 成分、32 ビット符号なし正規化整数フォーマット 3")\r
+    (L"DXGI_FORMAT_G8R8_G8B8_UNORM",L"4 成分、32 ビット符号なし正規化整数フォーマット 3")\r
+    (L"DXGI_FORMAT_BC1_TYPELESS",L"4 成分、型なしブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC1_UNORM",L"4 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC1_UNORM_SRGB",L"sRGB データ用の 4 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC2_TYPELESS",L"4 成分、型なしブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC2_UNORM",L"4 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC2_UNORM_SRGB",L"sRGB データ用の 4 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC3_TYPELESS",L"4 成分、型なしブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC3_UNORM",L"4 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC3_UNORM_SRGB",L"sRGB データ用の 4 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC4_TYPELESS",L"1 成分、型なしブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC4_UNORM",L"1 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC4_SNORM",L"1 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC5_TYPELESS",L"2 成分、型なしブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC5_UNORM",L"2 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_BC5_SNORM",L"2 成分、ブロック圧縮フォーマット")\r
+    (L"DXGI_FORMAT_B5G6R5_UNORM",L"3 成分、16 ビット符号なし正規化整数フォーマット")\r
+    (L"DXGI_FORMAT_B5G5R5A1_UNORM",L"1 ビット アルファをサポートする 4 成分、16 ビット符号なし正規化整数フォーマット")\r
+    (L"DXGI_FORMAT_B8G8R8A8_UNORM",L"8 ビット アルファをサポートする 4 成分、16 ビット符号なし正規化整数フォーマット")\r
+    (L"DXGI_FORMAT_B8G8R8X8_UNORM",L"4 成分、16 ビット符号なし正規化整数フォーマット")\r
+    (L"DXGI_FORMAT_FORCE_UINT",L"コンパイル時に、この列挙型のサイズを 32 ビットにするために定義されています。この値を指定しない場合、一部のコンパイラでは列挙型を 32 ビット以外のサイズでコンパイル可能この定数が使用されることはありません。");\r
+\r
+  // スキャンライン情報\r
+\r
+  std::vector<mode_info> scanline_orders = \r
+    boost::assign::list_of<mode_info>\r
+    (L"DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED",L"走査線の順序が指定されていません。")\r
+    (L"DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE",L"イメージは先頭の走査線~最後の走査線から作成され、スキップされる走査線はありません。")\r
+    (L"DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST",L"イメージが上部のフィールドから作成されます。")\r
+    (L"DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST",L"イメージが下部のフィールドから作成されます。");\r
+\r
+  // スケーリングパラメータ\r
+  std::vector<mode_info> scalings = boost::assign::list_of<mode_info>\r
+    (L"DXGI_MODE_SCALING_UNSPECIFIED",L"スケーリングが指定されていません。")\r
+    (L"DXGI_MODE_SCALING_CENTERED",L"スケーリングなしを指定します。イメージはディスプレイの中央に配置されます。通常、このフラグは固定ドットピッチ ディスプレイ (LED ディスプレイなど) に使用します。")\r
+    (L"DXGI_MODE_SCALING_STRETCHED",L"拡大スケーリングを指定します。");\r
+\r
+  struct simple_vertex\r
+  {\r
+    DirectX::XMFLOAT3 pos;\r
+    DirectX::XMFLOAT3 norm;\r
+    DirectX::XMFLOAT2 tex;\r
+  };\r
+\r
+  struct cb_never_changes\r
+  {\r
+    DirectX::XMMATRIX mView;\r
+    DirectX::XMFLOAT4 vLightDir;\r
+  };\r
+\r
+  struct cb_change_on_resize\r
+  {\r
+    DirectX::XMMATRIX mProjection;\r
+  };\r
+\r
+  struct cb_changes_every_frame\r
+  {\r
+    DirectX::XMMATRIX mWorld;\r
+    DirectX::XMFLOAT4 vLightColor;\r
+\r
+    //    DirectX::XMFLOAT4 vMeshColor;\r
+  };\r
+\r
+  struct slider : public subclass_window\r
+  {\r
+    slider() : subclass_window() {};\r
+    void create() {};\r
+    virtual LRESULT window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam) \r
+    {\r
+      //switch(message){\r
+      //case WM_HSCROLL :\r
+      //  {\r
+      //    switch(wParam)\r
+      //    {\r
+      //    case TB_THUMBTRACK : \r
+      //       DWORD dwPos = SendMessage(GetDlgItem(hwnd_,IDC_SLIDER), TBM_GETPOS, 0, 0); \r
+      //       break; \r
+      //    }\r
+      //  }\r
+      /*   }*/\r
+      return CallWindowProc(proc_backup_,hwnd,message,wParam,lParam);\r
+    };\r
+  };\r
+\r
+  struct toplevel_window::impl : public base_win32_dialog_t\r
+  {\r
+\r
+    static const uint32_t SLIDER_MAX = 30000;\r
+    static const int TAB_INFO = 0;\r
+    static const int TAB_CONFIG = 1;\r
+    static const int TAB_SEQ = 2;\r
+\r
+    impl(const std::wstring& menu_name,const std::wstring& name,bool fit_to_display,float width = 160,float height = 100) \r
+      : base_win32_dialog_t(menu_name,name,fit_to_display,width,height) \r
+      , timer_(*this,100)\r
+      , icon_(IDI_ICON1)\r
+      /*,mesh_color_(0.7f, 0.7f, 0.7f, 1.0f)*/\r
+      ,init_(false)\r
+      ,thumb_start_(false)\r
+    {\r
+\r
+      file_name_.reserve(MAX_PATH + 1);\r
+      dir_name_.reserve(MAX_PATH + 1);\r
+      on_render.connect(boost::bind(&impl::render,this));\r
+    };\r
+\r
+    ~impl(){\r
+      //safe_release(dxgi_factory_);\r
+    };\r
+\r
+\r
+    // -------------------------------------------------------------------\r
+    // ウィンドウプロシージャ\r
+    // -------------------------------------------------------------------\r
+\r
+    void init_control()\r
+    {\r
+      SendMessage(GetDlgItem(hwnd_,IDC_SLIDER), TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, SLIDER_MAX));\r
+\r
+      DWORD dwDlgBase = GetDialogBaseUnits();\r
+      int cxMargin = LOWORD(dwDlgBase) / 4; \r
+      int cyMargin = HIWORD(dwDlgBase) / 8;\r
+\r
+      //タブの初期設定\r
+      TCITEM tie; \r
+      tie.mask = TCIF_TEXT | TCIF_IMAGE; \r
+      tie.iImage = -1; \r
+      HWND tab = GetDlgItem(hwnd_,IDC_TAB);\r
+      // 情報タブの挿入\r
+      tie.pszText = L"情報";\r
+      TabCtrl_InsertItem(tab,TAB_INFO,&tie);\r
+      tab_dialogs_.push_back(\r
+        new info_tab_dialog(*this,tab,TAB_INFO,L"info",L"info",HINST_THISCOMPONENT,MAKEINTRESOURCEW(IDD_INFO))\r
+        );\r
+      tab_dialogs_[TAB_INFO].show();\r
+\r
+      // 設定タブの挿入\r
+      tie.pszText = L"設定";\r
+      TabCtrl_InsertItem(tab,TAB_CONFIG,&tie);\r
+      tab_dialogs_.push_back(\r
+        new config_tab_dialog(*this,tab,TAB_CONFIG,L"config",L"config",HINST_THISCOMPONENT,MAKEINTRESOURCEW(IDD_CONFIG)) \r
+        );\r
+      //TabCtrl_SetCurSel(tab,0);\r
+      //RECT rci;\r
+      //TabCtrl_GetItemRect(tab,0,&rci);\r
+      //RECT r;\r
+      ////TabCtrl_GetItemRect(tab,0,&r);\r
+      //GetClientRect(tab,&r);\r
+      //RECT rw;\r
+      //GetWindowRect(tab,&rw);\r
+      //POINT pt = {rw.left,rw.top + rci.bottom};\r
+      //ScreenToClient(hwnd_,&pt);\r
+\r
+      // シーケンサタブの挿入\r
+      tie.pszText = L"シーケンサ";\r
+      TabCtrl_InsertItem(tab,TAB_SEQ,&tie);\r
+      tab_dialogs_.push_back(\r
+        new seq_tab_dialog(application::instance()->sequencer(),*this,tab,TAB_SEQ,L"sequencer",L"sequencer",HINST_THISCOMPONENT,MAKEINTRESOURCEW(IDD_SEQ))\r
+        );\r
+\r
+      //GetRect(\r
+\r
+      //情報表示ダイアログの作成・表示\r
+      //hwnd_info_ = CreateDialogW(HINST_THISCOMPONENT,MAKEINTRESOURCE(IDD_INFO),hwnd_,proc_info_);\r
+      //SetWindowPos(hwnd_info_,HWND_TOP,pt.x + cxMargin,pt.y + cyMargin,r.right - cxMargin * 2 - 1,r.bottom - rci.bottom - cyMargin * 2 - 1,SWP_NOZORDER | SWP_SHOWWINDOW);\r
+\r
+      //TODO: 設定ダイアログの作成・表示\r
+      //hwnd_config_ = CreateDialogW(HINST_THISCOMPONENT,MAKEINTRESOURCEW(IDD_CONFIG),hwnd_,proc_config_);\r
+      //SetWindowPos(hwnd_config_,HWND_TOP,pt.x + cxMargin,pt.y + cyMargin,r.right - cxMargin * 2 - 1,r.bottom - rci.bottom - cyMargin * 2 - 1,SWP_NOZORDER | SWP_SHOWWINDOW);\r
+      ////MapDialogRect(hwnd_config_,&r);\r
+      //ShowWindow(hwnd_config_,FALSE);\r
+      //config_dialog_.reset();\r
+\r
+      // 背景色の設定\r
+      //get_dc tab_dc(tab);\r
+      //get_dc info_dc(hwnd_info_);\r
+      //get_dc config_dc(hwnd_config_);\r
+      //SetBkMode(info_dc.get(),GetBkMode(tab_dc.get()));\r
+      //SetBkMode(config_dc.get(),GetBkMode(tab_dc.get()));\r
+      //SetBkColor(info_dc.get(),GetBkColor(tab_dc.get()));\r
+      //SetBkColor(config_dc.get(),GetBkColor(tab_dc.get()));\r
+\r
+      tab_page_ = 0;\r
+      //slider_.attach(GetDlgItem(hwnd_,IDC_SLIDER));\r
+    }\r
+\r
+    void reader_ready()\r
+    {\r
+      // プレイボタンは有効化\r
+      enable_control(IDC_PLAY,true);\r
+      focus(IDC_PLAY);\r
+      // highlight(IDC_PLAY);\r
+      // その他のボタンは無効化\r
+      enable_control(IDC_REPEAT_CHECK,true);\r
+      enable_control(IDC_PAUSE,false);\r
+      enable_control(IDC_SLIDER,true);\r
+      enable_control(IDC_STOP,false);\r
+      //    enable_control(hwnd_config_,IDC_EXC_MODE,true);\r
+    }\r
+\r
+    void reader_read_file()\r
+    {\r
+      post_message(WM_PLAY_PLAY,0,0);\r
+    }\r
+\r
+    void play_()\r
+    {\r
+      enable_control(IDC_PLAY,false);\r
+      enable_control(IDC_STOP,true);\r
+      focus(IDC_STOP);\r
+      //highlight(IDC_STOP);\r
+      enable_control(IDC_REPEAT_CHECK,true);\r
+      enable_control(IDC_PAUSE,true);\r
+      ::SetWindowText(GetDlgItem(hwnd_,IDC_PAUSE),L"一時停止");\r
+      enable_control(IDC_SLIDER,true);\r
+      enable_control(IDC_FILE,false);\r
+\r
+      // 設定ダイアログ\r
+      // EnableWindow(hwnd_config_,FALSE);\r
+      tab_dialogs_[TAB_CONFIG].disable();\r
+      //    enable_config_dialog(false);\r
+\r
+    }\r
+\r
+    void reader_stop()\r
+    {\r
+      post_message(WM_PLAY_STOP,0,0);\r
+    }\r
+\r
+    void stop_()\r
+    {\r
+      enable_control(IDC_PLAY,true);\r
+      focus(IDC_PLAY);\r
+      //highlight(IDC_PLAY);\r
+      enable_control(IDC_REPEAT_CHECK,true);\r
+      enable_control(IDC_STOP,false);\r
+      enable_control(IDC_PAUSE,false);\r
+      enable_control(IDC_SLIDER,true);\r
+      ::SendMessage(GetDlgItem(hwnd_,IDC_SLIDER), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)0);\r
+      enable_control(IDC_FILE,true);\r
+\r
+      // 設定ダイアログ\r
+      // EnableWindow(hwnd_config_,TRUE);\r
+      tab_dialogs_[TAB_CONFIG].enable();\r
+      //    enable_config_dialog(true);\r
+\r
+    }\r
+\r
+\r
+    void reader_pause()\r
+    {\r
+      send_message(WM_PLAY_PAUSE,0,0);\r
+    }\r
+\r
+    void pause_()\r
+    {\r
+      enable_control(IDC_PLAY,false);\r
+      enable_control(IDC_STOP,false);\r
+      enable_control(IDC_PAUSE,true);\r
+      enable_control(IDC_REPEAT_CHECK,true);\r
+      focus(IDC_PAUSE);\r
+      //highlight(IDC_PAUSE);\r
+      ::SetWindowText(GetDlgItem(hwnd_,IDC_PAUSE),L"再開");\r
+      enable_control(IDC_SLIDER,true);\r
+      enable_control(IDC_FILE,false);\r
+\r
+      // 設定ダイアログ\r
+      tab_dialogs_[TAB_CONFIG].disable();\r
+      //    enable_config_dialog(false);\r
+    }\r
+\r
+    virtual void create(){\r
+      create_device_independent_resources();\r
+      //    icon_ = ::LoadIconW(HINST_THISCOMPONENT,MAKEINTRESOURCE(IDI_ICON1));\r
+      register_class(this->name_.c_str(),CS_HREDRAW | CS_VREDRAW ,0,DLGWINDOWEXTRA,icon_.get());\r
+      create_dialog();\r
+\r
+      // 半透明ウィンドウを有効にする。\r
+      //BOOL dwmEnable;\r
+      //DwmIsCompositionEnabled (&dwmEnable); \r
+      //if (dwmEnable) EnableBlurBehind(*this);\r
+\r
+    }\r
+\r
+    void create_dialog()\r
+    {\r
+      hwnd_ = ::CreateDialog(HINST_THISCOMPONENT,MAKEINTRESOURCE(IDD_MAINDIALOG),::GetDesktopWindow(),thunk_proc_);\r
+      // ::DialogBox(HINST_THISCOMPONENT,MAKEINTRESOURCE(IDD_MAINDIALOG),0,thunk_proc_);\r
+    }\r
+\r
+    virtual void discard_device()\r
+    {}\r
+\r
+    void calc_client_size()\r
+    {\r
+      //クライアント領域の現在の幅、高さを求める\r
+      RECT rc;\r
+      GetClientRect( hwnd_, &rc );\r
+      client_width_ = rc.right - rc.left;\r
+      client_height_ = rc.bottom - rc.top;\r
+    }\r
+\r
+    virtual void create_device()\r
+    {\r
+      calc_client_size();\r
+      //HRESULT hr = S_OK;\r
+      init_ = false;\r
+      init_ = true;// 初期化完了\r
+    }\r
+\r
+\r
+    virtual void create_device_independent_resources()\r
+    {\r
+\r
+    }\r
+\r
+    void render(){\r
+\r
+    }\r
+\r
+\r
+    void create_window()\r
+    {\r
+\r
+      // Windowを作成する\r
+      CreateWindowEx(\r
+        WS_EX_APPWINDOW | WS_EX_TOPMOST,\r
+        name_.c_str(),\r
+        title_.c_str(),\r
+        WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME,\r
+        CW_USEDEFAULT,\r
+        CW_USEDEFAULT,\r
+        static_cast<uint32_t>(dpi_.scale_x(width_)),\r
+        static_cast<uint32_t>(dpi_.scale_x(height_)),\r
+        NULL,\r
+        NULL,\r
+        HINST_THISCOMPONENT,\r
+        this\r
+        );\r
+    };\r
+\r
+    void get_dxgi_information()\r
+    {\r
+      //    int i = 0;\r
+      //\r
+      //    while(1){\r
+      //      IDXGIAdapter1Ptr adapter;\r
+      //      HRESULT hr = dxgi_factory_->EnumAdapters1(i,&adapter);\r
+      //      if(hr == DXGI_ERROR_NOT_FOUND)\r
+      //      {\r
+      //        break;\r
+      //      }\r
+      //      DXGI_ADAPTER_DESC1 desc;\r
+      //      adapter->GetDesc1(&desc);\r
+      //      //adapter->CheckInterfaceSupport();\r
+      //      \r
+      //      wdout << desc.Description << std::endl;\r
+      //      wdout << desc.DedicatedVideoMemory << std::endl;\r
+      //      IDXGIDevice1Ptr device;\r
+      //\r
+      //      uint32_t oi = 0;\r
+      //\r
+      //\r
+      //      while(1)\r
+      //      {\r
+      //        IDXGIOutputPtr output;        \r
+      //        if(adapter->EnumOutputs(oi,&output) == DXGI_ERROR_NOT_FOUND){\r
+      //          break;\r
+      //        }\r
+      //        DXGI_OUTPUT_DESC output_desc;\r
+      //        output->GetDesc(&output_desc); \r
+      //        UINT num = 0;\r
+      //        DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;\r
+      //        UINT flags         = DXGI_ENUM_MODES_INTERLACED | DXGI_ENUM_MODES_SCALING;\r
+      //\r
+      //        output->GetDisplayModeList(format,flags,&num,0);\r
+      //        boost::shared_array<DXGI_MODE_DESC> disp_modes(new DXGI_MODE_DESC[num]);\r
+      //        output->GetDisplayModeList(format,flags,&num,&disp_modes[0]);\r
+      //        //output->GetFrameStatistics\r
+      //        for(uint32_t mode_index = 0;mode_index < num;++mode_index)\r
+      //        {\r
+      //          DXGI_MODE_DESC& mode(disp_modes[mode_index]);\r
+      //          wdout << boost::wformat(L"Format: %s %s \n Width: %d Height: %d RefleshRate: %d/%d Scaling:%s %s \n Scanline: %s %s ")\r
+      //            %  display_modes[mode.Format].name % display_modes[mode.Format].description\r
+      //            %  mode.Width % mode.Height \r
+      //            %  mode.RefreshRate.Numerator % mode.RefreshRate.Denominator\r
+      //            %  scalings[mode.Scaling].name %  scalings[mode.Scaling].description\r
+      //            %  scanline_orders[mode.ScanlineOrdering].name\r
+      //            %  scanline_orders[mode.ScanlineOrdering].description\r
+      //            << std::endl;\r
+      //        }\r
+      ////        output->\r
+      //        wdout << output_desc.DeviceName << std::endl; \r
+      //        oi++;\r
+      //      }\r
+      //\r
+      //      adapter.Release();\r
+      //      ++i;\r
+      //    }\r
+    }\r
+\r
+    // コントロールにフォーカスを移動する\r
+    // id ... コントロールID\r
+    void focus(uint32_t id)\r
+    {\r
+      // 間違い\r
+      // ::SetFocus(GetDlgItem(hwnd_,id));\r
+\r
+      // 正解\r
+      post_message(WM_NEXTDLGCTL,(WPARAM)GetDlgItem(hwnd_,id),TRUE);\r
+    }\r
+\r
+    void highlight(uint32_t id)\r
+    {\r
+      Button_SetState(GetDlgItem(hwnd_,id),TRUE);\r
+    }\r
+\r
+  LRESULT other_window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)\r
+\r
+  {\r
+    switch (message)\r
+    {\r
+    case WM_PLAY_PLAY:\r
+      play_();\r
+      return TRUE;\r
+    case WM_PLAY_STOP:\r
+      stop_();\r
+      return TRUE;\r
+    case WM_PLAY_PAUSE:\r
+      pause_();\r
+      return TRUE;\r
+      //::SetTimer(hwnd_,(UINT_PTR)&timer_id_,1000,NULL);\r
+    }\r
+\r
+    return FALSE;\r
+  };\r
+\r
+  LRESULT on_init_dialog(HWND default_focus_ctrl,LPARAM data)\r
+  {\r
+    init_control();\r
+    create_device();\r
+    timer_.start();\r
+    //MARGINS mgn = {-1};//left,right,top,bottom\r
+    //HRESULT hr = DwmExtendFrameIntoClientArea(hwnd_, &mgn);\r
+    return TRUE;\r
+  }\r
+\r
+  LRESULT on_size(uint32_t flag,uint32_t width,uint32_t height)\r
+  {\r
+    // バックバッファなどに関係するインターフェースを解放する\r
+    // バックバッファを解放する\r
+    if(init_)\r
+    {\r
+      int height = client_height_;\r
+      int width = client_width_;\r
+\r
+      calc_client_size();\r
+\r
+      int delta_height = client_height_ - height; \r
+\r
+      HWND hwnd_tab = GetDlgItem(hwnd_,IDC_TAB);\r
+      RECT rect_tab;\r
+      GetWindowRect(hwnd_tab,&rect_tab);\r
+\r
+\r
+      int tab_width(rect_tab.right - rect_tab.left),\r
+        tab_height(rect_tab.bottom - rect_tab.top);\r
+      int delta_width = width - tab_width; \r
+\r
+      SetWindowPos(hwnd_tab,0,0,0,client_width_ - delta_width,tab_height + delta_height,SWP_NOZORDER | SWP_NOMOVE);\r
+\r
+      for(int i = 0;i < tab_dialogs_.size();++i)\r
+      {\r
+        tab_dialogs_[i].resize();\r
+      }\r
+\r
+      //client_width_\r
+    }\r
+    // バックバッファなどに関係するインターフェースを再作成する\r
+\r
+    //if (render_target_)\r
+    //{\r
+    // D2D1_SIZE_U size;\r
+    // size.width = lParam & 0xFFFF;\r
+    // size.height = (lParam >> 16) & 0xFFFF; ;\r
+\r
+    // // Note: This method can fail, but it's okay to ignore the\r
+    // // error here -- it will be repeated on the next call to\r
+    // // EndDraw.\r
+    // render_target_->Resize(size);\r
+    //}\r
+    return TRUE;\r
+  }\r
+\r
+  LRESULT on_paint()\r
+  {\r
+    //create_device();\r
+\r
+    { \r
+      paint_struct begin_paint(hwnd_);\r
+      //CloseHandle(cb);\r
+      // 描画コードの呼び出し\r
+      /*render();*/\r
+\r
+    }\r
+    return FALSE;\r
+    //        ::ShowWindow(hwnd_,SW_MINIMIZE);\r
+\r
+  }\r
+\r
+  LRESULT on_display_change(uint32_t bpp,uint32_t h_resolution,uint32_t v_resolution)\r
+  {\r
+    invalidate_rect();\r
+    return TRUE;\r
+  }\r
+\r
+  LRESULT on_erase_backgroud(HDC dc)\r
+  {\r
+    return FALSE;\r
+  }\r
+\r
+  LRESULT on_hscroll(uint32_t state,uint32_t position,HWND ctrl_hwnd)\r
+  {\r
+    switch(state)\r
+    {\r
+    case TB_THUMBTRACK :\r
+\r
+#ifdef _DEBUG\r
+      wdout << L"TB_THUMBTRACK" << std::endl;\r
+#endif\r
+      thumb_start_ = true;\r
+      break;\r
+    case TB_ENDTRACK :\r
+#ifdef _DEBUG\r
+      wdout << L"TB_ENDTRACK" << std::endl;\r
+#endif\r
+      application::instance()->reader_position(SendMessage(GetDlgItem(hwnd_,IDC_SLIDER), TBM_GETPOS, 0, 0) * application::instance()->reader_data_size() / SLIDER_MAX); \r
+\r
+      thumb_start_ = false;\r
+      break;\r
+    case TB_PAGEUP:\r
+      thumb_start_ = true;\r
+      break;\r
+    case TB_PAGEDOWN:\r
+      thumb_start_ = true;\r
+      break;\r
+    default:\r
+#ifdef _DEBUG\r
+      wdout << boost::wformat(L"LOWORD(wParam):%d") % state << std::endl;\r
+#endif\r
+      break;\r
+    }\r
+    return FALSE;\r
+  }\r
+\r
+  LRESULT on_destroy()\r
+  {\r
+    ::PostQuitMessage(0);\r
+    return FALSE;\r
+  }\r
+\r
+  LRESULT on_close()\r
+  {\r
+    //slider_.detatch();\r
+    timer_.reader_stop();\r
+    // 後始末\r
+    discard_device();\r
+    // レンダーターゲットのリリース\r
+    //safe_release(dcr_);\r
+    //      safe_release(render_target_);\r
+    // Windowの破棄\r
+    BOOL ret(::DestroyWindow(hwnd_));\r
+    BOOST_ASSERT(ret != 0);\r
+    return TRUE;\r
+  }\r
+\r
+  LRESULT on_command(uint32_t wparam, uint32_t lparam)\r
+  {\r
+    switch(LOWORD(wparam)){\r
+    case IDC_FILE:\r
+      {\r
+        return get_file_path();\r
+      }\r
+    case IDC_SLIDER:\r
+      //::MessageBox( hwnd_,L"SLIDERが動作しました。",L"IDC_SLIDER",MB_OK);\r
+      return TRUE;\r
+    case IDC_PLAY:\r
+      //         ::MessageBox( hwnd_,L"reader_read_fileボタンが押されました。",L"IDC_PLAY",MB_OK);\r
+      application::instance()->reader_read_file();\r
+      return TRUE;\r
+    case IDC_STOP:\r
+      //::MessageBox( hwnd_,L"reader_stopボタンが押されました。",L"IDC_STOP",MB_OK);\r
+      application::instance()->reader_stop();\r
+      return TRUE;\r
+    case IDC_PAUSE:\r
+      //::MessageBox( hwnd_,L"reader_pauseボタンが押されました。",L"IDC_PAUSE",MB_OK);\r
+      application::instance()->reader_pause();\r
+      return TRUE;\r
+    case IDC_REPEAT_CHECK:\r
+      application::instance()->reader_repeat_mode(::SendMessage(GetDlgItem(hwnd_,IDC_REPEAT_CHECK),BM_GETCHECK,0,0) == BST_CHECKED);\r
+      return TRUE;\r
+    }\r
+\r
+    //if(HIWORD(wParam) == THBN_CLICKED ){\r
+    //  switch(LOWORD(wParam)){\r
+    //  case THUMB_START:\r
+    //    {\r
+    //      if(status_ != reader_stop)\r
+    //      {\r
+    //        update_status(reader_stop);\r
+    //      } else {\r
+    //        update_status(active);\r
+    //      }\r
+    //    }\r
+    //    break;\r
+    //  }\r
+    //}\r
+    return FALSE;\r
+  }\r
+\r
+  LRESULT on_timer(uint32_t timer_id)\r
+  {\r
+    // TODO:スレッドのエラーチェックも入れておく\r
+    if(!thumb_start_){\r
+      int status = application::instance()->reader_status(std::memory_order_relaxed);\r
+      if( status == reader_thread_t::status_play_ok || status == reader_thread_t::status_end_ok)\r
+      {\r
+        uint64_t pos = application::instance()->reader_position() * SLIDER_MAX / application::instance()->reader_data_size(); \r
+        SendMessage(GetDlgItem(hwnd_,IDC_SLIDER), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);\r
+      }\r
+    }\r
+    return TRUE;\r
+\r
+  }\r
+\r
+  LRESULT on_notify(NMHDR* nmhdr)\r
+  {\r
+    switch (nmhdr->code)\r
+    {\r
+    case TCN_SELCHANGE:\r
+      {\r
+        tab_page_ = TabCtrl_GetCurSel(nmhdr->hwndFrom);\r
+        for(int i = 0;i < tab_dialogs_.size();++ i)\r
+        {\r
+          if( i == tab_page_)\r
+          {\r
+            tab_dialogs_[i].show();\r
+          } else {\r
+            tab_dialogs_[i].hide();\r
+          }\r
+        }\r
+        return TRUE;\r
+        break;\r
+      }\r
+    }\r
+    return FALSE;\r
+  }\r
+\r
+  private:\r
+\r
+    void read_start() {};\r
+    BOOL get_file_path ()\r
+    {\r
+      WCHAR file_name[MAX_PATH]  = L"";  // ファイル名\r
+      WCHAR dir_name[MAX_PATH]   = L"";  // ディレクトリ\r
+\r
+      WCHAR file_title[MAX_PATH] = L"";  // ダイアログのタイトル\r
+      OPENFILENAME ofn;              \r
+\r
+      if (dir_name_.empty())\r
+      {\r
+        GetWindowsDirectory(dir_name, MAX_PATH);\r
+        dir_name_.assign(dir_name);\r
+      }\r
+\r
+      if(!file_name_.empty())\r
+      {\r
+        wcscpy_s(file_name,MAX_PATH,dir_name_.c_str());\r
+      }\r
+\r
+      // Set up structure for file dialog\r
+      ZeroMemory(&ofn, sizeof(ofn));\r
+      ofn.lStructSize = sizeof(OPENFILENAME);\r
+      ofn.hwndOwner = ::GetDesktopWindow();\r
+      ofn.lpstrFilter = L"Wave File (*.wav)\0*.WAV\0";\r
+      ofn.lpstrCustomFilter = NULL;\r
+      ofn.nFilterIndex = 1;\r
+      ofn.lpstrFile = file_name;\r
+      ofn.nMaxFile = MAX_PATH;\r
+      ofn.lpstrFileTitle = file_title;\r
+      ofn.nMaxFileTitle = MAX_PATH;\r
+      ofn.lpstrInitialDir = dir_name;\r
+      ofn.lpstrTitle = L".WAVファイルを指定してください。";\r
+      ofn.lpstrDefExt = L"wav";\r
+      ofn.Flags = OFN_SHAREAWARE | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;\r
+\r
+      // Put up Open File dialog to get file name.\r
+      if (GetOpenFileName(&ofn))\r
+      {\r
+        file_name_.assign(file_name);\r
+        sf::application::instance()->reader_setup(file_name);\r
+      }\r
+      return TRUE;\r
+    }\r
+\r
+    //long wm_task_bar_create_;\r
+    //sf::taskbar taskbar_;\r
+\r
+    timer timer_;\r
+    bool thumb_start_;\r
+    //slider slider_;\r
+\r
+    //IDXGIFactory1Ptr dxgi_factory_;\r
+    //IDXGIAdapter1Ptr adapter_;\r
+    //IDXGIOutputPtr output_;\r
+    //ID3D11DevicePtr d3d_device_;\r
+    //ID3D11DeviceContextPtr d3d_context_;\r
+    //ID3D11Texture2DPtr texture_;\r
+    //ID3D11RenderTargetViewPtr view_;\r
+    //ID3D11Texture2DPtr depth_texture_;\r
+    //ID3D11DepthStencilViewPtr depth_view_;\r
+    //ID3D11VertexShaderPtr v_shader_;\r
+    //ID3D11InputLayoutPtr input_layout_;\r
+    //ID3D11PixelShaderPtr p_shader_;\r
+    //ID3D11BufferPtr v_buffer_;\r
+    //ID3D11BufferPtr i_buffer_;\r
+    //ID3D11BufferPtr cb_never_changes_;\r
+    //ID3D11BufferPtr cb_change_on_resize_;\r
+    //ID3D11BufferPtr cb_changes_every_frame_;\r
+    //ID3D11ShaderResourceViewPtr shader_res_view_;\r
+    //ID3D11SamplerStatePtr sampler_state_;\r
+\r
+    //DirectX::XMMATRIX                            mat_world_;\r
+    //DirectX::XMMATRIX                            mat_view_;\r
+    //DirectX::XMMATRIX                            mat_projection_;\r
+    //DirectX::XMFLOAT4                            mesh_color_;\r
+\r
+    float client_width_,client_height_;\r
+\r
+    //IDXGISwapChainPtr; \r
+    //IDXGISwapChainPtr swap_chain_;\r
+    // std::wstring dxgi_info_;\r
+\r
+    std::wstring file_name_;\r
+    std::wstring dir_name_;\r
+    icon icon_;\r
+    bool init_;\r
+\r
+    D2D1_SIZE_U icon_size_;\r
+\r
+    //  HWND hwnd_config_;\r
+    // HWND hwnd_info_;\r
+\r
+    boost::ptr_vector<tab_dialog_base> tab_dialogs_;\r
+    //tab_dialog_ptr config_dialog_;\r
+\r
+    int tab_page_;\r
+\r
+\r
+    // thisとhwndをつなぐthunkクラス\r
+    // メンバー関数を直接呼び出す。\r
+    struct hwnd_this_thunk2 : public Xbyak::CodeGenerator {\r
+      hwnd_this_thunk2(LONG_PTR this_addr,const void * proc)\r
+      {\r
+        // 引数の位置をひとつ後ろにずらす\r
+        mov(r10,r9);\r
+        mov(r9,r8);\r
+        mov(r8,rdx);\r
+        mov(rdx,rcx);\r
+        // thisのアドレスをrcxに格納する\r
+        mov(rcx,(LONG_PTR)this_addr);\r
+        // 第5引数をスタックに格納\r
+        push(r10);\r
+        sub(rsp,32);\r
+        mov(r10,(LONG_PTR)proc);\r
+        // メンバ関数呼び出し\r
+        call(r10);\r
+        add(rsp,40);\r
+        ret(0);\r
+      }\r
+    };\r
+\r
+    //hwnd_this_thunk2 thunk_info_;\r
+    //  hwnd_this_thunk2 thunk_config_;\r
+    //proc_t proc_info_;\r
+    //  proc_t proc_config_;\r
+\r
+  };\r
+\r
+  //\r
+  // Creates a Direct2D bitmap from the specified\r
+  // file name.\r
+  //\r
+  ID2D1BitmapPtr load_bitmap_from_file(\r
+    ID2D1HwndRenderTargetPtr render_target,\r
+    IWICImagingFactoryPtr wic_factory,\r
+    std::wstring uri,\r
+    uint32_t destination_width,\r
+    uint32_t destination_height\r
+    )\r
+  {\r
+    HRESULT hr = S_OK;\r
+\r
+    IWICBitmapDecoderPtr decoder;\r
+    IWICBitmapFrameDecodePtr decoder_source;\r
+    IWICStreamPtr stream;\r
+    IWICFormatConverterPtr converter;\r
+    IWICBitmapScalerPtr scaler;\r
+    ID2D1BitmapPtr bitmap;\r
+\r
+    THROW_IFERR(wic_factory->CreateDecoderFromFilename(\r
+      uri.c_str(),\r
+      NULL,\r
+      GENERIC_READ,\r
+      WICDecodeMetadataCacheOnLoad,\r
+      &decoder\r
+      ));\r
+\r
+    // Create the initial frame.\r
+    THROW_IFERR(decoder->GetFrame(0, &decoder_source));\r
+\r
+    // Convert the image format to 32bppPBGRA\r
+    // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).\r
+    THROW_IFERR(hr = wic_factory->CreateFormatConverter(&converter));\r
+\r
+    // If a new width or height was specified, create an\r
+    // IWICBitmapScaler and use it to resize the image.\r
+    if (destination_width != 0 || destination_height != 0)\r
+    {\r
+      uint32_t originalWidth, originalHeight;\r
+      THROW_IFERR(decoder_source->GetSize((UINT*)&originalWidth, (UINT*)&originalHeight));\r
+      if (destination_width == 0)\r
+      {\r
+        FLOAT scalar = static_cast<FLOAT>(destination_height) / static_cast<FLOAT>(originalHeight);\r
+        destination_width = static_cast<uint32_t>(scalar * static_cast<FLOAT>(originalWidth));\r
+      }\r
+      else if (destination_height == 0)\r
+      {\r
+        FLOAT scalar = static_cast<FLOAT>(destination_width) / static_cast<FLOAT>(originalWidth);\r
+        destination_height = static_cast<uint32_t>(scalar * static_cast<FLOAT>(originalHeight));\r
+      }\r
+\r
+      THROW_IFERR(wic_factory->CreateBitmapScaler(&scaler));\r
+      THROW_IFERR(scaler->Initialize(\r
+        decoder_source,\r
+        destination_width,\r
+        destination_height,\r
+        WICBitmapInterpolationModeCubic\r
+        ));\r
+      THROW_IFERR(converter->Initialize(\r
+        scaler.GetInterfacePtr(),\r
+        GUID_WICPixelFormat32bppPBGRA,\r
+        WICBitmapDitherTypeNone,\r
+        NULL,\r
+        0.f,\r
+        WICBitmapPaletteTypeMedianCut\r
+        ));\r
+    }\r
+    else // Don't scale the image.\r
+    {\r
+      THROW_IFERR(converter->Initialize(\r
+        decoder_source.GetInterfacePtr(),\r
+        GUID_WICPixelFormat32bppPBGRA,\r
+        WICBitmapDitherTypeNone,\r
+        NULL,\r
+        0.f,\r
+        WICBitmapPaletteTypeMedianCut\r
+        ));\r
+    }\r
+\r
+    // Create a Direct2D bitmap from the WIC bitmap.\r
+    THROW_IFERR(render_target->CreateBitmapFromWicBitmap(\r
+      converter.GetInterfacePtr(),\r
+      NULL,\r
+      &bitmap\r
+      ));\r
+\r
+    return bitmap;\r
+  }\r
+\r
+\r
+  toplevel_window::toplevel_window(const std::wstring& menu_name,const std::wstring& name,bool fit_to_display,float width ,float height)\r
+    : impl_(new impl(menu_name,name,fit_to_display,width,height))\r
+  {\r
+\r
+  };\r
+\r
+  void * toplevel_window::raw_handle() const {return impl_->raw_handle();};\r
+  void toplevel_window::create(){impl_->create();};\r
+  void toplevel_window::show(){impl_->show();};\r
+  void toplevel_window::hide(){impl_->hide();};\r
+  bool toplevel_window::is_show(){return impl_->is_show();};\r
+  void toplevel_window::text(std::wstring& text){impl_->text(text);};\r
+  void toplevel_window::message_box(const std::wstring& text,const std::wstring& caption,uint32_t type )\r
+  {\r
+    impl_->message_box(text,caption,type);\r
+  };\r
+  void toplevel_window::update(){impl_->update();};\r
+  void toplevel_window::render(){impl_->render();};\r
+  void toplevel_window::reader_ready(){impl_->reader_ready();};\r
+  void toplevel_window::reader_read_file(){impl_->reader_read_file();};\r
+  void toplevel_window::reader_pause(){impl_->reader_pause();};\r
+  void toplevel_window::reader_stop(){impl_->reader_stop();};\r
+\r
+  void toplevel_window::enable_control(uint32_t id,bool enable)\r
+  {\r
+    impl_->enable_control(id,enable);\r
+  };\r
+\r
+\r
+  toplevel_window_ptr create_toplevel_window\r
+    (\r
+    const std::wstring& menu_name,\r
+    const std::wstring& name,\r
+    const uint32_t show_flag,\r
+    bool fit_to_display,\r
+    float width,\r
+    float height\r
+    )\r
+  {\r
+    // クライアント領域のサイズからウィンドウサイズを設定\r
+    RECT    rect    = { 0, 0, width, height };\r
+    ::AdjustWindowRectEx( &rect, WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME, FALSE, 0 );\r
+    toplevel_window* p = new toplevel_window(menu_name,name,fit_to_display,rect.right - rect.left,rect.bottom - rect.top);\r
+    p->create();\r
+    p->show();\r
+    p->update();\r
+    return toplevel_window_ptr(p);\r
+  }\r
+  void dialogbox\r
+    (\r
+    const std::wstring& menu_name,\r
+    const std::wstring& name\r
+    )\r
+  {\r
+    toplevel_window_ptr p(new toplevel_window(menu_name,name,false));\r
+    p->create();\r
+  }\r
+\r
+\r
+\r
+\r
+}\r
+\r
diff --git a/wasapi2/toplevel_window.h b/wasapi2/toplevel_window.h
new file mode 100644 (file)
index 0000000..5f2c55d
--- /dev/null
@@ -0,0 +1,80 @@
+#pragma once\r
+/*\r
+*/\r
+// Windows Header Files:\r
+#include "sf_windows.h"\r
+#include "icon.h"\r
+#include "base_window.h"\r
+#include "taskbar.h"\r
+\r
+#define WM_PLAY_STOP WM_USER + 1\r
+#define WM_PLAY_PAUSE WM_USER + 2\r
+#define WM_PLAY_PLAY WM_USER + 3\r
+\r
+namespace sf\r
+{\r
+\r
+  struct toplevel_window;\r
+  typedef std::shared_ptr<toplevel_window> toplevel_window_ptr;\r
+\r
+  /** toplevel_window を生成する関数 */\r
+  toplevel_window_ptr create_toplevel_window (\r
+    const std::wstring& menu_name,\r
+    const std::wstring& name,\r
+    const uint32_t show_flag = SW_SHOW,\r
+    bool fit_to_display = false,\r
+    float width = 640,\r
+    float height = 480\r
+    );\r
+  /** toplevel_window を生成する関数 */\r
+  void dialogbox (\r
+    const std::wstring& menu_name,\r
+    const std::wstring& name\r
+    );\r
+\r
+  /** toplevel ウィンドウクラス */\r
+  /* このクラスは、create_toplevel_window 関数からのみ生成可能 */\r
+  struct toplevel_window : public base_window\r
+  {\r
+\r
+    friend   toplevel_window_ptr create_toplevel_window\r
+      (\r
+      const std::wstring& menu_name,\r
+      const std::wstring& name,\r
+      const uint32_t show_flag,\r
+      bool fit_to_display,\r
+      float width ,\r
+      float height\r
+      );\r
+\r
+    friend void dialogbox (\r
+      const std::wstring& menu_name,\r
+      const std::wstring& name\r
+    );\r
+\r
+    ~toplevel_window(){};\r
\r
+    void * raw_handle() const;\r
+    void create();\r
+    void toplevel_window::show();\r
+    bool toplevel_window::is_show();\r
+    void toplevel_window::hide();\r
+    void message_box(const std::wstring& text,const std::wstring& caption,uint32_t type = MB_OK);\r
+    void text(std::wstring& text);\r
+    void update();\r
+    void render();\r
+\r
+    void reader_ready();\r
+    void reader_read_file();\r
+    void reader_pause();\r
+    void reader_stop();\r
+   \r
+    void enable_control(uint32_t id,bool enable);\r
+\r
+  private:\r
+    struct impl;\r
+    toplevel_window(const std::wstring& menu_name,const std::wstring& name,bool fit_to_display,float width = 800 ,float height = 600);\r
+    // 実装部\r
+    std::shared_ptr<impl> impl_;\r
+  };\r
+}
\ No newline at end of file
diff --git a/wasapi2/wasapi.cpp b/wasapi2/wasapi.cpp
new file mode 100644 (file)
index 0000000..187f08c
--- /dev/null
@@ -0,0 +1,303 @@
+/*\r
+  ==============================================================================\r
+\r
+   Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+#include "StdAfx.h"\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+#include "sf_memory.h"\r
+#include "audio_base.h"\r
+#include "wasapi.h"\r
+\r
+using namespace std;\r
+\r
+namespace sf{\r
+\r
+\r
+  wasapi_shared_timer::wasapi_shared_timer()\r
+    : is_enabled_(false),position_(0),is_start_(false)\r
+  {\r
+//    co_task_memory<WAVEFORMATEX> wfx;\r
+    get_default_audio_client();\r
+    WAVEFORMATEXTENSIBLE w;\r
+    wasapi_device_manager::device_info::current_device_params& params(wasapi_device_manager::instance()->current_input_device().current_params);\r
+    bits_pair bits = {params.bits,params.valid_bits};\r
+    make_wave_format(w,params.sample_rate,params.channel,bits);\r
+    latency_ =  wasapi_device_manager::instance()->current_output_device().latency_default;\r
+//    audio_client_->GetMixFormat(&wfx);\r
+    //WAVEFORMATEXTENSIBLE* w(reinterpret_cast<WAVEFORMATEXTENSIBLE*>(wfx.get())); \r
+    //w->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;\r
+    //w->Format.wBitsPerSample = 16;\r
+    //w->Format.nBlockAlign = (w->Format.wBitsPerSample / 8) * w->Format.nChannels;\r
+    //w->Format.nAvgBytesPerSec = w->Format.nSamplesPerSec  *w->Format.nBlockAlign;\r
+    //w->Samples.wValidBitsPerSample = 16;\r
+    init(w);\r
+  }\r
+\r
+  wasapi_shared_timer::wasapi_shared_timer(int device_index,wasapi_device_manager::device_info::current_device_params& params)\r
+  : is_enabled_(false),position_(0),is_start_(false)\r
+  {\r
+    current_device_ = wasapi_device_manager::instance()->output_device_infos().at(device_index).device_ptr;\r
+    // オーディオクライアントを取得\r
+    THROW_IF_ERR(\r
+      current_device_\r
+      ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+      NULL, reinterpret_cast<void **>(&audio_client_))\r
+      );\r
+    WAVEFORMATEXTENSIBLE w;\r
+    bits_pair bits = {params.bits,params.valid_bits};\r
+    make_wave_format(w,params.sample_rate,params.channel,bits);\r
+    latency_ =  params.latency;//wasapi_device_manager::instance()->current_output_device().latency_default;\r
+    init(w);\r
+  }\r
+\r
+\r
+  void wasapi_shared_timer::get_default_audio_client()\r
+  {\r
+    // IMMDeviceEnumeratorの取得\r
+    //THROW_IF_ERR(\r
+    //  CoCreateInstance(\r
+    //  __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,\r
+    //  IID_PPV_ARGS(&device_enumerator_)));\r
+\r
+    // デフォルトのオーディオデバイスを取得する\r
+    //THROW_IF_ERR(\r
+    //  device_enumerator_\r
+    //  ->GetDefaultAudioEndpoint(eRender,eMultimedia,&current_device_)\r
+    //  );\r
+\r
+    current_device_ = wasapi_device_manager::instance()->current_output_device().device_ptr;\r
+\r
+    // オーディオクライアントを取得\r
+    THROW_IF_ERR(\r
+      current_device_\r
+      ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+      NULL, reinterpret_cast<void **>(&audio_client_))\r
+      );\r
+  }\r
+\r
+  void wasapi_shared_timer::init(::WAVEFORMATEXTENSIBLE& wfx)\r
+  {\r
+     // 代替フォーマット定義\r
+      sf::co_task_memory<WAVEFORMATEX>  alt_format;\r
+\r
+      // 読みこもうとしているWAVファイルのフォーマットをサポートしているか?\r
+      HRESULT hr = audio_client_->IsFormatSupported(\r
+        AUDCLNT_SHAREMODE_SHARED ,&wfx.Format,&alt_format);\r
+//      bool sample_rate_convert = false;\r
+      float sample_rate_backup = 0.0f;\r
+      if(hr != S_OK) //  S_FALSEならそのフォーマットをサポートしていないらしい..\r
+      {\r
+        // サンプルレートのコンバート\r
+        if(alt_format->nSamplesPerSec != wfx.Format.nSamplesPerSec)\r
+        {\r
+          // 本来のサンプルレートをバックアップする\r
+          sample_rate_backup = wfx.Format.nSamplesPerSec;\r
+          // 代替フォーマットのサンプルレートをセットする\r
+          wfx.Format.nSamplesPerSec = alt_format->nSamplesPerSec;\r
+          // 再計算する\r
+          wfx.Format.nAvgBytesPerSec = alt_format->nSamplesPerSec * wfx.Format.nBlockAlign;\r
+          // もう一回チェックする。\r
+          // サンプルレート以外でサポートしていない点があれば例外が発生する。\r
+          THROW_IF_ERR(audio_client_->IsFormatSupported(\r
+            AUDCLNT_SHAREMODE_SHARED ,&wfx.Format,&alt_format));\r
+          // フラグをセットする\r
+//          sample_rate_convert = true;\r
+        } else {\r
+          // サンプルレート以外であれば例外を出す。\r
+          throw win32_error_exception(hr);\r
+        }\r
+      }\r
+\r
+      // 再生クライアントの初期化\r
+\r
+      REFERENCE_TIME buffer_period =  latency_;\r
+\r
+      REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;\r
+\r
+      THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_SHARED  , \r
+        AUDCLNT_STREAMFLAGS_NOPERSIST /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/, \r
+        buffer_duration, \r
+        0/*buffer_period*/,\r
+        &(wfx.Format), \r
+        NULL));\r
+\r
+      // バッファサイズの取得\r
+      THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));\r
+\r
+      // 再生クライアントの取得\r
+      THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_render_client_)));\r
+\r
+      REFERENCE_TIME psl;\r
+      THROW_IF_ERR(audio_client_->GetStreamLatency(&psl));\r
+#ifdef _DEBUG\r
+      wdout << L"StreamLatency:" << psl << endl;\r
+#endif\r
+//      wdout\r
+\r
+      // サンプルレートコンバータ\r
+      //if(sample_rate_convert)\r
+      //{\r
+      //  THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_clock_adjustment_)));\r
+      //  // 本来のサンプルレートをセットする\r
+      //  audio_clock_adjustment_->SetSampleRate(sample_rate_backup);\r
+      //}\r
+\r
+      num_of_frames_ = wfx.Format.nBlockAlign;\r
+      mix_format_ = wfx;\r
+      //inc_  = (buffer_size_ * num_of_frames_) / (sizeof(short) * periods_per_buffer_);\r
+      buffer_in_periods_ = buffer_size_ / periods_per_buffer_;\r
+\r
+      is_enabled_ = true;\r
+  }\r
+\r
+  wasapi_shared_timer::wasapi_shared_timer(::WAVEFORMATEXTENSIBLE& wfx) \r
+    : is_enabled_(false),position_(0),is_start_(false)\r
+  {\r
+\r
+    try {\r
+      //      thread_priority_.set_priority(AVRT_PRIORITY_NORMAL);\r
+\r
+      // WASAPIの初期化処理\r
+\r
+      get_default_audio_client();\r
+\r
+      init(wfx);\r
+\r
+     } catch (win32_error_exception& e)\r
+    {\r
+      exception_holder_.reset(new win32_error_exception(e.hresult()));\r
+      is_enabled_ = false;\r
+    } catch(...) {\r
+      is_enabled_ = false;\r
+    }\r
+  }\r
+\r
+  wasapi_shared_timer::~wasapi_shared_timer()\r
+  {\r
+//    safe_release(audio_clock_adjustment_);\r
+\r
+    // WASAPIの終了処理\r
+    if(audio_client_)\r
+    {\r
+      audio_client_->Stop();\r
+      audio_client_->Reset();\r
+      safe_release(audio_render_client_);\r
+      audio_client_.Release();\r
+    }\r
+\r
+    safe_release(current_device_);\r
+//    safe_release(device_enumerator_);\r
+  }\r
+\r
+  void wasapi_shared_timer::create_wave_data(){\r
+    // サイン波の生成\r
+    boost::uint32_t buffer_size_in_bytes = buffer_size_ * mix_format_.Format.nBlockAlign;\r
+    size_t render_data_length = mix_format_.Format.nSamplesPerSec * 10 /* 秒 */ * mix_format_.Format.nBlockAlign / sizeof(short);\r
+    tone_buffer_.reserve(render_data_length);\r
+\r
+    double sampleIncrement = (440 /* Hz */ * (M_PI * 2.0)) / (double)mix_format_.Format.nSamplesPerSec;\r
+    double theta = 0.0;\r
+\r
+    for (size_t i = 0 ; i < render_data_length ; i += mix_format_.Format.nChannels)\r
+    {\r
+      double sinValue = sin( theta );\r
+      for(size_t j = 0 ;j < mix_format_.Format.nChannels; j++)\r
+      {\r
+        tone_buffer_.push_back((short)(sinValue * _I16_MAX));\r
+      }\r
+      theta += sampleIncrement;\r
+    }\r
+  };\r
+\r
+  void wasapi_shared_timer::play_buffer(BYTE* source_buffer)\r
+  {\r
+    BYTE* buffer;\r
+\r
+    if(!is_start_)\r
+    {\r
+\r
+      // 最初にバッファを埋める\r
+      THROW_IF_ERR(audio_render_client_->GetBuffer(buffer_size_,&buffer));\r
+      ::CopyMemory(buffer,source_buffer,get_buffer_byte_size());\r
+\r
+      // レイテンシ時間*バッファ数分進める\r
+      THROW_IF_ERR(audio_render_client_->ReleaseBuffer(buffer_size_,0));\r
+\r
+      // 再生開始\r
+      THROW_IF_ERR(audio_client_->Start());\r
+      is_start_ = true;\r
+      return;\r
+    }\r
+\r
+\r
+    // レイテンシ時間だけ待つ\r
+    Sleep(latency_ / 10000);\r
+\r
+    uint32_t padding;\r
+    uint32_t frames_available;\r
+    uint32_t count_period = periods_per_buffer_;\r
+    while(count_period > 0)\r
+    {\r
+      // パディングを求める。\r
+      THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));\r
+      frames_available = buffer_size_ - padding;\r
+\r
+      // パディングを除いた部分のバッファを埋める。\r
+      // パディングを除いた部分のサイズがbuffer_in_periods_より小さい場合はつぎにまわす。\r
+      // パディングを除いた部分を一気に埋めようとしたけどできなかった。。\r
+      while(buffer_in_periods_ <= frames_available && count_period > 0 ) \r
+      {\r
+        THROW_IF_ERR(audio_render_client_->GetBuffer(buffer_in_periods_,&buffer));\r
+        ::CopyMemory(buffer,source_buffer,buffer_in_periods_ *  num_of_frames_);\r
+        THROW_IF_ERR(audio_render_client_->ReleaseBuffer(buffer_in_periods_,0));\r
+        // レイテンシ時間だけ進める\r
+        source_buffer += buffer_in_periods_ * num_of_frames_;\r
+        --count_period;\r
+        // パディングを再度求める\r
+        THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));\r
+        frames_available = buffer_size_ - padding;\r
+      }\r
+\r
+      if(count_period > 0)\r
+      {\r
+        Sleep(latency_ / 10000);\r
+      }\r
+    }\r
+  }\r
+  void wasapi_shared_timer::reset()\r
+  {\r
+    THROW_IF_ERR(audio_client_->Reset());\r
+  }\r
+  void wasapi_shared_timer::stop() {\r
+    //再生停止\r
+    if(is_start_)\r
+    {\r
+      THROW_IF_ERR(audio_client_->Stop());\r
+      reset();\r
+      is_start_ = false;\r
+\r
+    };\r
+  }\r
+}\r
diff --git a/wasapi2/wasapi.h b/wasapi2/wasapi.h
new file mode 100644 (file)
index 0000000..8cbc792
--- /dev/null
@@ -0,0 +1,316 @@
+#pragma once\r
+/*\r
+==============================================================================\r
+\r
+Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+// WASAPI\r
+#include "boost/mpl/if.hpp"\r
+#include <boost/type_traits/is_same.hpp>\r
+#include <boost/utility/enable_if.hpp>\r
+#include <boost/type.hpp>\r
+#include "exception.h"\r
+#include "sf_memory.h"\r
+#include <mmdeviceapi.h>\r
+#include <AudioClient.h>\r
+#include <audiopolicy.h>\r
+\r
+#define _USE_MATH_DEFINES\r
+#include <math.h>\r
+#include <limits.h>\r
+#pragma comment(lib, "winmm.lib")\r
+#pragma comment(lib, "Avrt.lib")\r
+\r
+#include "audio_base.h"\r
+#include "audio_source.h"\r
+#include "Functiondiscoverykeys_devpkey.h"\r
+\r
+// COM Pointer 定義\r
+_COM_SMARTPTR_TYPEDEF(IMMDeviceEnumerator,__uuidof(IMMDeviceEnumerator));\r
+_COM_SMARTPTR_TYPEDEF(IMMDevice,__uuidof(IMMDevice));\r
+_COM_SMARTPTR_TYPEDEF(IMMDeviceCollection,__uuidof(IMMDeviceCollection));\r
+_COM_SMARTPTR_TYPEDEF(IPropertyStore,__uuidof(IPropertyStore));\r
+\r
+_COM_SMARTPTR_TYPEDEF(IAudioClient,__uuidof(IAudioClient));\r
+_COM_SMARTPTR_TYPEDEF(IAudioClock,__uuidof(IAudioClock));\r
+_COM_SMARTPTR_TYPEDEF(IAudioClock2,__uuidof(IAudioClock2));\r
+_COM_SMARTPTR_TYPEDEF(IAudioRenderClient,__uuidof(IAudioRenderClient));\r
+_COM_SMARTPTR_TYPEDEF(IAudioCaptureClient,__uuidof(IAudioCaptureClient));\r
+_COM_SMARTPTR_TYPEDEF(IAudioClockAdjustment,__uuidof(IAudioClockAdjustment));\r
+\r
+namespace sf {\r
+  namespace  mpl = boost::mpl;\r
+  struct bits_pair \r
+  {\r
+    int bits_per_sample;\r
+    int valid_bits_per_sample;\r
+  };\r
+\r
+  void make_wave_format(WAVEFORMATEXTENSIBLE& format,\r
+    int sample_rate,int channels,bits_pair bits,\r
+    uint32_t type = WAVE_FORMAT_EXTENSIBLE,\r
+    const GUID& sub_type = KSDATAFORMAT_SUBTYPE_PCM);\r
+\r
+  void make_wave_format\r
+    (WAVEFORMATEX& format,int sample_rate,int channels,\r
+    int bits,uint32_t type = WAVE_FORMAT_PCM);\r
+\r
+\r
+  struct wasapi_device_manager : singleton<wasapi_device_manager>\r
+  {\r
+    static const int NUM_SAMPLE_RATE = 12;\r
+    static const int NUM_SAMPLE_BITS = 6;\r
+    static const int sample_rates[NUM_SAMPLE_RATE];\r
+\r
+\r
+    static const bits_pair sample_bits[NUM_SAMPLE_BITS];\r
+\r
+    typedef std::map<int,std::map<int,std::map<int,std::map<int,std::map<int,int> > > > > format_map_type;\r
+\r
+    struct device_info \r
+    {\r
+\r
+      device_info(std::wstring& i,std::wstring& difn,std::wstring& dd,std::wstring& dfn,IMMDevicePtr p);\r
+      ~device_info();\r
+      std::wstring id;\r
+      std::wstring device_interface_friendly_name;\r
+      std::wstring device_description;\r
+      std::wstring device_friendly_name;\r
+      bool is_selected;\r
+      IMMDevicePtr device_ptr;\r
+      format_map_type support_formats;\r
+      REFERENCE_TIME latency_minimum;\r
+      REFERENCE_TIME latency_default;\r
+      struct params_t\r
+      {\r
+        params_t()\r
+          : exclusive_mode(false),event_mode(false),bits(16),valid_bits(16),sample_rate(44100),latency(0),channel(2)\r
+        {}\r
+        bool exclusive_mode;\r
+        bool event_mode;\r
+        int bits;\r
+        int valid_bits;\r
+        int sample_rate;\r
+        REFERENCE_TIME latency;\r
+        int channel;\r
+      private:\r
+        friend class boost::serialization::access;\r
+        template<class Archive>\r
+        void serialize(Archive& ar, const unsigned int version)\r
+        {\r
+          ar & BOOST_SERIALIZATION_NVP(exclusive_mode);\r
+          ar & BOOST_SERIALIZATION_NVP(event_mode);\r
+          ar & BOOST_SERIALIZATION_NVP(bits);\r
+          ar & BOOST_SERIALIZATION_NVP(valid_bits);\r
+          ar & BOOST_SERIALIZATION_NVP(sample_rate);\r
+          ar & BOOST_SERIALIZATION_NVP(latency);\r
+          ar & BOOST_SERIALIZATION_NVP(channel);\r
+        }\r
+      };\r
+      params_t params;\r
+    };\r
+\r
+    typedef std::vector<device_info> device_infos_t;\r
+\r
+    wasapi_device_manager();\r
+    ~wasapi_device_manager();\r
+\r
+    device_info& current_output_device(){return output_device_infos_[output_device_index_];};\r
+    device_info& current_input_device() {return input_device_infos_[input_device_index_];};\r
+\r
+    device_infos_t& output_device_infos() {return output_device_infos_;}\r
+    device_infos_t& input_device_infos() {return input_device_infos_;}\r
+\r
+    void select_output_device(int index) { assert(index < output_device_infos_.size()) ; output_device_index_ = index;}\r
+    void select_input_device(int index) { assert(index < input_device_infos_.size()) ; input_device_index_ = index;}\r
+    int current_output_device_index() const {return output_device_index_;}\r
+    int current_input_device_index() const {return input_device_index_;}\r
+  private:\r
+    int get_device_infos(EDataFlow data_flow, std::vector<device_info>& infos,const std::wstring& idd);\r
+    IMMDeviceEnumeratorPtr device_enumerator_;\r
+    int output_device_index_;\r
+    int input_device_index_;\r
+    std::vector<device_info> output_device_infos_;\r
+    std::vector<device_info> input_device_infos_;\r
+  };\r
+\r
+  // タイマーモードのポリシークラス\r
+  struct wasapi_timer_policy\r
+  {\r
+    wasapi_timer_policy(REFERENCE_TIME & latency) : latency_(latency) {};\r
+    void wait(){ Sleep(latency_ / 20000L);}\r
+    static const int STREAM_FLAG = 0;\r
+  private:\r
+    const REFERENCE_TIME& latency_;\r
+  };\r
+\r
+  // イベントモードのポリシークラス\r
+  struct wasapi_event_policy\r
+  {\r
+    wasapi_event_policy() :  \r
+  wait_events_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)) {}\r
+\r
+  void wait()\r
+  {\r
+    WaitForSingleObject(wait_events_.get(),INFINITE);\r
+    ;\r
+  }\r
+\r
+  HANDLE event_handle(){return wait_events_.get();}\r
+  static const int STREAM_FLAG = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;\r
+  private:\r
+    handle_holder wait_events_;\r
+  };\r
+\r
+  // 排他モードのポリシークラス\r
+  struct wasapi_exclusive_policy \r
+  {\r
+    static const AUDCLNT_SHAREMODE SHARE_MODE = AUDCLNT_SHAREMODE_EXCLUSIVE;  \r
+  };\r
\r
+  // 共有モードのポリシークラス\r
+  struct wasapi_shared_policy \r
+  {\r
+    static const AUDCLNT_SHAREMODE SHARE_MODE = AUDCLNT_SHAREMODE_SHARED;\r
+  };\r
+\r
+  // レンダークライアントのポリシークラス\r
+  struct render_client_policy \r
+  {\r
+    //typedef IAudioRenderClientPtr client_ptr_t;\r
+  };\r
+\r
+  // キャプチャのポリシークラス\r
+  struct capture_client_policy \r
+  {\r
+    //typedef IAudioCaptureClientPtr client_ptr_t;\r
+  };\r
+\r
+  // キャプチャのポリシークラス\r
+  struct loopback_capture_client_policy \r
+  {\r
+    //typedef IAudioCaptureClientPtr client_ptr_t;\r
+  };\r
+\r
+  /// WASAPI処理クラス(デフォルト:共有・タイマーモード)\r
+  template <typename ShareModePolicy = wasapi_shared_policy,typename DrivenPolicy = wasapi_timer_policy,typename IOClientPolicy = render_client_policy> \r
+  struct wasapi_base : public audio_base\r
+  {\r
+    friend IOClientPolicy;\r
+    //typedef typename IOClientPolicy::client_ptr_t client_ptr_t;\r
+    typedef wasapi_base<ShareModePolicy,DrivenPolicy> this_type;\r
+    //wasapi_base();\r
+    wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params);\r
+    //explicit wasapi_base(::WAVEFORMATEXTENSIBLE& wfx);\r
+    virtual ~wasapi_base();\r
+\r
+    bool is_enabled () const {return is_enabled_;}\r
+\r
+    /// テスト用 サイン波データの生成\r
+    void create_wave_data();\r
+\r
+    /// サウンド再生処理\r
+    // bool play_buffer(BYTE* buffer);\r
+    bool is_start(){ return is_start_; }\r
+    // 出力用\r
+    uint32_t get_buffer(BYTE** buffer,uint32_t size);\r
+    // キャプチャ用\r
+    uint32_t get_buffer(BYTE** buffer);\r
+    \r
+    void release_buffer(uint32_t num_byte_written);\r
+\r
+    void start();\r
+    void stop();\r
+    void reset();\r
+    void wait(){driven_policy_.wait();};\r
+    uint32_t get_current_padding();\r
+    uint64_t get_position() const \r
+    {\r
+      uint64_t pos = 0;\r
+      audio_clock2_->GetPosition(&pos,0);\r
+      return pos;\r
+    };\r
+    uint32_t get_buffer_byte_size () const { return buffer_size_ * num_of_frames_;}\r
+    uint32_t get_frame_size() const {return num_of_frames_;}\r
+    uint32_t get_buffer_size () const { return buffer_size_; }\r
+    uint64_t get_buffer_duration() { return latency_;}\r
+    uint32_t get_channel() { return mix_format_.Format.nChannels; }\r
+    win32_error_exception* const result() {return exception_holder_.get(); }\r
+\r
+  private:\r
+\r
+    void init_io_client( boost::type<render_client_policy>)\r
+    {\r
+      // 再生クライアントの取得\r
+      THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&render_client_)));\r
+    };\r
+\r
+    void init_io_client(boost::type<capture_client_policy>)\r
+    {\r
+      // 再生クライアントの取得\r
+      THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&capture_client_)));\r
+    };\r
+\r
+    void init_audio_client(WAVEFORMATEXTENSIBLE& wfx);\r
+    DrivenPolicy driven_policy_;\r
+    void get_default_audio_client();\r
+    void init(IMMDevicePtr device,wasapi_device_manager::device_info::params_t& params);\r
+    // IMMDeviceEnumeratorPtr device_enumerator_;\r
+    IMMDevicePtr current_device_;\r
+    IAudioClientPtr audio_client_;\r
+    IAudioRenderClientPtr render_client_;\r
+    IAudioCaptureClientPtr capture_client_;\r
+    IAudioClockPtr audio_clock2_;\r
+    //IAudioClockAdjustmentPtr audio_clock_adjustment_;\r
+    //handle_holder buffer_control_event_;\r
+    WAVEFORMATEXTENSIBLE mix_format_;\r
+    bool is_enabled_;\r
+    bool is_start_;\r
+    boost::shared_ptr<win32_error_exception> exception_holder_;\r
+    boost::uint32_t num_of_frames_;\r
+    boost::uint32_t buffer_size_;\r
+    uint64_t position_;\r
+    std::vector<short> tone_buffer_;\r
+    size_t buffer_in_periods_;//  = buffer_size_ / periods_per_buffer_;\r
+\r
+    // バッファ中の区切り数(レイテンシ時間が何個あるか)\r
+    static const uint32_t periods_per_buffer_ = 1;\r
+      //= mpl::if_c<boost::is_same<this_type,wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy> >::value,\r
+      //    mpl::int_<1>,mpl::int_<1> >::type::value;\r
+\r
+    // 再生レイテンシ\r
+    REFERENCE_TIME latency_;/* ms */\r
+    REFERENCE_TIME actual_latency_;\r
+  };\r
+\r
+  typedef wasapi_base<wasapi_shared_policy,wasapi_timer_policy> wasapi_shared_timer;\r
+  typedef wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy> wasapi_exclusive_timer;\r
+\r
+  typedef wasapi_base<wasapi_shared_policy,wasapi_event_policy> wasapi_shared_event;\r
+  typedef wasapi_base<wasapi_exclusive_policy,wasapi_event_policy> wasapi_exclusive_event;\r
+\r
+  typedef wasapi_base<wasapi_shared_policy,wasapi_timer_policy,capture_client_policy> wasapi_capture_shared_timer;\r
+  typedef wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,capture_client_policy> wasapi_capture_exclusive_timer;\r
+\r
+  typedef wasapi_base<wasapi_shared_policy,wasapi_event_policy,capture_client_policy> wasapi_capture_shared_event;\r
+  typedef wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy> wasapi_capture_exclusive_event;\r
+\r
+\r
+}\r
+\r
diff --git a/wasapi2/wasapi2.manifest b/wasapi2/wasapi2.manifest
new file mode 100644 (file)
index 0000000..47189d1
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\r
+\r
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">\r
+    <application>\r
+      <!--Windows 7-->\r
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />\r
+    </application>\r
+  </compatibility>\r
+  <dependency>\r
+      <dependentAssembly>\r
+          <assemblyIdentity type="win32"\r
+                name="Microsoft.Windows.Common-Controls"\r
+                version="6.0.0.0"\r
+                processorArchitecture="amd64"\r
+                publicKeyToken="6595b64144ccf1df"\r
+                language="*" />\r
+        \r
+    </dependentAssembly>\r
+  </dependency>\r
+</assembly>\r
diff --git a/wasapi2/wasapi2.rc b/wasapi2/wasapi2.rc
new file mode 100644 (file)
index 0000000..214d1cf
--- /dev/null
@@ -0,0 +1,121 @@
+// Generated by ResEdit 1.5.11\r
+// Copyright (C) 2006-2012\r
+// http://www.resedit.net\r
+\r
+#include <windows.h>\r
+#include <commctrl.h>\r
+#include <richedit.h>\r
+#include "resource.h"\r
+\r
+\r
+\r
+\r
+//\r
+// Dialog resources\r
+//\r
+LANGUAGE LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN\r
+IDD_CONFIG DIALOG 0, 0, 300, 200\r
+STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW | WS_SYSMENU\r
+FONT 9, "\83\81\83C\83\8a\83I"\r
+{\r
+    AUTOCHECKBOX    "\94r\91¼\83\82\81[\83h", IDC_EXC_MODE, 166, 20, 50, 8, 0, WS_EX_TRANSPARENT\r
+    COMBOBOX        IDC_ENDPOINT_DEVICE, 40, 3, 250, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    COMBOBOX        IDC_SAMPLE_BIT, 40, 18, 35, 12, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    LTEXT           "\8fo\97Í", IDC_STATIC, 7, 5, 15, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    LTEXT           "\83r\83b\83g\90\94", IDC_STATIC, 7, 20, 28, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    LTEXT           "\8eÀ\8dÛ\83r\83b\83g\90\94", IDC_STATIC, 77, 20, 42, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    COMBOBOX        IDC_VALID_SAMPLE_BITS, 124, 18, 40, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    COMBOBOX        IDC_SAMPLE_RATE, 124, 33, 40, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    LTEXT           "\8eü\94g\90\94", IDC_STATIC, 77, 35, 22, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    PUSHBUTTON      "\93K\97p", IDC_APPLY, 205, 175, 39, 14\r
+    PUSHBUTTON      "\83L\83\83\83\93\83Z\83\8b", IDC_CANCEL, 250, 175, 39, 14\r
+    LTEXT           "\83o\83b\83t\83@ms", IDC_STATIC, 166, 35, 39, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    COMBOBOX        IDC_CHANNEL, 40, 33, 35, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    LTEXT           "\83`\83\83\83l\83\8b", IDC_STATIC, 7, 35, 28, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    EDITTEXT        IDC_LATENCY, 206, 33, 25, 12, ES_AUTOHSCROLL\r
+    LTEXT           "Static", IDC_MIN_MAX_LATENCY, 232, 35, 68, 10, SS_LEFT\r
+    AUTOCHECKBOX    "\83C\83x\83\93\83g\83\82\81[\83h", IDC_EVENT_MODE, 218, 20, 64, 8, 0, WS_EX_TRANSPARENT\r
+    LTEXT           "\93ü\97Í", IDC_STATIC, 7, 50, 15, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    COMBOBOX        IDC_INPUT_ENDPOINT_DEVICE, 40, 50, 250, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    AUTOCHECKBOX    "\94r\91¼\83\82\81[\83h", IDC_INPUT_EXC_MODE, 166, 66, 50, 8, 0, WS_EX_TRANSPARENT\r
+    COMBOBOX        IDC_INPUT_SAMPLE_BIT, 40, 64, 35, 12, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    LTEXT           "\83r\83b\83g\90\94", IDC_STATIC, 7, 66, 28, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    LTEXT           "\8eÀ\8dÛ\83r\83b\83g\90\94", IDC_STATIC, 79, 66, 42, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    COMBOBOX        IDC_INPUT_VALID_SAMPLE_BITS, 124, 64, 40, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    COMBOBOX        IDC_INPUT_SAMPLE_RATE, 124, 79, 40, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    LTEXT           "\8eü\94g\90\94", IDC_STATIC, 79, 81, 22, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    LTEXT           "\83o\83b\83t\83@ms", IDC_STATIC, 166, 81, 39, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    COMBOBOX        IDC_INPUT_CHANNEL, 40, 79, 35, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS\r
+    LTEXT           "\83`\83\83\83l\83\8b", IDC_STATIC, 7, 81, 28, 8, SS_LEFT, WS_EX_TRANSPARENT\r
+    EDITTEXT        IDC_INPUT_LATENCY, 206, 79, 25, 12, ES_AUTOHSCROLL\r
+    AUTOCHECKBOX    "\83C\83x\83\93\83g\83\82\81[\83h", IDC_INPUT_EVENT_MODE, 218, 66, 64, 8, 0, WS_EX_TRANSPARENT\r
+    LTEXT           "Static", IDC_INPUT_MIN_MAX_LATENCY, 232, 81, 65, 10, SS_LEFT\r
+}\r
+\r
+\r
+\r
+LANGUAGE LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN\r
+IDD_INFO DIALOG 0, 0, 304, 200\r
+STYLE DS_CENTER | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW | WS_SYSMENU\r
+FONT 9, "\83\81\83C\83\8a\83I"\r
+{\r
+    LTEXT           "Static", IDC_INFO, 1, 2, 301, 99, SS_LEFT, WS_EX_TRANSPARENT\r
+    CONTROL         "", IDC_WAVEFORM, WC_STATIC, SS_BLACKFRAME, 1, 105, 301, 88\r
+}\r
+\r
+\r
+\r
+LANGUAGE LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN\r
+IDD_MAINDIALOG DIALOG 0, 0, 544, 285\r
+STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_GROUP | WS_TABSTOP | WS_THICKFRAME | WS_SYSMENU\r
+EXSTYLE WS_EX_WINDOWEDGE | WS_EX_APPWINDOW\r
+CAPTION "\94ñ\93¯\8aú\82Å\83t\83@\83C\83\8b\82ð\93Ç\82Ý\8d\9e\82Ý\81A\8dÄ\90\82·\82é\83e\83X\83g"\r
+FONT 9, "\83\81\83C\83\8a\83I"\r
+{\r
+    PUSHBUTTON      "\83t\83@\83C\83\8b", IDC_FILE, 5, 5, 40, 14\r
+    PUSHBUTTON      "\8dÄ\90¶", IDC_PLAY, 48, 5, 40, 14, WS_DISABLED\r
+    PUSHBUTTON      "\88ê\8e\9e\92â\8e~", IDC_PAUSE, 91, 5, 40, 14, WS_DISABLED\r
+    PUSHBUTTON      "\92â\8e~", IDC_STOP, 134, 5, 40, 14, WS_DISABLED\r
+    CONTROL         "", IDC_SLIDER, TRACKBAR_CLASS, WS_TABSTOP | WS_DISABLED | TBS_BOTH | TBS_NOTICKS, 2, 24, 535, 15\r
+    AUTOCHECKBOX    "\83\8a\83s\81[\83g", IDC_REPEAT_CHECK, 179, 8, 43, 8, WS_DISABLED\r
+    CONTROL         "", IDC_TAB, WC_TABCONTROL, 0, 5, 40, 535, 245\r
+}\r
+\r
+\r
+\r
+LANGUAGE LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN\r
+IDD_SEQ DIALOG 0, 0, 504, 284\r
+STYLE DS_CENTER | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW\r
+FONT 9, "\83\81\83C\83\8a\83I"\r
+{\r
+    EDITTEXT        IDC_EDIT1, 50, 5, 445, 12, NOT WS_BORDER | ES_AUTOHSCROLL | ES_WANTRETURN\r
+    LTEXT           "Song Name", IDC_STATIC, 5, 5, 45, 10, SS_LEFT\r
+    SCROLLBAR       IDC_SCROLLBAR1, 491, 95, 10, 174, SBS_VERT\r
+    LTEXT           "Comment", IDC_STATIC, 5, 15, 34, 8, SS_LEFT\r
+    EDITTEXT        IDC_EDIT2, 50, 15, 445, 12, NOT WS_BORDER | ES_AUTOHSCROLL\r
+    LTEXT           "Tempo", IDC_STATIC, 5, 25, 40, 10, SS_LEFT\r
+    EDITTEXT        IDC_EDIT3, 50, 25, 50, 12, NOT WS_BORDER | ES_AUTOHSCROLL\r
+    LTEXT           "Key", IDC_STATIC, 105, 25, 14, 8, SS_LEFT\r
+    EDITTEXT        IDC_EDIT4, 145, 25, 50, 12, NOT WS_BORDER | ES_AUTOHSCROLL\r
+    LTEXT           "Key", IDC_STATIC, 5, 40, 14, 8, SS_LEFT\r
+    CONTROL         "", IDC_SEQ_AREA, WC_STATIC, SS_BLACKFRAME, 39, 76, 434, 143\r
+}\r
+\r
+\r
+\r
+//\r
+// String Table resources\r
+//\r
+LANGUAGE LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN\r
+STRINGTABLE\r
+{\r
+    IDS_STRING1                   "\83T\83\93\83v\83\8b\83e\83L\83X\83g"\r
+}\r
+\r
+\r
+\r
+//\r
+// Icon resources\r
+//\r
+LANGUAGE LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN\r
+IDI_ICON1          ICON           "directx.ico"\r
diff --git a/wasapi2/wasapi2.vcxproj b/wasapi2/wasapi2.vcxproj
new file mode 100644 (file)
index 0000000..55be080
--- /dev/null
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{87DCF2CB-7B02-4B6D-9191-237065BDB69C}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>wasapi2</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="..\SF.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="..\SF.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>H:\libs\libsamplerate-0.1.8\src;H:\libs\libsamplerate-0.1.8\Win32;$(IncludePath)</IncludePath>
+    <LibraryPath>H:\libs\libsamplerate-0.1.8\Win32\src\x64\Debug;H:\libs\libsamplerate-0.1.8\Win32\src\x64\Release;H:\satoshi_documents\documents\Visual Studio 2012\Projects\boostlib\x64\Debug;$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>H:\libs\libsamplerate-0.1.8\src;$(IncludePath)</IncludePath>
+    <LibraryPath>H:\libs\libsamplerate-0.1.8\Win32\src\x64\Release;H:\satoshi_documents\documents\Visual Studio 2012\Projects\boostlib\boostlib\x64\Release;$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalOptions>/Zm200 %(AdditionalOptions)</AdditionalOptions>
+      <EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
+      <FloatingPointModel>Precise</FloatingPointModel>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <CompileAsWinRT>true</CompileAsWinRT>
+      <AdditionalUsingDirectories>C:\Program Files %28x86%29\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\Microsoft.VCLibs\11.0\References\CommonConfiguration\neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
+      <MinimalRebuild>false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>comctl32.lib;boostlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <Manifest>
+      <AdditionalManifestFiles>wasapi2.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles>
+    </Manifest>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <AdditionalOptions>/Zm200 %(AdditionalOptions)</AdditionalOptions>
+      <FloatingPointModel>Fast</FloatingPointModel>
+      <CompileAsWinRT>true</CompileAsWinRT>
+      <AdditionalUsingDirectories>C:\Program Files %28x86%29\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\Microsoft.VCLibs\11.0\References\CommonConfiguration\neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="application.cpp">
+      <AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">All</AssemblerOutput>
+    </ClCompile>
+    <ClCompile Include="config_tab_dialog.cpp" />
+    <ClCompile Include="info_tab_dialog.cpp" />
+    <ClCompile Include="input_thread.cpp" />
+    <ClCompile Include="mixer_thread.cpp" />
+    <ClCompile Include="output_thread.cpp" />
+    <ClCompile Include="reader_thread.cpp" />
+    <ClCompile Include="async_reader.cpp" />
+    <ClCompile Include="base_window.cpp" />
+    <ClCompile Include="code_converter.cpp" />
+    <ClCompile Include="dpi.cpp" />
+    <ClCompile Include="exception.cpp" />
+    <ClCompile Include="icon.cpp" />
+    <ClCompile Include="jumplist.cpp" />
+    <ClCompile Include="logger.cpp" />
+    <ClCompile Include="ring_buffer.cpp" />
+    <ClCompile Include="sample_rate_converter.cpp" />
+    <ClCompile Include="sequencer.cpp" />
+    <ClCompile Include="seq_tab_dialog.cpp" />
+    <ClCompile Include="sf_com.cpp" />
+    <ClCompile Include="sf_windows.cpp">
+      <AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NoListing</AssemblerOutput>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+      <ExpandAttributedSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExpandAttributedSource>
+      <AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NoListing</AssemblerOutput>
+    </ClCompile>
+    <ClCompile Include="tab_dialog.cpp" />
+    <ClCompile Include="taskbar.cpp" />
+    <ClCompile Include="thread_base.cpp" />
+    <ClCompile Include="timer.cpp" />
+    <ClCompile Include="toplevel_window.cpp" />
+    <ClCompile Include="wasapi_base.cpp" />
+    <ClCompile Include="wasapi_manager.cpp" />
+    <ClCompile Include="wavefile.cpp" />
+    <ClCompile Include="winmain.cpp" />
+    <ClCompile Include="writer_thread.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="application.h" />
+    <ClInclude Include="async_reader.h" />
+    <ClInclude Include="audio_base.h" />
+    <ClInclude Include="audio_filter.h" />
+    <ClInclude Include="audio_processor.h" />
+    <ClInclude Include="audio_source.h" />
+    <ClInclude Include="base_window.h" />
+    <ClInclude Include="code_converter.h" />
+    <ClInclude Include="config_tab_dialog.h" />
+    <ClInclude Include="dout.h" />
+    <ClInclude Include="dpi.h" />
+    <ClInclude Include="exception.h" />
+    <ClInclude Include="icon.h" />
+    <ClInclude Include="info_tab_dialog.h" />
+    <ClInclude Include="input_thread.h" />
+    <ClInclude Include="jumplist.h" />
+    <ClInclude Include="logger.h" />
+    <ClInclude Include="message_loop.h" />
+    <ClInclude Include="mixer_thread.h" />
+    <ClInclude Include="output_thread.h" />
+    <ClInclude Include="sequencer.h" />
+    <ClInclude Include="seq_tab_dialog.h" />
+    <ClInclude Include="tab_dialog.h" />
+    <ClInclude Include="thread_base.h" />
+    <ClInclude Include="reader_thread.h" />
+    <ClInclude Include="resource.h" />
+    <ClInclude Include="ring_buffer.h" />
+    <ClInclude Include="sample_rate_converter.h" />
+    <ClInclude Include="sf_com.h" />
+    <ClInclude Include="sf_memory.h" />
+    <ClInclude Include="sf_windows.h" />
+    <ClInclude Include="singleton.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="taskbar.h" />
+    <ClInclude Include="timer.h" />
+    <ClInclude Include="toplevel_window.h" />
+    <ClInclude Include="wasapi.h" />
+    <ClInclude Include="wavefile.h" />
+    <ClInclude Include="writer_thread.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="wasapi2.rc">
+      <Culture Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">0x0411</Culture>
+    </ResourceCompile>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/wasapi2/wasapi_base.cpp b/wasapi2/wasapi_base.cpp
new file mode 100644 (file)
index 0000000..e39d37a
--- /dev/null
@@ -0,0 +1,499 @@
+/*\r
+==============================================================================\r
+\r
+Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+\r
+#include "StdAfx.h"\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+#include "audio_base.h"\r
+#include "wasapi.h"\r
+\r
+using namespace std;\r
+\r
+namespace sf{\r
+\r
+  // ==================================\r
+  // コンストラクタ\r
+  // ==================================\r
+\r
+  // 共有/排他・タイマー・再生\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+    : is_enabled_(false),position_(0),is_start_(false),driven_policy_(latency_)\r
+  {\r
+    init(wasapi_device_manager::instance()->output_device_infos().at(device_index).device_ptr,params);\r
+  }\r
+\r
+  // 共有・イベント・再生\r
+  template<> \r
+  wasapi_base<wasapi_shared_policy,wasapi_event_policy,render_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+    : is_enabled_(false),position_(0),is_start_(false),driven_policy_()\r
+  {\r
+    init(wasapi_device_manager::instance()->output_device_infos().at(device_index).device_ptr,params);\r
+    audio_client_->SetEventHandle(driven_policy_.event_handle());\r
+  }\r
+\r
+  // 排他・イベント・再生\r
+  template<> \r
+  wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,render_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+    : is_enabled_(false),position_(0),is_start_(false),driven_policy_()\r
+  {\r
+    init(wasapi_device_manager::instance()->output_device_infos().at(device_index).device_ptr,params);\r
+    audio_client_->SetEventHandle(driven_policy_.event_handle());\r
+  }\r
+\r
+  // 共有・タイマ・キャプチャ\r
+  template<> \r
+  wasapi_base<wasapi_shared_policy,wasapi_timer_policy,capture_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+    : is_enabled_(false),position_(0),is_start_(false),driven_policy_(latency_)\r
+  {\r
+    init(wasapi_device_manager::instance()->input_device_infos().at(device_index).device_ptr,params);\r
+  }\r
+\r
+  // 排他・タイマ・キャプチャ\r
+  template<> \r
+  wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,capture_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+    : is_enabled_(false),position_(0),is_start_(false),driven_policy_(latency_)\r
+  {\r
+    init(wasapi_device_manager::instance()->input_device_infos().at(device_index).device_ptr,params);\r
+  }\r
+\r
+  // 共有・イベント・キャプチャ\r
+  template<> \r
+  wasapi_base<wasapi_shared_policy,wasapi_event_policy,capture_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+    : is_enabled_(false),position_(0),is_start_(false),driven_policy_()\r
+  {\r
+    init(wasapi_device_manager::instance()->input_device_infos().at(device_index).device_ptr,params);\r
+    audio_client_->SetEventHandle(driven_policy_.event_handle());\r
+  }\r
+\r
+  // 排他・イベント・キャプチャ\r
+  template<> \r
+  wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)\r
+    : is_enabled_(false),position_(0),is_start_(false),driven_policy_()\r
+  {\r
+    init(wasapi_device_manager::instance()->input_device_infos().at(device_index).device_ptr,params);\r
+    audio_client_->SetEventHandle(driven_policy_.event_handle());\r
+  }\r
+\r
+  // ========================================\r
+  // デフォルトのオーディオクライアントの取得\r
+  // ========================================\r
+\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::get_default_audio_client()\r
+  {\r
+\r
+    current_device_ = wasapi_device_manager::instance()->current_output_device().device_ptr;\r
+\r
+    // オーディオクライアントを取得\r
+    THROW_IF_ERR(\r
+      current_device_\r
+      ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+      NULL, reinterpret_cast<void **>(&audio_client_))\r
+      );\r
+  }\r
+\r
+  template<> \r
+  void wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>\r
+    ::get_default_audio_client()\r
+  {\r
+    current_device_ = wasapi_device_manager::instance()->current_input_device().device_ptr;\r
+    // オーディオクライアントを取得\r
+    THROW_IF_ERR(\r
+      current_device_\r
+      ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+      NULL, reinterpret_cast<void **>(&audio_client_))\r
+      );\r
+  }\r
+\r
+  // ==================================\r
+  // 初期化\r
+  // ==================================\r
+\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::init(IMMDevicePtr device,wasapi_device_manager::device_info::params_t& params)\r
+  {\r
+    WAVEFORMATEXTENSIBLE wfx;\r
+    bits_pair bits = {params.bits,params.valid_bits};\r
+    make_wave_format(wfx,params.sample_rate,params.channel,bits);\r
+    latency_ =  params.latency;//wasapi_device_manager::instance()->current_output_device().latency_default;\r
+\r
+    // 代替フォーマット定義\r
+    sf::co_task_memory<WAVEFORMATEX>  alt_format;\r
+\r
+    THROW_IF_ERR(\r
+      device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+      NULL, reinterpret_cast<void **>(&audio_client_))\r
+      );\r
+    \r
+    current_device_ = device;\r
+\r
+    // 読みこもうとしているWAVファイルのフォーマットをサポートしているか?\r
+    THROW_IF_ERR(audio_client_->IsFormatSupported(\r
+      ShareModePolicy::SHARE_MODE ,&wfx.Format,&alt_format));\r
+    //if(hr != S_OK) //  S_FALSEならそのフォーマットをサポートしていないらしい..\r
+    //{\r
+    //  // サンプルレートのコンバート\r
+    //  if(alt_format->nSamplesPerSec != wfx.Format.nSamplesPerSec)\r
+    //  {\r
+    //    // 本来のサンプルレートをバックアップする\r
+    //    sample_rate_backup = wfx.Format.nSamplesPerSec;\r
+    //    // 代替フォーマットのサンプルレートをセットする\r
+    //    wfx.Format.nSamplesPerSec = alt_format->nSamplesPerSec;\r
+    //    // 再計算する\r
+    //    wfx.Format.nAvgBytesPerSec = alt_format->nSamplesPerSec * wfx.Format.nBlockAlign;\r
+    //    // もう一回チェックする。\r
+    //    // サンプルレート以外でサポートしていない点があれば例外が発生する。\r
+    //    THROW_IF_ERR(audio_client_->IsFormatSupported(\r
+    //      ShareModePolicy::SHARE_MODE ,&wfx.Format,&alt_format));\r
+    //    // フラグをセットする\r
+    //    //          sample_rate_convert = true;\r
+    //  } else {\r
+    //    // サンプルレート以外であれば例外を出す。\r
+    //    throw win32_error_exception(hr);\r
+    //  }\r
+    //}\r
+\r
+    // クライアントの初期化\r
+\r
+    try {\r
+      init_audio_client(wfx);\r
+    } catch (win32_error_exception& e)\r
+    {\r
+      if(e.hresult() == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)\r
+      {\r
+        THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));\r
+        latency_ = actual_latency_ = \r
+        (double)10000000 * (buffer_size_) / wfx.Format.nSamplesPerSec;\r
+        audio_client_.Release();\r
+        THROW_IF_ERR(\r
+          device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+          NULL, reinterpret_cast<void **>(&audio_client_))\r
+          );\r
+        init_audio_client(wfx);\r
+\r
+      } else {\r
+        throw;\r
+      }\r
+    }\r
+    actual_latency_ = latency_;\r
+\r
+    // バッファサイズの取得\r
+    THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));\r
+\r
+    init_io_client(boost::type<IOClientPolicy>());\r
+\r
+    // Audio Clock 2\r
+    THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_clock2_)));\r
+    REFERENCE_TIME psl;\r
+    THROW_IF_ERR(audio_client_->GetStreamLatency(&psl));\r
+#ifdef _DEBUG\r
+    wdout << L"StreamLatency:" << psl << endl;\r
+#endif\r
+    //      wdout\r
+\r
+    // サンプルレートコンバータ\r
+    //if(sample_rate_convert)\r
+    //{\r
+    //  THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_clock_adjustment_)));\r
+    //  // 本来のサンプルレートをセットする\r
+    //  audio_clock_adjustment_->SetSampleRate(sample_rate_backup);\r
+    //}\r
+\r
+    num_of_frames_ = wfx.Format.nBlockAlign;\r
+    mix_format_ = wfx;\r
+    //inc_  = (buffer_size_ * num_of_frames_) / (sizeof(short) * periods_per_buffer_);\r
+    buffer_in_periods_ = buffer_size_ / periods_per_buffer_;\r
+\r
+    is_enabled_ = true;\r
+  }\r
+\r
+  // =========================\r
+  // AudioClientの初期化\r
+  // =========================\r
+  // デフォルト\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)\r
+  {\r
+      REFERENCE_TIME buffer_duration =  latency_;\r
+\r
+      THROW_IF_ERR(audio_client_->Initialize(ShareModePolicy::SHARE_MODE  , \r
+      AUDCLNT_STREAMFLAGS_NOPERSIST | DrivenPolicy::STREAM_FLAG /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/, \r
+      buffer_duration, \r
+      0,\r
+      &(wfx.Format), \r
+      NULL));\r
+  }\r
+\r
+  // 排他・イベント・出力\r
+  template<> \r
+  void wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,render_client_policy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)\r
+  {\r
+    REFERENCE_TIME buffer_duration =  latency_;\r
+\r
+    THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE  , \r
+      AUDCLNT_STREAMFLAGS_NOPERSIST | wasapi_event_policy::STREAM_FLAG /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/, \r
+      buffer_duration, \r
+      buffer_duration,\r
+      &(wfx.Format), \r
+      NULL));  \r
+  }\r
+\r
+  // 排他・タイマー・出力\r
+  template<> \r
+  void wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,render_client_policy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)\r
+  {\r
+    REFERENCE_TIME buffer_period =  latency_;\r
+    REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;\r
+\r
+    THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE  , \r
+      AUDCLNT_STREAMFLAGS_NOPERSIST /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/, \r
+      buffer_duration, \r
+      buffer_period,\r
+      &(wfx.Format), \r
+      NULL));  \r
+  }\r
+\r
+  // 排他・イベント・キャプチャ\r
+  template<> \r
+  void wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)\r
+  {\r
+    REFERENCE_TIME buffer_duration =  latency_;\r
+\r
+    THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE  , \r
+      AUDCLNT_STREAMFLAGS_NOPERSIST | wasapi_event_policy::STREAM_FLAG /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/, \r
+      buffer_duration, \r
+      buffer_duration,\r
+      &(wfx.Format), \r
+      NULL));  \r
+  }\r
+\r
+  // 排他・タイマー・キャプチャ\r
+  template<> \r
+  void wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,capture_client_policy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)\r
+  {\r
+    REFERENCE_TIME buffer_period =  latency_;\r
+    REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;\r
+\r
+    THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE  , \r
+      AUDCLNT_STREAMFLAGS_NOPERSIST /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/, \r
+      buffer_duration, \r
+      buffer_period,\r
+      &(wfx.Format), \r
+      NULL));  \r
+  }\r
+  // ================================\r
+  // デストラクタ\r
+  // ================================\r
+  // デフォルト\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>\r
+  wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::~wasapi_base()\r
+  {\r
+    //    safe_release(audio_clock_adjustment_);\r
+\r
+    // WASAPIの終了処理\r
+    if(audio_client_)\r
+    {\r
+      audio_client_->Stop();\r
+      audio_client_->Reset();\r
+      audio_client_.Release();\r
+    }\r
+    safe_release(render_client_);\r
+    safe_release(capture_client_);\r
+    safe_release(current_device_);\r
+    //    safe_release(device_enumerator_);\r
+  }\r
+\r
+  // ================================\r
+  // テスト用サイン波形テーブルの作成\r
+  // ================================\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::create_wave_data(){\r
+    // サイン波の生成\r
+    boost::uint32_t buffer_size_in_bytes = buffer_size_ * mix_format_.Format.nBlockAlign;\r
+    size_t render_data_length = mix_format_.Format.nSamplesPerSec * 10 /* 秒 */ * mix_format_.Format.nBlockAlign / sizeof(short);\r
+    tone_buffer_.reserve(render_data_length);\r
+\r
+    double sampleIncrement = (440 /* Hz */ * (M_PI * 2.0)) / (double)mix_format_.Format.nSamplesPerSec;\r
+    double theta = 0.0;\r
+\r
+    for (size_t i = 0 ; i < render_data_length ; i += mix_format_.Format.nChannels)\r
+    {\r
+      double sinValue = sin( theta );\r
+      for(size_t j = 0 ;j < mix_format_.Format.nChannels; j++)\r
+      {\r
+        tone_buffer_.push_back((short)(sinValue * _I16_MAX));\r
+      }\r
+      theta += sampleIncrement;\r
+    }\r
+  };\r
+\r
+  // ===========================\r
+  // バッファを取得する\r
+  // ===========================\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  uint32_t wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::get_buffer(BYTE** buffer,uint32_t size)\r
+  {\r
+\r
+    uint32_t padding;\r
+    uint32_t frames_available;\r
+\r
+    THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));\r
+    frames_available = size - padding;\r
+    THROW_IF_ERR(render_client_->GetBuffer(frames_available,buffer));\r
+    return frames_available;\r
+  }\r
\r
+  // 排他・イベント・出力\r
+  template<> \r
+  uint32_t wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,render_client_policy>::get_buffer(BYTE** buffer,uint32_t size)\r
+  {\r
+    THROW_IF_ERR(render_client_->GetBuffer(size,buffer));\r
+    return size;\r
+  }\r
+\r
+  // キャプチャ ---------------------------------\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  uint32_t wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::get_buffer(BYTE** buffer)\r
+  {\r
+    UINT32 size;\r
+    DWORD flags;\r
+    HRESULT hr = capture_client_->GetBuffer(buffer,&size,&flags,0,0);\r
+    if(hr == AUDCLNT_S_BUFFER_EMPTY)\r
+    {\r
+      buffer = 0;\r
+      size = 0;\r
+    } else {\r
+      THROW_IF_ERR(hr);\r
+    }\r
+\r
+    if(flags == AUDCLNT_BUFFERFLAGS_SILENT)\r
+    {\r
+      buffer = 0;\r
+      size = 0;\r
+    }\r
+    return size;\r
+  }\r
+\r
+  // ===========================\r
+  // バッファのリリース\r
+  // ===========================\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::release_buffer(uint32_t  num_byte_written)\r
+  {\r
+    THROW_IF_ERR(render_client_->ReleaseBuffer(num_byte_written,0));\r
+  }\r
+\r
+  template<> \r
+  void wasapi_base<wasapi_shared_policy,wasapi_event_policy,capture_client_policy>::release_buffer(uint32_t  num_byte_written)\r
+  {\r
+    THROW_IF_ERR(capture_client_->ReleaseBuffer(num_byte_written));\r
+  }\r
+\r
+  template<> \r
+  void wasapi_base<wasapi_shared_policy,wasapi_timer_policy,capture_client_policy>::release_buffer(uint32_t  num_byte_written)\r
+  {\r
+    THROW_IF_ERR(capture_client_->ReleaseBuffer(num_byte_written));\r
+  }\r
+\r
+  template<> \r
+  void wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>::release_buffer(uint32_t  num_byte_written)\r
+  {\r
+    THROW_IF_ERR(capture_client_->ReleaseBuffer(num_byte_written));\r
+  }\r
+\r
+  template<> \r
+  void wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,capture_client_policy>::release_buffer(uint32_t  num_byte_written)\r
+  {\r
+    THROW_IF_ERR(capture_client_->ReleaseBuffer(num_byte_written));\r
+  }\r
+\r
+  // ===========================\r
+  // バッファのスタート\r
+  // ===========================\r
+\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::start()\r
+  {\r
+    THROW_IF_ERR(audio_client_->Start());\r
+    is_start_ = true;\r
+  }\r
+\r
+  // ===========================\r
+  // バッファのリセット\r
+  // ===========================\r
+\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+    void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::reset()\r
+  {\r
+    THROW_IF_ERR(audio_client_->Reset());\r
+  }\r
+\r
+  // ===========================\r
+  // バッファの停止\r
+  // ===========================\r
+\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::stop() {\r
+    //再生停止\r
+    if(is_start_)\r
+    {\r
+      THROW_IF_ERR(audio_client_->Stop());\r
+      reset();\r
+      is_start_ = false;\r
+\r
+    };\r
+  }\r
+\r
+  // ===========================\r
+  // パディングの取得\r
+  // ===========================\r
+\r
+  template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy> \r
+  uint32_t wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::get_current_padding()\r
+  {\r
+    uint32_t padding;\r
+    THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));\r
+    return padding;\r
+  }\r
+\r
+  template<> \r
+  uint32_t wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,render_client_policy>::get_current_padding()\r
+  {\r
+    return buffer_size_;\r
+  }\r
+\r
+  template struct wasapi_base<>;\r
+  template struct wasapi_base<wasapi_shared_policy,wasapi_event_policy>;\r
+  template struct wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy>;\r
+  template struct wasapi_base<wasapi_exclusive_policy,wasapi_event_policy>;\r
+  template struct wasapi_base<wasapi_shared_policy,wasapi_timer_policy,capture_client_policy>;\r
+  template struct wasapi_base<wasapi_shared_policy,wasapi_event_policy,capture_client_policy>;\r
+  template struct wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,capture_client_policy>;\r
+  template struct wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>;\r
+\r
+}\r
+\r
+\r
diff --git a/wasapi2/wasapi_exclusive_timer.cpp b/wasapi2/wasapi_exclusive_timer.cpp
new file mode 100644 (file)
index 0000000..f897407
--- /dev/null
@@ -0,0 +1,248 @@
+/*\r
+  ==============================================================================\r
+\r
+   Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+#include "StdAfx.h"\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+#include "sf_memory.h"\r
+#include "audio_base.h"\r
+#include "wasapi.h"\r
+\r
+using namespace std;\r
+\r
+namespace sf{\r
+\r
+  wasapi_exclusive_timer::wasapi_exclusive_timer(int device_index,wasapi_device_manager::device_info::current_device_params& params)\r
+    : is_enabled_(false),position_(0),is_start_(false)\r
+  {\r
+    current_device_ = wasapi_device_manager::instance()->output_device_infos().at(device_index).device_ptr;\r
+    // オーディオクライアントを取得\r
+    THROW_IF_ERR(\r
+      current_device_\r
+      ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+      NULL, reinterpret_cast<void **>(&audio_client_))\r
+      );\r
+    WAVEFORMATEXTENSIBLE w;\r
+    bits_pair bits = {params.bits,params.valid_bits};\r
+    make_wave_format(w,params.sample_rate,params.channel,bits);\r
+    latency_ =  params.latency;//wasapi_device_manager::instance()->current_output_device().latency_default;\r
+    init(w);\r
+  }\r
+\r
+  wasapi_exclusive_timer::wasapi_exclusive_timer()\r
+    : is_enabled_(false),position_(0),is_start_(false)\r
+  {\r
+    co_task_memory<WAVEFORMATEX> wfx;\r
+    get_default_audio_client();\r
+    WAVEFORMATEXTENSIBLE w;\r
+    wasapi_device_manager::device_info::current_device_params& params(wasapi_device_manager::instance()->current_input_device().current_params);\r
+    bits_pair bits = {params.bits,params.valid_bits};\r
+    make_wave_format(w,params.sample_rate,params.channel,bits);\r
+    latency_ =  wasapi_device_manager::instance()->current_output_device().latency_default;\r
+\r
+    //uint64_t freq;\r
+    //audio_client_->GetMixFormat(&wfx);\r
+    //WAVEFORMATEXTENSIBLE* w(reinterpret_cast<WAVEFORMATEXTENSIBLE*>(wfx.get())); \r
+    //w->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;\r
+    //w->Format.wBitsPerSample = 16;\r
+    //w->Format.nBlockAlign = (w->Format.wBitsPerSample / 8) * w->Format.nChannels;\r
+    //w->Format.nAvgBytesPerSec = w->Format.nSamplesPerSec  *w->Format.nBlockAlign;\r
+    //w->Samples.wValidBitsPerSample = 16;\r
+    init(w);\r
+  }\r
+\r
+  void wasapi_exclusive_timer::get_default_audio_client()\r
+  {\r
+      //// IMMDeviceEnumeratorの取得\r
+      //THROW_IF_ERR(\r
+      //  CoCreateInstance(\r
+      //  __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,\r
+      //  IID_PPV_ARGS(&device_enumerator_)));\r
+\r
+      //// デフォルトのオーディオデバイスを取得する\r
+      //THROW_IF_ERR(\r
+      //  device_enumerator_\r
+      //  ->GetDefaultAudioEndpoint(eRender,eMultimedia,&current_device_)\r
+      //  );\r
+\r
+      current_device_ = wasapi_device_manager::instance()->current_output_device().device_ptr;\r
+\r
+      // オーディオクライアントを取得\r
+      THROW_IF_ERR(\r
+        current_device_\r
+        ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+        NULL, reinterpret_cast<void **>(&audio_client_))\r
+        );\r
+  }\r
+\r
+  void wasapi_exclusive_timer::init(::WAVEFORMATEXTENSIBLE& wfx)\r
+  {\r
+      // 代替フォーマット定義\r
+      sf::co_task_memory<WAVEFORMATEX>  alt_format;\r
+\r
+      // 読みこもうとしているWAVファイルのフォーマットをサポートしているか?\r
+      HRESULT hr = audio_client_->IsFormatSupported(\r
+        AUDCLNT_SHAREMODE_EXCLUSIVE ,&wfx.Format,&alt_format);\r
+      \r
+      // 再生クライアントの初期化\r
+      REFERENCE_TIME buffer_period =  latency_ ;\r
+\r
+      REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;\r
+\r
+      THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE  , \r
+        AUDCLNT_STREAMFLAGS_NOPERSIST, \r
+        buffer_duration, \r
+        buffer_period,\r
+        &(wfx.Format), \r
+        NULL));\r
+\r
+      REFERENCE_TIME psl;\r
+      THROW_IF_ERR(audio_client_->GetStreamLatency(&psl));\r
+#ifdef _DEBUG\r
+      wdout << L"StreamLatency:" << psl << endl;\r
+#endif\r
+\r
+      // バッファサイズの取得\r
+      THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));\r
+\r
+      // 再生クライアントの取得\r
+      THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_render_client_)));\r
+\r
+\r
+      num_of_frames_ = wfx.Format.nBlockAlign;\r
+      mix_format_ = wfx;\r
+      buffer_in_periods_ = buffer_size_ / periods_per_buffer_;\r
+\r
+      is_enabled_ = true;\r
+  }\r
+\r
+  wasapi_exclusive_timer::wasapi_exclusive_timer(::WAVEFORMATEXTENSIBLE& wfx) \r
+    : is_enabled_(false),position_(0),is_start_(false)/*,buffer_control_event_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE))*/\r
+  {\r
+\r
+    try {\r
+      //      thread_priority_.set_priority(AVRT_PRIORITY_NORMAL);\r
+\r
+      // WASAPIの初期化処理\r
+\r
+      get_default_audio_client();\r
+      init(wfx);\r
+\r
+    } catch (win32_error_exception& e)\r
+    {\r
+      exception_holder_.reset(new win32_error_exception(e.hresult()));\r
+      is_enabled_ = false;\r
+    } catch(...) {\r
+      is_enabled_ = false;\r
+    }\r
+  }\r
+\r
+  wasapi_exclusive_timer::~wasapi_exclusive_timer()\r
+  {\r
+//    safe_release(audio_clock_adjustment_);\r
+\r
+    // WASAPIの終了処理\r
+    if(audio_client_)\r
+    {\r
+      audio_client_->Stop();\r
+      audio_client_->Reset();\r
+      safe_release(audio_render_client_);\r
+      audio_client_.Release();\r
+    }\r
+\r
+    safe_release(current_device_);\r
+//    safe_release(device_enumerator_);\r
+  }\r
+\r
+  void wasapi_exclusive_timer::play_buffer(BYTE* source_buffer)\r
+  {\r
+    BYTE* buffer;\r
+\r
+    if(!is_start_)\r
+    {\r
+\r
+      // 最初にバッファを埋める\r
+      THROW_IF_ERR(audio_render_client_->GetBuffer(buffer_size_,&buffer));\r
+      ::CopyMemory(buffer,source_buffer,get_buffer_byte_size());\r
+\r
+      // レイテンシ時間*バッファ数分進める\r
+      THROW_IF_ERR(audio_render_client_->ReleaseBuffer(buffer_size_,0));\r
+\r
+      // 再生開始\r
+      THROW_IF_ERR(audio_client_->Start());\r
+      is_start_ = true;\r
+      return;\r
+    }\r
+\r
+\r
+    // レイテンシ時間だけ待つ\r
+    Sleep(latency_ / 10000 );\r
+\r
+    uint32_t padding;\r
+    uint32_t frames_available;\r
+    uint32_t count_period = periods_per_buffer_;\r
+    while(count_period > 0)\r
+    {\r
+      // パディングを求める。\r
+      THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));\r
+      frames_available = buffer_size_ - padding;\r
+\r
+      // パディングを除いた部分のバッファを埋める。\r
+      // パディングを除いた部分のサイズがbuffer_in_periods_より小さい場合はつぎにまわす。\r
+      // パディングを除いた部分を一気に埋めようとしたけどできなかった。。\r
+      while(buffer_in_periods_ <= frames_available && count_period > 0 ) \r
+      {\r
+        THROW_IF_ERR(audio_render_client_->GetBuffer(buffer_in_periods_,&buffer));\r
+        ::CopyMemory(buffer,source_buffer,buffer_in_periods_ *  num_of_frames_);\r
+        THROW_IF_ERR(audio_render_client_->ReleaseBuffer(buffer_in_periods_,0));\r
+        // レイテンシ時間だけ進める\r
+        source_buffer += buffer_in_periods_ * num_of_frames_;\r
+        --count_period;\r
+        // パディングを再度求める\r
+        THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));\r
+        frames_available = buffer_size_ - padding;\r
+      }\r
+\r
+      if(count_period > 0)\r
+      {\r
+        Sleep(latency_ / 10000);\r
+      }\r
+    }\r
+  }\r
+  void wasapi_exclusive_timer::reset()\r
+  {\r
+    THROW_IF_ERR(audio_client_->Reset());\r
+  }\r
+  void wasapi_exclusive_timer::stop() {\r
+    //再生停止\r
+    if(is_start_)\r
+    {\r
+      THROW_IF_ERR(audio_client_->Stop());\r
+      reset();\r
+      is_start_ = false;\r
+\r
+    };\r
+  }\r
+}\r
diff --git a/wasapi2/wasapi_manager.cpp b/wasapi2/wasapi_manager.cpp
new file mode 100644 (file)
index 0000000..a4ae8ff
--- /dev/null
@@ -0,0 +1,422 @@
+/*\r
+  ==============================================================================\r
+\r
+   Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+#include "StdAfx.h"\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+#include "sf_memory.h"\r
+#include "audio_base.h"\r
+#include "wasapi.h"\r
+#include "application.h"\r
+using namespace boost;\r
+using namespace std;\r
+namespace sf {\r
+  const int wasapi_device_manager::sample_rates[NUM_SAMPLE_RATE] = {8000,11025,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000};\r
+  const bits_pair wasapi_device_manager::sample_bits[NUM_SAMPLE_BITS] = {{8,8},{16,16},{24,24},{32,24},{32,32},{32,WAVE_FORMAT_IEEE_FLOAT}};\r
+\r
+  void make_wave_format(WAVEFORMATEXTENSIBLE& format,int sample_rate,int channels,bits_pair b,uint32_t type,const GUID&  sub_type)\r
+  {\r
+    ZeroMemory(&format,sizeof(WAVEFORMATEXTENSIBLE));\r
+    format.Format.wFormatTag = type;\r
+    format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);\r
+    format.SubFormat = sub_type;\r
+    format.Format.nSamplesPerSec = sample_rate;\r
+    format.Format.nChannels = channels;\r
+    format.Format.wBitsPerSample = b.bits_per_sample;\r
+    format.Format.nBlockAlign = (format.Format.wBitsPerSample / 8) * format.Format.nChannels;\r
+    format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec  * format.Format.nBlockAlign;\r
+    format.Samples.wValidBitsPerSample = b.valid_bits_per_sample;\r
+\r
+    format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;\r
+  };\r
+\r
+  void make_wave_format(WAVEFORMATEX& format,int sample_rate,int channels,int bits,uint32_t type)\r
+  {\r
+    ZeroMemory(&format,sizeof(WAVEFORMATEX));\r
+    format.wFormatTag = type;\r
+    format.nSamplesPerSec = sample_rate;\r
+    format.nChannels = channels;\r
+    format.wBitsPerSample = bits;\r
+    format.nBlockAlign = (format.wBitsPerSample / 8) * format.nChannels;\r
+    format.nAvgBytesPerSec = format.nSamplesPerSec  * format.nBlockAlign;\r
+  };\r
+\r
+  struct prop_variant \r
+  {\r
+    prop_variant()\r
+    {\r
+      PropVariantInit(&value_);\r
+    }\r
+\r
+    ~prop_variant()\r
+    {\r
+      PropVariantClear(&value_);\r
+    }\r
+\r
+    PROPVARIANT* get(){ return &value_;};\r
+\r
+    PROPVARIANT* operator &(){return get();}\r
+\r
+    operator PROPVARIANT*() {return get();}\r
+\r
+  private:\r
+    PROPVARIANT value_;\r
+  };\r
+\r
+wasapi_device_manager::wasapi_device_manager() \r
+  : output_device_index_(0),input_device_index_(0)\r
+{\r
+  wstring p = application::instance()->base_directory() + L"\\wasapi_device_manager.config.xml";\r
+  filesystem::wpath config_path(p);\r
+\r
+  std::wstring output_id;\r
+  std::wstring input_id;\r
+\r
+  if(filesystem::exists(config_path))\r
+  {\r
+    try {\r
+      filesystem::wifstream f(config_path);\r
+      archive::xml_wiarchive ar(f);\r
+      ar & boost::serialization::make_nvp("output_device_id",output_id);\r
+      ar & boost::serialization::make_nvp("input_device_id" ,input_id);\r
+    } catch(...)\r
+    {\r
+      output_id = input_id = L"";\r
+      filesystem::remove(config_path);\r
+    }\r
+  }\r
+\r
+  // IMMDeviceEnumeratorの取得\r
+  THROW_IF_ERR(\r
+    CoCreateInstance(\r
+    __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,\r
+    IID_PPV_ARGS(&device_enumerator_)));\r
+\r
+  // 出力エンドポイントの取得\r
+  output_device_index_ = get_device_infos(eRender,output_device_infos_,output_id);\r
+\r
+  // 出力エンドポイントの能力を調査する\r
+  for(int d = 0;d < output_device_infos_.size();++d)\r
+  {\r
+    IAudioClientPtr c;\r
+    // オーディオクライアントを取得\r
+    THROW_IF_ERR(\r
+      output_device_infos_[d].device_ptr\r
+      ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+      NULL, reinterpret_cast<void **>(&c))\r
+      );          \r
+\r
+    c->GetDevicePeriod(&(output_device_infos_[d].latency_default),&(output_device_infos_[d].latency_minimum));\r
+    if(output_device_infos_[d].params.latency == 0 \r
+      || output_device_infos_[d].params.latency < output_device_infos_[d].latency_minimum )\r
+    {\r
+      output_device_infos_[d].params.latency = output_device_infos_[d].latency_default;\r
+    }\r
+\r
+#ifdef _DEBUG\r
+    wdout << output_device_infos_[d].device_friendly_name << endl;\r
+    wdout << wformat(L"latency default:%d min:%d") % output_device_infos_[d].latency_default % output_device_infos_[d].latency_minimum << endl;\r
+#endif\r
+    for(int bits = 0;bits < NUM_SAMPLE_BITS;++bits)\r
+    {\r
+      for(int channel = 1;channel < 3;++channel)\r
+      {\r
+        for(int rate = 0;rate < NUM_SAMPLE_RATE;++rate)\r
+        {\r
+          sf::co_task_memory<WAVEFORMATEXTENSIBLE>  a,a1;\r
+          WAVEFORMATEXTENSIBLE f;\r
+\r
+//            make_wave_fomat(f,sample_rates[rate],channel,sample_bits[bits]);\r
+          if(sample_bits[bits].valid_bits_per_sample == WAVE_FORMAT_IEEE_FLOAT)\r
+          {\r
+            bits_pair b ={sample_bits[bits].bits_per_sample,sample_bits[bits].bits_per_sample};\r
+            make_wave_format(f,sample_rates[rate],channel,b,WAVE_FORMAT_EXTENSIBLE,KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);\r
+          } else {\r
+            make_wave_format(f,sample_rates[rate],channel,sample_bits[bits],WAVE_FORMAT_EXTENSIBLE,KSDATAFORMAT_SUBTYPE_PCM);\r
+          }\r
+\r
+          // 排他モード\r
+          HRESULT hr = c->IsFormatSupported(\r
+            AUDCLNT_SHAREMODE_EXCLUSIVE,reinterpret_cast<WAVEFORMATEX*>(&f),reinterpret_cast<WAVEFORMATEX**>(&a));\r
+          if(hr == S_OK){\r
+            output_device_infos_[d].support_formats[AUDCLNT_SHAREMODE_EXCLUSIVE][ sample_bits[bits].bits_per_sample ][sample_bits[bits].valid_bits_per_sample][channel][sample_rates[rate]] = 0;\r
+#ifdef _DEBUG\r
+            wdout << wformat(L"|exc  |bits:%02d|vbits:%02d|channel:%02d|rate:%06d|%s|") % sample_bits[bits].bits_per_sample % sample_bits[bits].valid_bits_per_sample % channel % sample_rates[rate] % (hr == S_OK?L"OK":L"NG") << endl;\r
+#endif            }\r
+\r
+          // make_wave_format(f,sample_rates[rate],channel,sample_bits[bits],WAVE_FORMAT_EXTENSIBLE);\r
+          // 共有モード\r
+          hr = c->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,reinterpret_cast<WAVEFORMATEX*>(&f),reinterpret_cast<WAVEFORMATEX**>(&a1));\r
+          if(hr == S_OK){\r
+            output_device_infos_[d]\r
+              .support_formats\r
+                [AUDCLNT_SHAREMODE_SHARED]\r
+                [ sample_bits[bits].bits_per_sample ]\r
+                [sample_bits[bits].valid_bits_per_sample]\r
+                [channel][sample_rates[rate]] \r
+                = 0;\r
+#ifdef _DEBUG\r
+            wdout << wformat(L"|share|bits:%02d|vbits:%02d|channel:%02d|rate:%06d|%s|")\r
+              % sample_bits[bits].bits_per_sample \r
+              % sample_bits[bits].valid_bits_per_sample \r
+              % channel % sample_rates[rate] \r
+              % (hr == S_OK?L"OK":L"NG") << endl;\r
+\r
+#endif\r
+          }\r
+        }\r
+      }\r
+    }\r
+#ifdef _DEBUG\r
+    wdout << "-------------------------------" << std::endl;\r
+#endif\r
+    }\r
+    safe_release(c);\r
+  }\r
+\r
+  // 入力エンドポイントの取得\r
+  input_device_index_ = get_device_infos(eCapture,input_device_infos_,input_id);\r
+  // 出力エンドポイントの能力を調査する\r
+  for(int d = 0;d < input_device_infos_.size();++d)\r
+  {\r
+    IAudioClientPtr c;\r
+    // オーディオクライアントを取得\r
+    THROW_IF_ERR(\r
+      input_device_infos_[d].device_ptr\r
+      ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,\r
+      NULL, reinterpret_cast<void **>(&c))\r
+      );          \r
+\r
+    c->GetDevicePeriod(&(input_device_infos_[d].latency_default),&(input_device_infos_[d].latency_minimum));\r
+    if(input_device_infos_[d].params.latency == 0 || input_device_infos_[d].params.latency < input_device_infos_[d].latency_minimum ){\r
+      input_device_infos_[d].params.latency = input_device_infos_[d].latency_default;\r
+    }\r
+\r
+#ifdef _DEBUG\r
+    wdout << input_device_infos_[d].device_friendly_name << endl;\r
+    wdout << wformat(L"latency default:%d min:%d") % input_device_infos_[d].latency_default % input_device_infos_[d].latency_minimum << endl;\r
+#endif\r
+    for(int bits = 0;bits < NUM_SAMPLE_BITS;++bits)\r
+    {\r
+      for(int channel = 1;channel < 3;++channel)\r
+      {\r
+        for(int rate = 0;rate < NUM_SAMPLE_RATE;++rate)\r
+        {\r
+          sf::co_task_memory<WAVEFORMATEXTENSIBLE>  a,a1;\r
+          WAVEFORMATEXTENSIBLE f;\r
+\r
+          // make_wave_fomat(f,sample_rates[rate],channel,sample_bits[bits]);\r
+          if(sample_bits[bits].valid_bits_per_sample == WAVE_FORMAT_IEEE_FLOAT)\r
+          {\r
+            bits_pair b ={sample_bits[bits].bits_per_sample,sample_bits[bits].bits_per_sample};\r
+            make_wave_format(f,sample_rates[rate],channel,b,WAVE_FORMAT_EXTENSIBLE,KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);\r
+          } else {\r
+            make_wave_format(f,sample_rates[rate],channel,sample_bits[bits],WAVE_FORMAT_EXTENSIBLE,KSDATAFORMAT_SUBTYPE_PCM);\r
+          }\r
+\r
+          // 排他モード\r
+          HRESULT hr = c->IsFormatSupported(\r
+            AUDCLNT_SHAREMODE_EXCLUSIVE,reinterpret_cast<WAVEFORMATEX*>(&f),reinterpret_cast<WAVEFORMATEX**>(&a));\r
+          if(hr == S_OK){\r
+            input_device_infos_[d]\r
+            .support_formats\r
+              [AUDCLNT_SHAREMODE_EXCLUSIVE]\r
+              [ sample_bits[bits].bits_per_sample ]\r
+              [sample_bits[bits].valid_bits_per_sample]\r
+              [channel]\r
+              [sample_rates[rate]] = 0;\r
+#ifdef _DEBUG\r
+            wdout << wformat(L"|exc  |bits:%02d|vbits:%02d|channel:%02d|rate:%06d|%s|") \r
+              % sample_bits[bits].bits_per_sample \r
+              % sample_bits[bits].valid_bits_per_sample \r
+              % channel % sample_rates[rate] \r
+              % (hr == S_OK?L"OK":L"NG") << endl;\r
+#endif            }\r
+\r
+            // make_wave_format(f,sample_rates[rate],channel,sample_bits[bits],WAVE_FORMAT_EXTENSIBLE);\r
+            // 共有モード\r
+            hr = c->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,reinterpret_cast<WAVEFORMATEX*>(&f),reinterpret_cast<WAVEFORMATEX**>(&a1));\r
+            if(hr == S_OK){\r
+              input_device_infos_[d].\r
+                support_formats\r
+                [AUDCLNT_SHAREMODE_SHARED]\r
+                [sample_bits[bits].bits_per_sample ]\r
+                [sample_bits[bits].valid_bits_per_sample]\r
+                [channel]\r
+                [sample_rates[rate]] = 0;\r
+#ifdef _DEBUG\r
+              wdout << wformat(L"|share|bits:%02d|vbits:%02d|channel:%02d|rate:%06d|%s|") \r
+                % sample_bits[bits].bits_per_sample \r
+                % sample_bits[bits].valid_bits_per_sample \r
+                % channel \r
+                % sample_rates[rate] \r
+                % (hr == S_OK?L"OK":L"NG") << endl;\r
+\r
+#endif\r
+            }\r
+          }\r
+        }\r
+      }\r
+#ifdef _DEBUG\r
+    wdout << "-------------------------------" << std::endl;\r
+#endif\r
+    }\r
+    safe_release(c);\r
+  }\r
+}//\r
+\r
+  int wasapi_device_manager::get_device_infos(EDataFlow data_flow, std::vector<device_info>& infos,const std::wstring& idd)\r
+  {\r
+    // コレクションを取得\r
+    IMMDeviceCollectionPtr collection;\r
+    device_enumerator_->EnumAudioEndpoints(data_flow,DEVICE_STATE_ACTIVE ,&collection);\r
+    uint32_t count;\r
+    wstring idd_w(idd);\r
+    // デフォルトデバイスの情報\r
+    IMMDevicePtr default_device;\r
+    int default_index = 0;\r
+    device_enumerator_->GetDefaultAudioEndpoint(data_flow,eMultimedia,&default_device);\r
+    co_task_memory<WCHAR> iddw;\r
+    default_device->GetId(&iddw);\r
+    wstring id_default(iddw.get());\r
+\r
+    if(idd_w.empty() || id_default.size() != idd_w.size())\r
+    {\r
+      idd_w.assign(iddw.get());\r
+    }\r
+\r
+    // 各デバイスの情報を収集する\r
+    collection->GetCount(&count);\r
+    bool found = false;\r
+    for(int i = 0;i < count ;++i)\r
+    {\r
+      IMMDevicePtr d;\r
+      IPropertyStorePtr p;\r
+      co_task_memory<WCHAR> id;\r
+      collection->Item(i,&d);\r
+      d->GetId(&id);\r
+      d->OpenPropertyStore(STGM_READ,&p);\r
+      prop_variant difn,ddd,dfn;\r
+      THROW_IF_ERR(p->GetValue(PKEY_DeviceInterface_FriendlyName, &difn));\r
+      THROW_IF_ERR(p->GetValue(PKEY_Device_DeviceDesc, &ddd));\r
+      THROW_IF_ERR(p->GetValue(PKEY_Device_FriendlyName, &difn));\r
+      infos.push_back(device_info(std::wstring(id.get()),std::wstring(difn.get()->pwszVal),std::wstring(ddd.get()->pwszVal),std::wstring(difn.get()->pwszVal),d));\r
+\r
+      if(infos[i].id == idd_w)\r
+      {\r
+        default_index = i;\r
+        infos[i].is_selected = true;\r
+        found = true;\r
+      }\r
+\r
+#ifdef _DEBUG\r
+      wdout << L"--------------------------------------------" << std::endl;\r
+      wdout << infos[i].device_description << std::endl;\r
+      wdout << infos[i].device_friendly_name << std::endl;\r
+      wdout << infos[i].device_interface_friendly_name << std::endl;\r
+      wdout << infos[i].is_selected << std::endl;\r
+      wdout << infos[i].id << std::endl;\r
+#endif\r
+      safe_release(p);\r
+      safe_release(d);\r
+    }\r
+\r
+    if(!found)\r
+    {\r
+      for(int i = 0;i < infos.size();++i)\r
+      {\r
+        if(infos[i].id == id_default)\r
+        {\r
+          default_index = i;\r
+          infos[i].is_selected = true;\r
+        }\r
+\r
+\r
+      }\r
+    }\r
+    return default_index;\r
+  }\r
+\r
+  wasapi_device_manager::~wasapi_device_manager()\r
+  {\r
+    //for(int i = 0; i < \r
+    //safe_release(device_collection_);\r
+    //safe_release(device_collection_);\r
+    safe_release(device_enumerator_);\r
+\r
+    // 設定の保存\r
+    try{\r
+      wstring p = application::instance()->base_directory() + L"\\wasapi_device_manager.config.xml";\r
+      filesystem::wpath config_path(p);\r
+      filesystem::wofstream f(config_path,std::ios_base::out | std::ios_base::trunc);\r
+      archive::xml_woarchive ar(f);\r
+      ar & boost::serialization::make_nvp("output_device_id",current_output_device().id);\r
+      ar & boost::serialization::make_nvp("input_device_id" ,current_input_device().id);\r
+    }catch(...) {\r
+\r
+    }\r
+  }\r
+\r
+  wasapi_device_manager::device_info::device_info(std::wstring& i,std::wstring& difn,std::wstring& dd,std::wstring& dfn,IMMDevicePtr p)\r
+    : id(i),device_interface_friendly_name(difn),device_description(dd),device_friendly_name(dfn),is_selected(false)\r
+  {\r
+    device_ptr = p;\r
+    filesystem::wpath config_path(application::instance()->base_directory() + L"\\" + id + L".xml");\r
+    if(filesystem::exists(config_path))\r
+    {\r
+      try{\r
+        filesystem::wifstream ifile(config_path);\r
+        boost::archive::xml_wiarchive ar(ifile);\r
+        ar >> BOOST_SERIALIZATION_NVP(params);\r
+      } catch (...) \r
+      {\r
+        // ファイル読み込みに問題がある場合はファイルを消す。\r
+        filesystem::remove(config_path);\r
+      }\r
+    }\r
+#ifdef _DEBUG\r
+    wdout << L"================================================" << std::endl;\r
+    wdout << id << L"\n" << device_interface_friendly_name << std::endl;\r
+    wdout << params.latency << std::endl;\r
+    wdout << L"================================================" << std::endl;\r
+#endif\r
+\r
+  }\r
+\r
+  wasapi_device_manager::device_info::~device_info()\r
+  {\r
+    try {\r
+      filesystem::wpath config_path(application::instance()->base_directory() + L"\\"+  id + L".xml");\r
+      filesystem::wofstream ofile(config_path,std::ios_base::out | ios_base::trunc);\r
+      archive::xml_woarchive ar(ofile);\r
+      ar << BOOST_SERIALIZATION_NVP(params);\r
+    } catch(...)\r
+    {\r
+\r
+    }\r
+  }\r
+\r
+\r
+}
\ No newline at end of file
diff --git a/wasapi2/wavefile.cpp b/wasapi2/wavefile.cpp
new file mode 100644 (file)
index 0000000..517fe88
--- /dev/null
@@ -0,0 +1,349 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the async\r
+   Copyright 2005-11 by Satoshi Fujiwara.\r
+\r
+   async can be redistributed and/or modified under the terms of the\r
+   GNU General Public License, as published by the Free Software Foundation;\r
+   either version 2 of the License, or (at your option) any later version.\r
+\r
+   async is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with async; if not, visit www.gnu.org/licenses or write to the\r
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+   Boston, MA 02111-1307 USA\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+// SDKのサンプルを改造した作ったもの。内容はほぼそのまま。\r
+\r
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF\r
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A\r
+// PARTICULAR PURPOSE.\r
+//\r
+// Copyright (c) Microsoft Corporation. All rights reserved.\r
+\r
+//-----------------------------------------------------------\r
+//\r
+// wavefile.cpp\r
+//\r
+//   Wave file reader.\r
+//\r
+//-----------------------------------------------------------\r
+\r
+#include "stdafx.h"\r
+#include <stdio.h>\r
+#include <assert.h>\r
+#include <wtypes.h>\r
+#include <mmreg.h>\r
+#include <ks.h>\r
+#include <ksmedia.h>\r
+#include "wavefile.h"\r
+\r
+namespace sf {\r
+  // To parse a wave file, it is helpful to have two user-defined types.\r
+  // The first will receive all the information in the file header and\r
+  // in the header of the format chunk. The second will receive the\r
+  // information in the headers for the data chunks, and, if the file\r
+  // contains additional chunks, the headers for those chunks as well.\r
+\r
+  typedef struct\r
+  {\r
+    ULONG Riff4CC;      // "RIFF" 4-character code\r
+    ULONG FileSize;     // total file size in bytes\r
+    ULONG Wave4CC;      // "WAVE" 4-character code\r
+    ULONG Fmt4CC;       // "fmt " 4-character code\r
+    ULONG FormatSize;   // wave format size in bytes\r
+  } FileHeader;\r
+\r
+  typedef struct\r
+  {\r
+    ULONG ChunkType;\r
+    ULONG ChunkSize;\r
+  } ChunkHeader;\r
+\r
+  // Any file smaller than this cannot possibly contain wave data.\r
+#define MIN_WAVE_FILE_SIZE (sizeof(FileHeader)+sizeof(PCMWAVEFORMAT)+sizeof(ChunkHeader)+1)\r
+\r
+  // Macro to build FOURCC from first four characters in ASCII string\r
+#define FOURCC(s)  ((ULONG)(s[0] | (s[1]<<8) | (s[2]<<16) | (s[3]<<24)))\r
+\r
+  //\r
+  // Constructor -- Open wave file and parse file header.\r
+  //\r
+  wave_file_reader::wave_file_reader(const std::wstring file_name, bool repeat_mode)\r
+  {\r
+    file_ = NULL;\r
+    stream_status_ = S_OK;\r
+    data_chunk_position = 0;\r
+    total_data_bytes_ = 0;\r
+    data_bytes_remaining_ = 0;\r
+    reader_repeat_mode_ = repeat_mode;\r
+    ZeroMemory(&wfx_, sizeof(wfx_));\r
+    try{\r
+      // Try to open the wave file.\r
+      if (_wfopen_s(&file_, file_name.c_str(), L"rb") != 0)\r
+      {\r
+        throw exception(std::wstring(L"ファイルをオープンできません。"));\r
+      }\r
+\r
+      // Copy header from wave file.\r
+      FileHeader fileHdr;\r
+\r
+      if (fread(&fileHdr, sizeof(fileHdr), 1, file_) != 1)\r
+      {\r
+        throw exception(std::wstring(L"ファイルを読み込むことができません。"));\r
+      }\r
+\r
+      // Verify that wave file header is valid.\r
+      if (fileHdr.Riff4CC != FOURCC("RIFF") ||\r
+        fileHdr.FileSize < MIN_WAVE_FILE_SIZE ||\r
+        fileHdr.Wave4CC != FOURCC("WAVE") ||\r
+        fileHdr.Fmt4CC != FOURCC("fmt ") ||\r
+        fileHdr.FormatSize < sizeof(PCMWAVEFORMAT))\r
+      {\r
+        throw exception(std::wstring(L"サポートしていない.WAVファイルです。"));\r
+      }\r
+\r
+      // Copy wave format descriptor from file.\r
+      if (fread(&wfx_, min(fileHdr.FormatSize,sizeof(wfx_)), 1, file_) != 1)\r
+      {\r
+        throw exception(std::wstring(L"サポートしていない.WAVファイルです。"));\r
+      }\r
+\r
+      // Skip over any padding at the end of the format in the format chunk.\r
+      if (fileHdr.FormatSize > sizeof(wfx_))\r
+      {\r
+        if (fseek(file_, fileHdr.FormatSize-sizeof(wfx_), SEEK_CUR) != 0)\r
+        {\r
+          throw exception(std::wstring(L"ヘッダファイルのサイズが不正です。"));\r
+        }\r
+      }\r
+\r
+      // If format type is PCMWAVEFORMAT, convert to valid WAVEFORMATEX structure.\r
+      if (wfx_.Format.wFormatTag == WAVE_FORMAT_PCM)\r
+      {\r
+        wfx_.Format.cbSize = 0;\r
+      }\r
+\r
+      // If format type is WAVEFORMATEX, convert to WAVEFORMATEXTENSIBLE.\r
+      if (wfx_.Format.wFormatTag == WAVE_FORMAT_PCM ||\r
+        wfx_.Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)\r
+      {\r
+        if (wfx_.Format.wFormatTag == WAVE_FORMAT_PCM)\r
+        {\r
+          wfx_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;\r
+        }\r
+        else\r
+        {\r
+          wfx_.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;\r
+        }\r
+        wfx_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;\r
+\r
+        // Note that the WAVEFORMATEX structure is valid for\r
+        // representing wave formats with only 1 or 2 channels.\r
+        if (wfx_.Format.nChannels == 1)\r
+        {\r
+          wfx_.dwChannelMask = SPEAKER_FRONT_CENTER;\r
+        }\r
+        else if (wfx_.Format.nChannels == 2)\r
+        {\r
+          wfx_.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;\r
+        }\r
+        else\r
+        {\r
+          throw exception(std::wstring(L"サポートしていない.WAVファイルです。"));\r
+        }\r
+        wfx_.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);\r
+        wfx_.Samples.wValidBitsPerSample = wfx_.Format.wBitsPerSample;\r
+      }\r
+\r
+      // This wave file reader understands only PCM and IEEE float formats.\r
+      if (wfx_.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE ||\r
+        wfx_.SubFormat != KSDATAFORMAT_SUBTYPE_PCM &&\r
+        wfx_.SubFormat != KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)\r
+      {\r
+        throw exception(std::wstring(L"サポートしていない.WAVファイルです。"));\r
+      }\r
+\r
+      // Find chunk header for wave data. Skip past any other kinds of chunks.\r
+      ChunkHeader chunkHdr;   // buffer for chunk header\r
+      for (;;)\r
+      {\r
+        // Remember the file position of the data chunk (which this might be\r
+        // -- we don't know yet). That way, if we need to reader_read_file the file more\r
+        // than once, we won't have to parse the header again each time.\r
+        if (fgetpos(file_, &data_chunk_position) != 0)\r
+        {\r
+          throw exception(std::wstring(L"サポートしていない.WAVファイルです。"));\r
+        }\r
+\r
+        // Read header at start of next chunk of file.\r
+        if (fread(&chunkHdr, sizeof(ChunkHeader), 1, file_) != 1)\r
+        {\r
+          throw exception(std::wstring(L"サポートしていない.WAVファイルです。"));\r
+        }\r
+        if (chunkHdr.ChunkType == FOURCC("data"))\r
+        {\r
+          break;  // found start of data chunk\r
+        }\r
+        // This is *not* a data chunk. Skip this chunk and go to the next chunk.\r
+        if (fseek(file_, chunkHdr.ChunkSize, SEEK_CUR) != 0)\r
+        {\r
+          throw exception(std::wstring(L"サポートしていない.WAVファイルです。"));\r
+        }\r
+      }\r
+\r
+      // We've found the start of the data chunk. We're reader_ready to start\r
+      // playing wave data...\r
+      total_data_bytes_ = chunkHdr.ChunkSize;\r
+      data_bytes_remaining_ = total_data_bytes_;\r
+      if (total_data_bytes_ == 0)\r
+      {\r
+        throw exception(std::wstring(L"ファイルサイズが不正です。"));\r
+      }\r
+      stream_status_ = true;\r
+    } catch (exception& e) {\r
+      stream_status_ = false;\r
+      throw;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Destructor\r
+  //\r
+  wave_file_reader::~wave_file_reader()\r
+  {\r
+    if (file_)\r
+    {\r
+      fclose(file_);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Reset the file pointer to the start of the wave data.\r
+  //\r
+  void wave_file_reader::reset_data_position()\r
+  {\r
+    if (!stream_status_ )\r
+    {\r
+      throw wave_file_reader::exception(std::wstring(L"ファイルがオープンされていません。"));\r
+    }\r
+\r
+    // Move to the header info at the start of the data chunk.\r
+    if (fsetpos(file_, &data_chunk_position) != 0)\r
+    {\r
+      throw exception(std::wstring(L"不正なWAVファイルです。"));\r
+    }\r
+\r
+    // Read the header for the data chunk.\r
+    ChunkHeader chunkHdr;\r
+    if (fread(&chunkHdr, sizeof(chunkHdr), 1, file_) != 1)\r
+    {\r
+      throw exception(std::wstring(L"不正なWAVファイルです。"));\r
+    }\r
+\r
+    // Sanity check: The chunk header shouldn't have changed.\r
+    if (chunkHdr.ChunkType != FOURCC("data") ||\r
+      chunkHdr.ChunkSize != total_data_bytes_)\r
+    {\r
+      throw exception(std::wstring(L"不正なWAVファイルです。"));\r
+    }\r
+    data_bytes_remaining_ = total_data_bytes_;\r
+\r
+    // At this point, the file pointer is positioned at\r
+    // the beginning of the wave data.\r
+  }\r
+\r
+  void wave_file_reader::seek(uint64_t pos)\r
+  {\r
+    if (!stream_status_ )\r
+    {\r
+      throw wave_file_reader::exception(std::wstring(L"ファイルがオープンされていません。"));\r
+    }\r
+    fpos_t current;\r
+    fgetpos(file_,&current);\r
+    pos = (pos / get_wave_format().Format.nBlockAlign) * get_wave_format().Format.nBlockAlign;\r
+    data_bytes_remaining_ = total_data_bytes_ - pos;\r
+    pos = pos + data_chunk_position + sizeof(ChunkHeader);\r
+    fsetpos(file_,reinterpret_cast<fpos_t*>(&pos));\r
+  }\r
+\r
+\r
+  //\r
+  // Load next block of wave data from file into playback buffer.\r
+  // In repeat mode, when we reach the end of the wave data in the\r
+  // file, we just reset the file pointer back to the start of the\r
+  // data and continue filling the caller's buffer until it is full.\r
+  // In single-reader_read_file mode, once we reach the end of the wave data in\r
+  // the file, we just fill the buffer with silence instead of with\r
+  // real data.\r
+  //\r
+  void wave_file_reader::read_data(BYTE *buffer, uint64_t numbytes)\r
+  {\r
+\r
+    if (!stream_status_ )\r
+    {\r
+      throw wave_file_reader::exception(std::wstring(L"ファイルがオープンされていません。"));\r
+    }\r
+\r
+    if (buffer == NULL)\r
+    {\r
+      throw exception(L"バッファアドレスが無効です。");\r
+    }\r
+\r
+    if (numbytes == 0)\r
+    {\r
+      throw exception(L"読み込みバイト数の指定が0です。");\r
+    }\r
+\r
+    BYTE *current = (BYTE*)buffer;\r
+    ULONG numbytes_to_copy = numbytes;\r
+\r
+    while (numbytes_to_copy > data_bytes_remaining_)\r
+    {\r
+      if (fread(current, 1, data_bytes_remaining_, file_) != data_bytes_remaining_)\r
+      {\r
+        throw exception(L"不正なWAVファイルです。");\r
+      }\r
+      current += data_bytes_remaining_;\r
+      numbytes_to_copy -= data_bytes_remaining_;\r
+      data_bytes_remaining_ = 0;\r
+\r
+      // The file pointer now sits at the end of the data chunk.\r
+      // Are we operating in repeat mode?\r
+      if (!reader_repeat_mode_)\r
+      {\r
+        // Nope, we're operating in single-reader_read_file mode. Fill\r
+        // the rest of the buffer with silence and return.\r
+        BYTE silence = (wfx_.Format.wBitsPerSample==8) ? 0x80 : 0;\r
+        memset(current, silence, numbytes_to_copy);\r
+        return;  // yup, we're done\r
+      }\r
+      // Yes, we're operating in repeat mode, so loop back to\r
+      // the start of the wave data in the file's data chunk\r
+      // and continue loading data into the caller's buffer.\r
+      reset_data_position();\r
+\r
+    }\r
+\r
+    assert(numbytes_to_copy > 0);\r
+    assert(numbytes_to_copy <= data_bytes_remaining_);\r
+\r
+    // The remainder of the data chunk is big enough to\r
+    // completely fill the remainder of the caller's buffer.\r
+    if (fread(buffer, 1, numbytes_to_copy, file_) != numbytes_to_copy)\r
+    {\r
+      throw exception(L"不正なWAVファイルです。");\r
+    }\r
+    data_bytes_remaining_ -= numbytes_to_copy;\r
+    current += numbytes_to_copy;\r
+  }\r
+}\r
diff --git a/wasapi2/wavefile.h b/wasapi2/wavefile.h
new file mode 100644 (file)
index 0000000..0c51be0
--- /dev/null
@@ -0,0 +1,74 @@
+#pragma once
+/*
+  ==============================================================================
+
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#include <audioclient.h>
+#include "exception.h"
+#include "audio_source.h"
+
+namespace sf{
+
+class wave_file_reader : public audio_source
+{
+    struct exception : public sf::exception
+    {
+      exception(const std::wstring& reason) : sf::exception(reason) {};
+      exception(const wchar_t* reason) : sf::exception(std::wstring(reason)) {};
+    };
+
+    FILE *file_;
+    
+    bool stream_status_;
+    fpos_t data_chunk_position;
+    uint64_t total_data_bytes_;
+    uint64_t data_bytes_remaining_;
+    WAVEFORMATEXTENSIBLE wfx_;
+    bool reader_repeat_mode_;
+
+public:
+    wave_file_reader(const std::wstring file_name, bool repeat_mode);
+    ~wave_file_reader();
+    bool seekable() {return true;}
+    bool stream_status() { return stream_status_; };
+    WAVEFORMATEXTENSIBLE &get_wave_format()
+    {
+        return  wfx_ ;
+    };
+
+    bool more_data_available()
+    {
+        return (stream_status_  &&
+                (reader_repeat_mode_  || data_bytes_remaining_ > 0));
+    };
+
+    uint64_t total_data_bytes() { return total_data_bytes_; }
+    uint64_t data_bytes_remaining() { return data_bytes_remaining_; }
+    void seek(uint64_t pos);
+    void read_data(BYTE *buffer, uint64_t numbytes);
+    void reset_data_position();
+    HANDLE raw_handle() { return reinterpret_cast<HANDLE>(file_);};
+    void wait(int timer = -1) {return;};
+
+};
+
+
+}
+
diff --git a/wasapi2/winmain.cpp b/wasapi2/winmain.cpp
new file mode 100644 (file)
index 0000000..3aede80
--- /dev/null
@@ -0,0 +1,15 @@
+#include "stdafx.h"
+#include "application.h"
+
+
+//#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+/** WinMain */
+int APIENTRY _tWinMain(HINSTANCE hInstance,
+                     HINSTANCE hPrevInstance,
+                     LPTSTR    lpCmdLine,
+                     int       nCmdShow)
+{
+       
+  return sf::application::instance()
+    ->execute( hInstance,hPrevInstance,lpCmdLine,nCmdShow);
+}
diff --git a/wasapi2/writer_thread.cpp b/wasapi2/writer_thread.cpp
new file mode 100644 (file)
index 0000000..bd0d817
--- /dev/null
@@ -0,0 +1,63 @@
+/*\r
+==============================================================================\r
+\r
+This file is part of the async\r
+Copyright 2005-10 by Satoshi Fujiwara.\r
+\r
+async can be redistributed and/or modified under the terms of the\r
+GNU General Public License, as published by the Free Software Foundation;\r
+either version 2 of the License, or (at your option) any later version.\r
+\r
+async is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with async; if not, visit www.gnu.org/licenses or write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
+Boston, MA 02111-1307 USA\r
+\r
+==============================================================================\r
+*/\r
+#include "StdAfx.h"\r
+#include <commctrl.h>\r
+\r
+#if _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#include <crtdbg.h>\r
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
+#endif\r
+\r
+#include "message_loop.h"\r
+#include "sf_com.h"\r
+#include "application.h"\r
+#include "writer_thread.h"\r
+#include "dout.h"\r
+#include "async_reader.h"\r
+\r
+using namespace std;\r
+\r
+namespace sf {\r
+\r
+\r
+void writer_thread_t::thread_main()\r
+{\r
+  // TODO:ミキサーの実装\r
+  // COMの初期化\r
+  sf::com_initialize init(0,multi_threaded);\r
+  init_buffer();\r
+  int status;\r
+  switch(status = status_.load(),status !=status_exit)\r
+  {\r
+  case status_processing:\r
+    break;\r
+  case status_pause:\r
+    break;\r
+  default:\r
+    WaitForSingleObject(event_.get(),WAIT_TIMEOUT);\r
+  }\r
+}\r
+\r
+}\r
+\r
diff --git a/wasapi2/writer_thread.h b/wasapi2/writer_thread.h
new file mode 100644 (file)
index 0000000..85ba287
--- /dev/null
@@ -0,0 +1,43 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-10 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+#include "thread_base.h"
+
+namespace sf {
+struct writer_thread_t : public thread_base
+{
+  writer_thread_t(){};
+  ~writer_thread_t(){};
+  void thread_main();
+  enum wtiter_status
+  {
+    status_processing,
+    status_pause,
+    status_pause_ok,
+    status_exit,
+    status_error = STATUS_ERROR
+  };
+private:
+};
+}
+