OSDN Git Service

最初のコミット
[winaudioj/wasapi2.git] / wasapi2 / input_thread.cpp
1 /*\r
2 ==============================================================================\r
3 \r
4 This file is part of the async\r
5 Copyright 2005-10 by Satoshi Fujiwara.\r
6 \r
7 async can be redistributed and/or modified under the terms of the\r
8 GNU General Public License, as published by the Free Software Foundation;\r
9 either version 2 of the License, or (at your option) any later version.\r
10 \r
11 async is distributed in the hope that it will be useful,\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 GNU General Public License for more details.\r
15 \r
16 You should have received a copy of the GNU General Public License\r
17 along with async; if not, visit www.gnu.org/licenses or write to the\r
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, \r
19 Boston, MA 02111-1307 USA\r
20 \r
21 ==============================================================================\r
22 */\r
23 #include "StdAfx.h"\r
24 #include <commctrl.h>\r
25 \r
26 #if _DEBUG\r
27 #define _CRTDBG_MAP_ALLOC\r
28 #include <crtdbg.h>\r
29 #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)\r
30 #endif\r
31 \r
32 #include "message_loop.h"\r
33 #include "sf_com.h"\r
34 #include "application.h"\r
35 #include "input_thread.h"\r
36 #include "dout.h"\r
37 #include "async_reader.h"\r
38 \r
39 using namespace std;\r
40 \r
41 namespace sf {\r
42 \r
43 void input_thread_t::thread_main()\r
44 {\r
45   // COMの初期化\r
46   sf::com_initialize init(0,multi_threaded);\r
47 \r
48   // MMCSSの初期化\r
49   sf::av_mm_thread_characteristics avmm(wstring(L"Pro Audio"));\r
50   avmm.set_priority(AVRT_PRIORITY_HIGH);\r
51  \r
52   //// input デバイスの初期化\r
53   //wasapi_device_manager::ptr m(wasapi_device_manager::instance());\r
54   //apply_config_(\r
55   // m->current_input_device_index(),\r
56   // m->current_input_device().params\r
57   //);\r
58   change_status(status_pause);\r
59   application& app(*application::instance());\r
60   int status = STATUS_ERROR;\r
61   BYTE *buffer = 0;\r
62   index_ = 0;\r
63   int source_counter ,dest_counter;\r
64   source_counter  = dest_counter = 0;\r
65   //// 出力デバイスが稼働するまで待つ\r
66   //app.output_thread().wait_status(output_thread_t::status_processing,10);\r
67   //apply_config_(\r
68   //wasapi_device_manager::instance()->current_input_device_index(),\r
69   //wasapi_device_manager::instance()->current_input_device().params);\r
70   change_status(status_device_config);\r
71   while(status = status_.load(),status != status_exit)\r
72   {\r
73     // イベントを待つ\r
74     switch(status)\r
75     {\r
76     case status_device_config:\r
77       if(wasapi_input_)\r
78       {\r
79         wasapi_input_->stop();\r
80         dest_counter = 0;\r
81       }\r
82       change_status(status_device_config_ok);\r
83       break;\r
84     case status_process:\r
85       if(!wasapi_input_->is_start()){\r
86         wasapi_input_->start();\r
87       }\r
88       change_status(status_processing);\r
89     case status_processing:\r
90       {\r
91         wasapi_input_->wait();// 入力待ち\r
92         get_buffer g(*wasapi_input_);// キャプチャバッファの取得\r
93         if(g.size() && g != 0)\r
94         {\r
95           source_counter = 0;\r
96           while(source_counter != g.size())\r
97           {\r
98             BYTE * src = g + source_counter * wasapi_input_->get_frame_size();\r
99             int size_byte_src = g.size_byte() - source_counter * wasapi_input_->get_frame_size();\r
100             int size_src = g.size() - source_counter;\r
101 \r
102             BYTE * dest = buffer_[index_].get() + dest_counter * app.output_device().get_frame_size();\r
103             int size_byte_dest = app.output_device().get_buffer_byte_size() - dest_counter * app.output_device().get_frame_size();\r
104             int size_dest = app.output_device().get_buffer_size() - dest_counter;\r
105 \r
106             if(size_src <= size_dest)\r
107             {\r
108               ::CopyMemory(dest,src,size_byte_src);\r
109               source_counter += size_src;\r
110               dest_counter += size_src;\r
111             } else if(size_src > size_dest)\r
112             {\r
113               ::CopyMemory(dest,src,size_byte_dest);\r
114               source_counter += size_dest;\r
115               dest_counter += size_dest;\r
116             }\r
117             if(dest_counter == app.output_device().get_buffer_size())\r
118             {\r
119               if(ringbuffer_.enqueue(buffer_[index_].get()))\r
120               {\r
121                 index_ = (index_ + 1) & (buffer_.size() - 1);\r
122               }\r
123               dest_counter = 0;\r
124             }\r
125           }\r
126         }\r
127       }\r
128       break;\r
129     case status_pause:\r
130       if(wasapi_input_)\r
131       {\r
132         wasapi_input_->stop();\r
133       }\r
134       change_status(status_pause_ok);\r
135       break;\r
136      default:\r
137       WaitForSingleObject(event_.get(),WAIT_TIMEOUT_DEFAULT);\r
138       break;\r
139     }\r
140   }\r
141 loop_end:\r
142   ;\r
143   DOUT(L"##### input_threadは終了!" << endl);\r
144   if(wasapi_input_ && wasapi_input_->is_start())\r
145   {\r
146     wasapi_input_->stop();\r
147   }\r
148   wasapi_input_.reset();\r
149 };\r
150 \r
151 void input_thread_t::apply_config(int device_index,wasapi_device_manager::device_info::params_t& params)\r
152 {\r
153   if(status() != status_device_config_ok){\r
154     change_and_wait(status_device_config,status_device_config_ok);\r
155   }\r
156   apply_config_(device_index,params);\r
157   init_buffer();\r
158   change_and_wait(status_process,status_processing);\r
159 }\r
160 \r
161 void input_thread_t::apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params)\r
162 {\r
163   \r
164   WAVEFORMATEXTENSIBLE form;\r
165   if(wasapi_input_)\r
166   {\r
167     if(wasapi_input_->is_start())\r
168     {\r
169       wasapi_input_->stop();\r
170     }\r
171     wasapi_input_.reset();\r
172   };\r
173 \r
174   //bits_pair bits = {params.bits,params.valid_bits};\r
175   //make_wave_format(form,params.sample_rate,params.channel,bits);\r
176 \r
177   try {\r
178     if(params.exclusive_mode)\r
179     {\r
180       if(params.event_mode){\r
181         wasapi_input_.reset(new sf::wasapi_capture_exclusive_event(device_index,params));\r
182       } else {\r
183         wasapi_input_.reset(new sf::wasapi_capture_exclusive_timer(device_index,params));\r
184       };\r
185     } else {\r
186       if(params.event_mode)\r
187       {\r
188         wasapi_input_.reset(new sf::wasapi_capture_shared_event(device_index,params));\r
189       } else {\r
190         wasapi_input_.reset(new sf::wasapi_capture_shared_timer(device_index,params));\r
191       }\r
192     }\r
193   } catch (win32_error_exception& e)\r
194   {\r
195 \r
196     //window_->message_box((boost::wformat(L"WASAPI初期化エラーが発生しました。設定パラメータを見なおしてください。%s") % e.error()).str(),wstring(L"WASAPI初期化エラー"));\r
197     throw;\r
198   }\r
199 \r
200   wasapi_device_manager::instance()->select_input_device(device_index);\r
201   wasapi_device_manager::instance()->current_input_device().params = params;\r
202 \r
203 }\r
204 \r
205   //void input_thread_t::init_buffer()\r
206   //{\r
207   //  audio_base& in(application::instance()->input_device());\r
208   //  for(int i = 0,size = buffer_.size();i < size;++i)\r
209   //  {\r
210   //    buffer_[i].reset(reinterpret_cast<uint8_t*>(_aligned_malloc(sizeof(uint8_t) * in.get_buffer_byte_size(),16)));\r
211   //  }\r
212   //}\r
213 \r
214 \r
215 }\r
216 \r