OSDN Git Service

キャプチャ部分のバグ修正。
[winaudioj/wasapi2.git] / wasapi2 / wasapi_manager.cpp
1 /*\r
2 ==============================================================================\r
3 \r
4 Copyright 2005-11 by Satoshi Fujiwara.\r
5 \r
6 async can be redistributed and/or modified under the terms of the\r
7 GNU General Public License, as published by the Free Software Foundation;\r
8 either version 2 of the License, or (at your option) any later version.\r
9 \r
10 async is distributed in the hope that it will be useful,\r
11 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 GNU General Public License for more details.\r
14 \r
15 You should have received a copy of the GNU General Public License\r
16 along with async; if not, visit www.gnu.org/licenses or write to the\r
17 Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
18 Boston, MA 02111-1307 USA\r
19 \r
20 ==============================================================================\r
21 */\r
22 \r
23 #include "stdafx.h"\r
24 #if _DEBUG\r
25 #define _CRTDBG_MAP_ALLOC\r
26 #include <crtdbg.h>\r
27 #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
28 #endif\r
29 #include "sf_memory.h"\r
30 #include "audio_base.h"\r
31 #include "wasapi.h"\r
32 //#include "application.h"\r
33 //using namespace boost;\r
34 using namespace std;\r
35 using namespace Windows::Foundation;\r
36 using namespace Windows::Foundation::Collections;\r
37 using namespace Windows::Devices::Enumeration;\r
38 using namespace Windows::Media::Devices;\r
39 using namespace Concurrency;\r
40 using namespace Platform;\r
41 using namespace Microsoft::WRL;\r
42 \r
43 namespace sf {\r
44   const wstring wasapi_device_manager::base_directory_(L"."/* Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data() */);\r
45   const int wasapi_device_manager::sample_rates[NUM_SAMPLE_RATE] = {8000,11025,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000};\r
46   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
47 \r
48   void make_wave_format(WAVEFORMATEXTENSIBLE& format,int sample_rate,int channels,bits_pair b,uint32_t type,const GUID&  sub_type)\r
49   {\r
50     ZeroMemory(&format,sizeof(WAVEFORMATEXTENSIBLE));\r
51     format.Format.wFormatTag = type;\r
52     format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);\r
53     format.SubFormat = sub_type;\r
54     format.Format.nSamplesPerSec = sample_rate;\r
55     format.Format.nChannels = channels;\r
56     format.Format.wBitsPerSample = b.bits_per_sample;\r
57     format.Format.nBlockAlign = (format.Format.wBitsPerSample / 8) * format.Format.nChannels;\r
58     format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec  * format.Format.nBlockAlign;\r
59     format.Samples.wValidBitsPerSample = b.valid_bits_per_sample;\r
60 \r
61     format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;\r
62   };\r
63 \r
64   void make_wave_format(WAVEFORMATEX& format,int sample_rate,int channels,int bits,uint32_t type)\r
65   {\r
66     ZeroMemory(&format,sizeof(WAVEFORMATEX));\r
67     format.wFormatTag = type;\r
68     format.nSamplesPerSec = sample_rate;\r
69     format.nChannels = channels;\r
70     format.wBitsPerSample = bits;\r
71     format.nBlockAlign = (format.wBitsPerSample / 8) * format.nChannels;\r
72     format.nAvgBytesPerSec = format.nSamplesPerSec  * format.nBlockAlign;\r
73   };\r
74 \r
75   struct prop_variant \r
76   {\r
77     prop_variant()\r
78     {\r
79       PropVariantInit(&value_);\r
80     }\r
81 \r
82     ~prop_variant()\r
83     {\r
84       PropVariantClear(&value_);\r
85     }\r
86 \r
87     PROPVARIANT* get(){ return &value_;};\r
88 \r
89     PROPVARIANT* operator &(){return get();}\r
90 \r
91     operator PROPVARIANT*() {return get();}\r
92 \r
93   private:\r
94     PROPVARIANT value_;\r
95   };\r
96 \r
97 \r
98   wasapi_device_manager::wasapi_device_manager() \r
99     : output_device_index_(-1),input_device_index_(-1),output_enum_completed_(false),input_enum_completed_(false)\r
100   {\r
101 \r
102     config_path_.append(base_directory_).append(L"\\wasapi_device_manager.config.xml");\r
103     boost::filesystem::wpath config_path(config_path_);\r
104 \r
105 \r
106     if(boost::filesystem::exists(config_path))\r
107     {\r
108       try {\r
109         boost::filesystem::wifstream f(config_path);\r
110         boost::archive::xml_wiarchive ar(f);\r
111         ar & boost::serialization::make_nvp("output_device_id",output_id_);\r
112         ar & boost::serialization::make_nvp("input_device_id" ,input_id_);\r
113       } catch(...)\r
114       {\r
115         output_id_ = input_id_ = L"";\r
116         boost::filesystem::remove(config_path);\r
117       }\r
118     }\r
119 \r
120     default_output_id_ = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default)->Data();\r
121     default_input_id_ = MediaDevice::GetDefaultAudioCaptureId(AudioDeviceRole::Default)->Data();\r
122 \r
123     //watcher_ = DeviceInformation::CreateWatcher();\r
124     //adapter_ = ref new typed_event_handler_adapter<DeviceWatcher^,DeviceInformation^>(boost::bind(&wasapi_device_manager::added,this,_1,_2));\r
125     //  watcher_->Added += adapter_->get();\r
126     //watcher_->Added += (ref new typed_event_handler_adapter<DeviceWatcher^,DeviceInformation^>(boost::bind(&wasapi_device_manager::added,this,_1,_2)))->get();\r
127     //watcher_->Start();\r
128 \r
129     output_watcher_adapter_ = ref new DeviceWatcherAdapter(en::DeviceClass::AudioRender);\r
130     output_watcher_adapter_->added().connect(boost::bind(&wasapi_device_manager::output_added,this,_1,_2));\r
131     output_watcher_adapter_->enumration_completed().connect(boost::bind(&wasapi_device_manager::output_enumeration_completed,this,_1,_2));\r
132     output_watcher_adapter_->removed().connect(boost::bind(&wasapi_device_manager::output_removed,this,_1,_2));\r
133     output_watcher_adapter_->updated().connect(boost::bind(&wasapi_device_manager::output_updated,this,_1,_2));\r
134     output_watcher_adapter_->stopped().connect(boost::bind(&wasapi_device_manager::output_stopped,this,_1,_2));\r
135     output_watcher_adapter_->start();\r
136 \r
137     input_watcher_adapter_ = ref new DeviceWatcherAdapter(en::DeviceClass::AudioCapture);\r
138     input_watcher_adapter_->added().connect(boost::bind(&wasapi_device_manager::input_added,this,_1,_2));\r
139     input_watcher_adapter_->enumration_completed().connect(boost::bind(&wasapi_device_manager::input_enumeration_completed,this,_1,_2));\r
140     input_watcher_adapter_->removed().connect(boost::bind(&wasapi_device_manager::input_removed,this,_1,_2));\r
141     input_watcher_adapter_->updated().connect(boost::bind(&wasapi_device_manager::input_updated,this,_1,_2));\r
142     input_watcher_adapter_->stopped().connect(boost::bind(&wasapi_device_manager::input_stopped,this,_1,_2));\r
143     input_watcher_adapter_->start();\r
144 \r
145   }//\r
146 \r
147   int wasapi_device_manager::get_device_infos(DeviceClass data_flow, std::vector<device_info>& infos,const std::wstring& idd)\r
148   {\r
149 \r
150     // 対象デバイスを列挙する\r
151     task<DeviceInformationCollection^> t((DeviceInformation::FindAllAsync(data_flow)));\r
152     t.wait();\r
153     DeviceInformationCollection^ collection = t.get();\r
154     int current_index = 0;\r
155     bool found = false;\r
156     Platform::String^  default_id = ref new Platform::String();\r
157     switch(data_flow)\r
158     {\r
159     case Windows::Devices::Enumeration::DeviceClass::AudioRender:\r
160       default_id = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);\r
161       break;\r
162     case Windows::Devices::Enumeration::DeviceClass::AudioCapture:\r
163       default_id = MediaDevice::GetDefaultAudioCaptureId(AudioDeviceRole::Default);\r
164       break;\r
165     }\r
166 \r
167 \r
168     for(int i = 0 ,end = collection->Size;i < end;++i)\r
169     {\r
170       DeviceInformation^ info = collection->GetAt(i);\r
171       infos.push_back(device_info(info));\r
172       if(info->Id == default_id)\r
173       {\r
174         infos[i].is_default_ = true;\r
175       }\r
176 \r
177       if(idd == wstring(info->Id->Data()) )\r
178       {\r
179         infos[i].is_selected_ = true;\r
180         current_index = i;\r
181         found = true;\r
182       }\r
183     }\r
184 \r
185     if(!found)\r
186     {\r
187       for(int i = 0,end = infos.size();i < end;++i)\r
188       {\r
189         if(infos[i].is_default_)\r
190         {\r
191           current_index = i;\r
192           infos[i].is_selected_ = true;\r
193         }\r
194       }\r
195 \r
196     }\r
197     return current_index;\r
198   }\r
199 \r
200   wasapi_device_manager::~wasapi_device_manager()\r
201   {\r
202     //    stop_watching();\r
203   }\r
204 \r
205   wasapi_device_manager::device_info::device_info\r
206     (DeviceInformation^ info)\r
207     :   id_(info->Id->Data()),\r
208     name_(info->Name->Data()),  \r
209     display_name_(dynamic_cast<String^>(info->Properties->Lookup(L"System.ItemNameDisplay"))->Data()),\r
210     is_enabled_(info->IsEnabled),is_selected_(false),is_default_(info->IsDefault)\r
211   {\r
212     boost::filesystem::wpath \r
213       config_path(wasapi_device_manager::base_directory() + L"\\" + Windows::Foundation::Uri::EscapeComponent(info->Id)->Data() + L".xml");\r
214     if(boost::filesystem::exists(config_path))\r
215     {\r
216       try{\r
217         boost::filesystem::wifstream ifile(config_path);\r
218         boost::archive::xml_wiarchive ar(ifile);\r
219         ar >> BOOST_SERIALIZATION_NVP(params);\r
220       } catch (...) \r
221       {\r
222         // ファイル読み込みに問題がある場合はファイルを消す。\r
223         boost::filesystem::remove(config_path);\r
224       }\r
225     }\r
226 #ifdef _DEBUG\r
227     wdout << L"================================================" << std::endl;\r
228     wdout << id_ << L"\n" << display_name_ << std::endl;\r
229     wdout << params.latency << std::endl;\r
230     wdout << L"================================================" << std::endl;\r
231 #endif\r
232 \r
233   }\r
234 \r
235   void wasapi_device_manager::stop_watching()\r
236   {\r
237     input_watcher_adapter_->stop();\r
238     output_watcher_adapter_->stop();\r
239   }\r
240 \r
241   void wasapi_device_manager::save_params()\r
242   {\r
243     // watcherの停止\r
244     // stop_watching();\r
245 \r
246     // 設定の保存\r
247     try{\r
248       boost::filesystem::wpath config_path(config_path_);\r
249       boost::filesystem::wofstream f(config_path,std::ios_base::out | std::ios_base::trunc);\r
250       boost::archive::xml_woarchive ar(f);\r
251       ar & boost::serialization::make_nvp("output_device_id",current_output_device().id_);\r
252       ar & boost::serialization::make_nvp("input_device_id" ,current_input_device().id_);\r
253     }catch(...) {\r
254 \r
255     }\r
256 \r
257     // 出力デバイスパラメータの保存\r
258     for(device_info& inf : output_device_infos_)\r
259     {\r
260 \r
261       try {\r
262         boost::filesystem::wpath \r
263           config_path(wasapi_device_manager::base_directory() + L"\\" +  Windows::Foundation::Uri::EscapeComponent(ref new Platform::String(inf.id_.c_str()))->Data() + L".xml");\r
264         boost::filesystem::wofstream ofile(config_path,std::ios_base::out | ios_base::trunc);\r
265         boost::archive::xml_woarchive ar(ofile);\r
266         ar << BOOST_SERIALIZATION_NVP(inf.params);\r
267       } catch(...)\r
268       {\r
269 \r
270       }\r
271     }\r
272 \r
273     // 入力デバイスパラメータの保存\r
274     for(device_info& inf : input_device_infos_)\r
275     {\r
276 \r
277       try {\r
278         boost::filesystem::wpath \r
279           config_path(wasapi_device_manager::base_directory() + L"\\" + Windows::Foundation::Uri::EscapeComponent(ref new Platform::String(inf.id_.c_str()))->Data() + L".xml");\r
280         boost::filesystem::wofstream ofile(config_path,std::ios_base::out | ios_base::trunc);\r
281         boost::archive::xml_woarchive ar(ofile);\r
282         ar << BOOST_SERIALIZATION_NVP(inf.params);\r
283       } catch(...)\r
284       {\r
285 \r
286       }\r
287     }\r
288 \r
289   }\r
290 \r
291   wasapi_device_manager::device_info::~device_info()\r
292   {\r
293   }\r
294 \r
295   void wasapi_device_manager::output_added(Windows::Devices::Enumeration::DeviceWatcher^ sender, Windows::Devices::Enumeration::DeviceInformation^ deviceInfo)\r
296   {\r
297     device_info info(deviceInfo);\r
298 \r
299     IAudioClient2Ptr c;\r
300     // オーディオクライアントを取得\r
301     {\r
302       ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOpPtr;\r
303       ComPtr<ActivateAudioInterfaceCompletionHandler> handler(Make<ActivateAudioInterfaceCompletionHandler>());\r
304       HRESULT hr = ActivateAudioInterfaceAsync(info.id_.c_str(),__uuidof(IAudioClient2),nullptr,handler.Get(),asyncOpPtr.GetAddressOf());\r
305       if(SUCCEEDED(hr)){\r
306         handler->wait();\r
307         if(handler->ResultCode() == S_OK)\r
308         {\r
309           c = handler->AudioClient();\r
310         } else {\r
311           throw win32_error_exception(handler->ResultCode());\r
312         }\r
313       } else {\r
314         throw win32_error_exception(handler->ResultCode());\r
315       }\r
316     }\r
317     c->GetDevicePeriod(&(info.latency_default_),&(info.latency_minimum_));\r
318     if(info.params.latency == 0 \r
319       || info.params.latency < info.latency_minimum_ )\r
320     {\r
321       info.params.latency = info.latency_default_;\r
322     }\r
323 \r
324 #ifdef _DEBUG\r
325     wdout << info.name_ << endl;\r
326     wdout << boost::wformat(L"latency default:%d min:%d") % info.latency_default_ % info.latency_minimum_ << endl;\r
327 #endif\r
328     for(int bits = 0;bits < NUM_SAMPLE_BITS;++bits)\r
329     {\r
330       for(int channel = 1;channel < 3;++channel)\r
331       {\r
332         for(int rate = 0;rate < NUM_SAMPLE_RATE;++rate)\r
333         {\r
334           sf::co_task_memory<WAVEFORMATEXTENSIBLE>  a,a1;\r
335           WAVEFORMATEXTENSIBLE f;\r
336 \r
337           //            make_wave_fomat(f,sample_rates[rate],channel,sample_bits[bits]);\r
338           if(sample_bits[bits].valid_bits_per_sample == WAVE_FORMAT_IEEE_FLOAT)\r
339           {\r
340             bits_pair b ={sample_bits[bits].bits_per_sample,sample_bits[bits].bits_per_sample};\r
341             make_wave_format(f,sample_rates[rate],channel,b,WAVE_FORMAT_EXTENSIBLE,KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);\r
342           } else {\r
343             make_wave_format(f,sample_rates[rate],channel,sample_bits[bits],WAVE_FORMAT_EXTENSIBLE,KSDATAFORMAT_SUBTYPE_PCM);\r
344           }\r
345 \r
346           // 排他モード\r
347           HRESULT hr = c->IsFormatSupported(\r
348             AUDCLNT_SHAREMODE_EXCLUSIVE,reinterpret_cast<WAVEFORMATEX*>(&f),reinterpret_cast<WAVEFORMATEX**>(&a));\r
349           if(hr == S_OK){\r
350             info.support_formats_[AUDCLNT_SHAREMODE_EXCLUSIVE][ sample_bits[bits].bits_per_sample ][sample_bits[bits].valid_bits_per_sample][channel][sample_rates[rate]] = 0;\r
351 #ifdef _DEBUG\r
352             wdout << boost::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
353 #endif            }\r
354 \r
355             // make_wave_format(f,sample_rates[rate],channel,sample_bits[bits],WAVE_FORMAT_EXTENSIBLE);\r
356             // 共有モード\r
357             hr = c->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,reinterpret_cast<WAVEFORMATEX*>(&f),reinterpret_cast<WAVEFORMATEX**>(&a1));\r
358             if(hr == S_OK){\r
359               info\r
360                 .support_formats_\r
361                 [AUDCLNT_SHAREMODE_SHARED]\r
362               [ sample_bits[bits].bits_per_sample ]\r
363               [sample_bits[bits].valid_bits_per_sample]\r
364               [channel][sample_rates[rate]] \r
365               = 0;\r
366 #ifdef _DEBUG\r
367               wdout << boost::wformat(L"|share|bits:%02d|vbits:%02d|channel:%02d|rate:%06d|%s|")\r
368                 % sample_bits[bits].bits_per_sample \r
369                 % sample_bits[bits].valid_bits_per_sample \r
370                 % channel % sample_rates[rate] \r
371               % (hr == S_OK?L"OK":L"NG") << endl;\r
372 \r
373 #endif\r
374             }\r
375         }\r
376       }\r
377     }\r
378 #ifdef _DEBUG\r
379     wdout << "-------------------------------" << std::endl;\r
380 #endif\r
381   }\r
382 \r
383   if(output_id_ == deviceInfo->Id->Data())\r
384   {\r
385     info.is_selected_ = true;\r
386   }\r
387   if(default_output_id_ == deviceInfo->Id->Data())\r
388   {\r
389     info.is_default_ = true;\r
390   }\r
391   output_device_infos_.push_back(info);\r
392 \r
393 #ifdef _DEBUG\r
394   wdout << deviceInfo->Name->Data() << std::endl;\r
395 #endif\r
396 }\r
397 \r
398 void wasapi_device_manager::output_enumeration_completed(en::DeviceWatcher^ sender, Platform::Object^ obj)\r
399 {\r
400 \r
401   for(int i = 0;i < output_device_infos_.size();++i)\r
402   {\r
403     device_info& inf(output_device_infos_[i]);\r
404     if(inf.is_selected_ && inf.is_enabled_)\r
405     {\r
406       output_device_index_ = i;\r
407     }\r
408   }\r
409 \r
410   if(output_device_index_ == -1)\r
411   {\r
412     for(int i = 0;i < output_device_infos_.size();++i)\r
413     {\r
414       device_info& inf(output_device_infos_[i]);\r
415       if(inf.is_default_)\r
416       {\r
417         output_device_index_ = i;\r
418         inf.is_selected_ = true;\r
419       }\r
420     }\r
421   }\r
422 \r
423   output_enum_completed_ = true;\r
424 }\r
425 \r
426 void wasapi_device_manager::output_updated(en::DeviceWatcher^ sender, en::DeviceInformationUpdate^ deviceInfo)\r
427 {\r
428 }\r
429 \r
430 void wasapi_device_manager::output_removed(en::DeviceWatcher^ sender, en::DeviceInformationUpdate^ deviceInfo)\r
431 {\r
432 }\r
433 \r
434 void wasapi_device_manager::output_stopped(en::DeviceWatcher^ sender, Platform::Object^ obj)\r
435 {\r
436 }\r
437 \r
438 void wasapi_device_manager::input_added(Windows::Devices::Enumeration::DeviceWatcher^ sender, Windows::Devices::Enumeration::DeviceInformation^ deviceInfo)\r
439 {\r
440   device_info info(deviceInfo);\r
441   IAudioClient2Ptr c;\r
442   // オーディオクライアントを取得\r
443   //    THROW_IF_ERR(ActivateAudioInterface(info.id_.c_str(),__uuidof(IAudioClient2),&c)      );          \r
444   {\r
445     ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOpPtr;\r
446 //    IActivateAudioInterfaceAsyncOperation* asyncOp;\r
447     ComPtr<ActivateAudioInterfaceCompletionHandler> handler(Make<ActivateAudioInterfaceCompletionHandler>());\r
448     HRESULT hr = ActivateAudioInterfaceAsync(info.id_.c_str(),__uuidof(IAudioClient2),nullptr,handler.Get(),asyncOpPtr.GetAddressOf());\r
449 //    asyncOpPtr.Attach(asyncOp);\r
450     if(SUCCEEDED(hr)){\r
451       handler->wait();\r
452       if(handler->ResultCode() == S_OK)\r
453       {\r
454         c = handler->AudioClient();\r
455       } else {\r
456         throw win32_error_exception(handler->ResultCode());\r
457       }\r
458     } else {\r
459       throw win32_error_exception(handler->ResultCode());\r
460     }\r
461   }\r
462   c->GetDevicePeriod(&(info.latency_default_),&(info.latency_minimum_));\r
463   if(info.params.latency == 0 || info.params.latency < info.latency_minimum_ ){\r
464     info.params.latency = info.latency_default_;\r
465   }\r
466 #ifdef _DEBUG\r
467   wdout << info.display_name_ << endl;\r
468   wdout << boost::wformat(L"latency default:%d min:%d") % info.latency_default_ % info.latency_minimum_ << endl;\r
469 #endif\r
470   for(int bits = 0;bits < NUM_SAMPLE_BITS;++bits)\r
471   {\r
472     for(int channel = 1;channel < 3;++channel)\r
473     {\r
474       for(int rate = 0;rate < NUM_SAMPLE_RATE;++rate)\r
475       {\r
476         sf::co_task_memory<WAVEFORMATEXTENSIBLE>  a,a1;\r
477         WAVEFORMATEXTENSIBLE f;\r
478 \r
479         // make_wave_fomat(f,sample_rates[rate],channel,sample_bits[bits]);\r
480         if(sample_bits[bits].valid_bits_per_sample == WAVE_FORMAT_IEEE_FLOAT)\r
481         {\r
482           bits_pair b ={sample_bits[bits].bits_per_sample,sample_bits[bits].bits_per_sample};\r
483           make_wave_format(f,sample_rates[rate],channel,b,WAVE_FORMAT_EXTENSIBLE,KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);\r
484         } else {\r
485           make_wave_format(f,sample_rates[rate],channel,sample_bits[bits],WAVE_FORMAT_EXTENSIBLE,KSDATAFORMAT_SUBTYPE_PCM);\r
486         }\r
487 \r
488         // 排他モード\r
489         HRESULT hr = c->IsFormatSupported(\r
490           AUDCLNT_SHAREMODE_EXCLUSIVE,reinterpret_cast<WAVEFORMATEX*>(&f),reinterpret_cast<WAVEFORMATEX**>(&a));\r
491         if(hr == S_OK){\r
492           info\r
493             .support_formats_\r
494             [AUDCLNT_SHAREMODE_EXCLUSIVE]\r
495           [ sample_bits[bits].bits_per_sample ]\r
496           [sample_bits[bits].valid_bits_per_sample]\r
497           [channel]\r
498           [sample_rates[rate]] = 0;\r
499 #ifdef _DEBUG\r
500           wdout << boost::wformat(L"|exc  |bits:%02d|vbits:%02d|channel:%02d|rate:%06d|%s|") \r
501             % sample_bits[bits].bits_per_sample \r
502             % sample_bits[bits].valid_bits_per_sample \r
503             % channel % sample_rates[rate] \r
504           % (hr == S_OK?L"OK":L"NG") << endl;\r
505 #endif            }\r
506 \r
507           // make_wave_format(f,sample_rates[rate],channel,sample_bits[bits],WAVE_FORMAT_EXTENSIBLE);\r
508           // 共有モード\r
509           hr = c->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,reinterpret_cast<WAVEFORMATEX*>(&f),reinterpret_cast<WAVEFORMATEX**>(&a1));\r
510           if(hr == S_OK){\r
511             info.\r
512               support_formats_\r
513               [AUDCLNT_SHAREMODE_SHARED]\r
514             [sample_bits[bits].bits_per_sample ]\r
515             [sample_bits[bits].valid_bits_per_sample]\r
516             [channel]\r
517             [sample_rates[rate]] = 0;\r
518 #ifdef _DEBUG\r
519             wdout << boost::wformat(L"|share|bits:%02d|vbits:%02d|channel:%02d|rate:%06d|%s|") \r
520               % sample_bits[bits].bits_per_sample \r
521               % sample_bits[bits].valid_bits_per_sample \r
522               % channel \r
523               % sample_rates[rate] \r
524             % (hr == S_OK?L"OK":L"NG") << endl;\r
525 \r
526 #endif\r
527           }\r
528       }\r
529     }\r
530   }\r
531 #ifdef _DEBUG\r
532   wdout << "-------------------------------" << std::endl;\r
533 #endif\r
534 }\r
535 \r
536 if(input_id_ == deviceInfo->Id->Data())\r
537 {\r
538   info.is_selected_ = true;\r
539 }\r
540 if(default_input_id_ == deviceInfo->Id->Data())\r
541 {\r
542   info.is_default_ = true;\r
543 }\r
544 \r
545 input_device_infos_.push_back(info);\r
546 \r
547 #ifdef _DEBUG\r
548 //    if(deviceInfo->IsEnabled){\r
549 wdout << deviceInfo->Name->Data() << std::endl;\r
550 \r
551 //                auto i = deviceInfo->Properties->First();\r
552 //                while(i->HasCurrent)\r
553 //                {\r
554 ////                      wdout << iCurrent->Key->Data() << L"," << i->Current->Value->ToString()->Data() << std::endl;\r
555 //        wdout << i->\r
556 //                        i->MoveNext();\r
557 //                }\r
558 //    }\r
559 #endif\r
560   }\r
561 \r
562   void wasapi_device_manager::input_enumeration_completed(en::DeviceWatcher^ sender, Platform::Object^ obj)\r
563   {\r
564 \r
565     for(int i = 0;i < input_device_infos_.size();++i)\r
566     {\r
567       device_info& inf(input_device_infos_[i]);\r
568       if(inf.is_selected_ && inf.is_enabled_)\r
569       {\r
570         input_device_index_ = i;\r
571       }\r
572     }\r
573 \r
574     if(input_device_index_ == -1)\r
575     {\r
576       for(int i = 0;i < input_device_infos_.size();++i)\r
577       {\r
578         device_info& inf(input_device_infos_[i]);\r
579         if(inf.is_default_)\r
580         {\r
581           input_device_index_ = i;\r
582           inf.is_selected_ = true;\r
583         }\r
584       }\r
585     }\r
586     input_enum_completed_ = true;\r
587   }\r
588 \r
589   void wasapi_device_manager::input_updated(en::DeviceWatcher^ sender, en::DeviceInformationUpdate^ deviceInfo)\r
590   {\r
591   }\r
592 \r
593   void wasapi_device_manager::input_removed(en::DeviceWatcher^ sender, en::DeviceInformationUpdate^ deviceInfo)\r
594   {\r
595   }\r
596 \r
597   void wasapi_device_manager::input_stopped(en::DeviceWatcher^ sender, Platform::Object^ obj)\r
598   {\r
599   }\r
600 }