PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
TelemedUltrasound.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2  Program: Plus
3  Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4  See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 
8 #include "PlusConfigure.h"
9 
10 #include "TelemedUltrasound.h"
11 
12 #include <math.h>
13 #include <string>
14 
15 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
16 
17 //----------------------------------------------------------------------------
19 {
20  this->ImageWindowHandle = NULL;
21 
22  m_FrameSize[0] = 0;
23  m_FrameSize[1] = 0;
24  m_FrameSize[2] = 1;
25 
26  m_MaximumFrameSize[0] = 512;
27  m_MaximumFrameSize[1] = 512;
28  m_MaximumFrameSize[2] = 1;
29 
30  m_refCount = 0;
31  m_usgfw2 = NULL;
32  m_data_view = NULL;
33  m_probe = NULL;
34  m_mixer_control = NULL;
35  m_depth_ctrl = NULL;
36  m_b_power_ctrl = NULL;
37  m_b_gain_ctrl = NULL;
38  m_b_dynrange_ctrl = NULL;
39  m_b_frequency_ctrl = NULL;
40  m_b_focus_ctrl = NULL;
41  m_usg_control_change_cpnt = NULL;
42  m_usg_control_change_cpnt_cookie = 0;
43  m_usg_device_change_cpnt = NULL;
44  m_usg_device_change_cpnt_cookie = 0;
45 
46  CoInitialize(NULL);
47 }
48 
49 //----------------------------------------------------------------------------
51 {
52  Disconnect(); // just in case it was forgot to be called
53  CoUninitialize();
54 }
55 
56 //----------------------------------------------------------------------------
57 static LRESULT CALLBACK ImageWindowProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
58 {
59  TelemedUltrasound* self = (TelemedUltrasound*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
60  return DefWindowProc(hwnd, iMsg, wParam, lParam) ;
61 }
62 
63 //----------------------------------------------------------------------------
64 void TelemedUltrasound::SetMaximumFrameSize(const FrameSizeType& maxFrameSize)
65 {
66  m_MaximumFrameSize = maxFrameSize;
67 }
68 
69 //----------------------------------------------------------------------------
70 PlusStatus TelemedUltrasound::Connect(int probeId /* = 0 */)
71 {
72  HINSTANCE hInst = GetModuleHandle(NULL);
73 
74  WNDCLASSEX wndclass;
75  wndclass.cbSize = sizeof(wndclass);
76  wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT;
77  wndclass.lpfnWndProc = ImageWindowProc;
78  wndclass.cbClsExtra = 0;
79  wndclass.cbWndExtra = 0;
80  wndclass.hInstance = hInst;
81  wndclass.hIcon = NULL;
82  wndclass.hCursor = NULL;
83  wndclass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
84  wndclass.lpszMenuName = NULL;
85  wndclass.lpszClassName = TEXT("TelemedImageWindow");
86  wndclass.hIconSm = NULL;
87  RegisterClassEx(&wndclass);
88 
89  this->ImageWindowHandle = CreateWindow(TEXT("TelemedImageWindow"), TEXT("Ultrasound"),
90  WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0,
91  m_MaximumFrameSize[0] + 2 * GetSystemMetrics(SM_CXFIXEDFRAME),
92  m_MaximumFrameSize[1] + 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYSIZE),
93  NULL, NULL, hInst, NULL);
94 
95  if (this->ImageWindowHandle == NULL)
96  {
97  LOG_ERROR("Failed to create capture window");
98  return PLUS_FAIL;
99  }
100 
101  SetWindowLongPtr(this->ImageWindowHandle, GWLP_USERDATA, (LONG)this);
102 
103  // Create a bitmap for use in our DIB
104  HDC hdc = GetDC(this->ImageWindowHandle) ;
105  RECT rect;
106  GetClientRect(this->ImageWindowHandle, &rect) ;
107  int cx = rect.right - rect.left;
108  int cy = rect.bottom - rect.top;
109  this->DataHandle = CreateCompatibleBitmap(hdc, cx, cy);
110  GetObject(this->DataHandle, sizeof(BITMAP), (LPVOID) &this->Bitmap) ;
111  // zero indexed window including borders
112  size_t toAllocate = (this->Bitmap.bmWidth + 16) * (this->Bitmap.bmHeight + 4);
113  this->MemoryBitmapBuffer.resize(toAllocate, 0);
114 
115  CreateUsgControls(probeId);
116 
117  return PLUS_SUCCESS;
118 }
119 
120 //----------------------------------------------------------------------------
122 {
123  ReleaseUsgControls(true);
124 
125  if (this->ImageWindowHandle)
126  {
127  LOG_DEBUG("DestroyWindow(this->ImageWindowHandle)");
128  DestroyWindow(this->ImageWindowHandle);
129  this->ImageWindowHandle = NULL;
130  UnregisterClass(TEXT("TelemedImageWindow"), GetModuleHandle(NULL));
131  }
132 }
133 
134 //----------------------------------------------------------------------------
136 {
137  std::cout << "TelemedUltrasound::FreezeDevice(" << freeze << ")" << std::endl;
138  if (m_data_view == NULL) { return; }
139  if (freeze)
140  {
141  m_data_view->put_ScanState(SCAN_STATE_FREEZE);
142  }
143  else
144  {
145  m_data_view->put_ScanState(SCAN_STATE_RUN);
146  }
147 }
148 
149 //----------------------------------------------------------------------------
150 /* **********************************************************************
151 RETURNS:
152 HPALETTE - a handle to a spectrum palette - NULL on failure
153 
154 REMARKS:
155 This function was stolen from Mike Irvine's SEEDIB sample. There's
156 no source code comments in his version either :)
157 
158 This function will build a palette with a spectrum of colors. It is
159 useful when you want to display a number of DIBs each with a different
160 palette yet still have an a good selection of colors to which the
161 DIBs' colors will be mapped.
162 
163 ********************************************************************** */
164 
165 /* **********************************************************************
166 LPBITMAPINFO DSGetBITMAPINFOForDIBSection(HBITMAP)
167 
168 PARAMETERS:
169 HBITMAP - a DIBSection for which to get the BITMAPINFO
170 
171 RETURNS:
172 LPBITMAPINFO - a pointer to a newly allocated memory block containing
173 the BITMAPINFO structure which describes the DIBSection.
174 
175 REMARKS:
176 Allocates and returns a pointer to a BITMAPINFO for the DIBSection.
177 The returned BITMAPINFO contains a color table, even if the
178 bit-depth does not require one - this way the caller can override
179 the optional color table if need be.
180 The caller is responsible for de-allocating the memory block using
181 the CRT function free().
182 
183 ********************************************************************** */
184 
185 LPBITMAPINFO DSGetBITMAPINFOForDIBSection(HBITMAP hBitmap)
186 {
187  DIBSECTION ds;
188  GetObject(hBitmap, sizeof(DIBSECTION), &ds);
189 
190  // load the header and the bitmasks if present
191  // per function comments above, we allocate space for a color
192  // table even if it is not needed
193  LPRGBQUAD prgb = NULL;
194  LPBITMAPINFO pbmi = NULL;
195  if (ds.dsBmih.biCompression == BI_BITFIELDS)
196  {
197  // has a bitmask - be sure to allocate for and copy them
198  pbmi = (LPBITMAPINFO)malloc(sizeof(BITMAPINFOHEADER) + (3 * sizeof(DWORD)) + (256 * sizeof(RGBQUAD)));
199  if (!pbmi)
200  {
201  return (LPBITMAPINFO)NULL;
202  }
203  CopyMemory(&(pbmi->bmiHeader), &(ds.dsBmih), sizeof(BITMAPINFOHEADER) + (3 * sizeof(DWORD)));
204  prgb = (LPRGBQUAD) & (pbmi->bmiColors[3]);
205  }
206  else
207  {
208  // no bitmask - just the header and color table
209  pbmi = (LPBITMAPINFO)malloc(sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
210  if (!pbmi)
211  {
212  return (LPBITMAPINFO)NULL;
213  }
214  CopyMemory(&(pbmi->bmiHeader), &(ds.dsBmih), sizeof(BITMAPINFOHEADER));
215  prgb = pbmi->bmiColors;
216  }
217 
218  // at this point, prgb points to the color table, even
219  // if bitmasks are present
220 
221  // Now for the color table
222  if ((ds.dsBm.bmBitsPixel * ds.dsBm.bmPlanes) <= 8)
223  {
224  // the DIBSection is 256 color or less (has color table)
225  HDC hMemDC = CreateCompatibleDC(NULL);
226  HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
227  GetDIBColorTable(hMemDC, 0, 1 << (ds.dsBm.bmBitsPixel * ds.dsBm.bmPlanes), prgb);
228  SelectObject(hMemDC, hOldBitmap);
229  DeleteDC(hMemDC);
230  }
231  else
232  {
233  // the DIBSection is >8bpp (has no color table) so create a simple (grayscale) color table
234  const int PALETTE_SIZE = 256;
235  for (int i = 0; i < PALETTE_SIZE; i++)
236  {
237  prgb[i].rgbRed = i;
238  prgb[i].rgbGreen = i;
239  prgb[i].rgbBlue = i;
240  prgb[i].rgbReserved = 0;
241  }
242  pbmi->bmiHeader.biClrUsed = PALETTE_SIZE;
243  }
244 
245  return pbmi;
246 }
247 
248 #define BYTESPERLINE(Width, BPP) ((WORD)((((DWORD)(Width) * (DWORD)(BPP) + 31) >> 5)) << 2)
249 
250 //----------------------------------------------------------------------------
252 {
253  if (m_data_view == NULL || m_mixer_control == NULL)
254  {
255  return NULL;
256  }
257 
258  /*
259  {
260  // repaint ultrasound (important if we are in freeze)
261  HDC hdc = ::GetDC(m_usg_wnd);
262  m_mixer_control->Repaint((LONG)m_usg_wnd,(LONG)hdc);
263  ::ReleaseDC(m_usg_wnd,hdc);
264  }
265  */
266 
267  HBITMAP bmp = NULL;
268  m_mixer_control->GetCurrentBitmap((LONG*)&bmp);
269  if (bmp == NULL)
270  {
271  return NULL;
272  }
273 
274  int h = 0;
275  int pitch = 0;
276  {
277  LPBITMAPINFO pbmi = DSGetBITMAPINFOForDIBSection(bmp);
278  if (pbmi == NULL)
279  {
280  ::DeleteObject(bmp);
281  return NULL;
282  }
283  h = abs(pbmi->bmiHeader.biHeight);
284  pitch = BYTESPERLINE(abs(pbmi->bmiHeader.biWidth), pbmi->bmiHeader.biBitCount);
285  m_FrameSize[0] = abs(pbmi->bmiHeader.biWidth);
286  m_FrameSize[1] = abs(pbmi->bmiHeader.biHeight);
287  m_FrameSize[2] = 1;
288  free(pbmi);
289  }
290 
291  int cbBuffer = pitch * h;
292  if (m_FrameBuffer.size() != cbBuffer)
293  {
294  m_FrameBuffer.resize(cbBuffer);
295  }
296  unsigned char* pBuffer = NULL;
297  if (!m_FrameBuffer.empty())
298  {
299  pBuffer = &(m_FrameBuffer[0]);
300  }
301  if (pBuffer == NULL)
302  {
303  ::DeleteObject(bmp);
304  return NULL;
305  }
306 
307  // get a pointer which points to the image bits for a DIBSection
308  DIBSECTION ds;
309  if (!GetObject(bmp, sizeof(DIBSECTION), &ds))
310  {
311  LOG_ERROR("Failed to get pointer to bitmap");
312  ::DeleteObject(bmp);
313  return NULL;
314  }
315  LPBYTE src = (LPBYTE)ds.dsBm.bmBits;
316 
317  memcpy(pBuffer, src, pitch * h);
318 
319  ::DeleteObject(bmp);
320 
321  return pBuffer;
322 }
323 
324 //----------------------------------------------------------------------------
325 void TelemedUltrasound::CreateUsgControl(IUsgDataView* data_view, const IID& type_id, ULONG scan_mode, ULONG stream_id, void** ctrl)
326 {
327  IUsgControl* ctrl2 = NULL;
328  if (data_view == NULL)
329  {
330  return;
331  }
332  data_view->GetControlObj(&type_id, scan_mode, stream_id, &ctrl2);
333  if (ctrl2 != NULL)
334  {
335  HRESULT hr = ctrl2->QueryInterface(type_id, (void**)ctrl);
336  if (hr != S_OK)
337  {
338  *ctrl = NULL;
339  }
340  SAFE_RELEASE(ctrl2);
341  }
342 }
343 
344 //----------------------------------------------------------------------------
345 void TelemedUltrasound::CreateUsgControls(int probeId /* = 0 */)
346 {
347  HRESULT hr = S_OK;
348  IUnknown* tmp_obj = NULL;
349 
350  do
351  {
352  CoInitialize(NULL);
353 
354  IConnectionPointContainer* cpc = NULL;
355 
356  // create main Usgfw2 library object only once and do not destroy till software closing;
357  // it is required in order to receive probe/beamformer arrive/remove events
358  if (m_usgfw2 == NULL)
359  {
360  // create main Usgfw2 library object
361  hr = CoCreateInstance(CLSID_Usgfw2, NULL, CLSCTX_INPROC_SERVER, IID_IUsgfw2, (LPVOID*) &m_usgfw2);
362  if (hr != S_OK)
363  {
364  m_usgfw2 = NULL;
365  break;
366  }
367 
368  // get connection points container
369  hr = m_usgfw2->QueryInterface(IID_IConnectionPointContainer, (void**)&cpc);
370  if (hr != S_OK)
371  { cpc = NULL; }
372 
373  // find connection point
374  if (cpc != NULL)
375  { hr = cpc->FindConnectionPoint(IID_IUsgDeviceChangeSink, &m_usg_device_change_cpnt); }
376 
377  if (hr != S_OK)
378  {
379  m_usg_device_change_cpnt = NULL;
380  m_usg_device_change_cpnt_cookie = 0;
381  }
382  SAFE_RELEASE(cpc);
383 
384  // attach
385  if (m_usg_device_change_cpnt != NULL)
386  {
387  hr = m_usg_device_change_cpnt->Advise((IUnknown*)((IUsgDeviceChangeSink*)this), &m_usg_device_change_cpnt_cookie);
388  }
389 
390  }
391 
392  IUsgCollection* probes_collection = NULL;
393 
394  // get collection of connected probes
395  tmp_obj = NULL;
396  m_usgfw2->get_ProbesCollection(&tmp_obj);
397  if (tmp_obj == NULL)
398  {
399  probes_collection = NULL;
400  break;
401  }
402  hr = tmp_obj->QueryInterface(IID_IUsgCollection, (void**)&probes_collection);
403  tmp_obj->Release();
404  if ((hr != S_OK) || (probes_collection == NULL))
405  {
406  probes_collection = NULL;
407  break;
408  }
409 
410  // get the number of connected probes
411  LONG probes_count = 0;
412  probes_collection->get_Count(&probes_count);
413  if (probes_count == 0)
414  {
415  probes_collection->Release();
416  probes_collection = NULL;
417  break;
418  }
419 
420  // get probe
421  tmp_obj = NULL;
422  if (probeId >= probes_count || probeId < 0)
423  {
424  // invalid probe id provided, connect to first probe
425  LOG_WARNING("Attempted to connect to non-existant US probe with ID " << probeId << ". There are only " << probes_count << " probes connected. Connecting to default probe with ID 0.");
426  probeId = 0;
427  }
428  probes_collection->Item(probeId, &tmp_obj);
429  probes_collection->Release();
430  probes_collection = NULL;
431  if (tmp_obj == NULL)
432  {
433  m_probe = NULL;
434  break;
435  }
436  hr = tmp_obj->QueryInterface(IID_IProbe, (void**)&m_probe);
437  tmp_obj->Release();
438  if ((hr != S_OK) || (m_probe == NULL))
439  {
440  m_probe = NULL;
441  break;
442  }
443 
444  // create main ultrasound scanning object for selected probe
445  m_usgfw2->CreateDataView(m_probe, &m_data_view);
446  if (m_data_view == NULL)
447  {
448  break;
449  }
450 
451  m_data_view->put_ScanState(SCAN_STATE_STOP);
452 
453  IUsgScanMode* mode = NULL;
454  m_data_view->GetScanModeObj(SCAN_MODE_B, &mode);
455  if (mode == NULL)
456  {
457  break;
458  }
459 
460  // get mixer control
461  mode->GetMixerControl(SCAN_MODE_B, 0, &m_mixer_control);
462  mode->Release();
463  mode = NULL;
464  if (m_mixer_control == NULL)
465  {
466  break;
467  }
468 
469  // set B scanning mode
470  m_data_view->put_ScanMode(SCAN_MODE_B);
471 
472  // set ultrasound output window (panel)
473  m_mixer_control->SetOutputWindow((LONG)this->ImageWindowHandle);
474 
475  tagRECT rect1;
476  rect1.left = 0;
477  rect1.top = 0;
478  rect1.right = rect1.left + m_MaximumFrameSize[0];
479  rect1.bottom = rect1.top + m_MaximumFrameSize[1];
480 
481  // set ultrasound output rectangle
482  m_mixer_control->SetOutputRect(&rect1);
483 
484  // set background color that surrounds ultrasound image to black
485  tagPALETTEENTRY clr1;
486  clr1.peRed = 0;
487  clr1.peGreen = 0;
488  clr1.peBlue = 0;
489  clr1.peFlags = 0;
490  m_mixer_control->put_BkColor(clr1);
491 
492  // create depth control
493  tmp_obj = NULL;
494  CreateUsgControl(m_data_view, IID_IUsgDepth, SCAN_MODE_B, 0, (void**)&tmp_obj);
495  if (tmp_obj != NULL)
496  {
497  m_depth_ctrl = (IUsgDepth*)tmp_obj;
498  }
499  else
500  {
501  m_depth_ctrl = NULL;
502  }
503 
504  // create power control
505  tmp_obj = NULL;
506  CreateUsgControl(m_data_view, IID_IUsgPower, SCAN_MODE_B, 0, (void**)&tmp_obj);
507  if (tmp_obj != NULL)
508  {
509  m_b_power_ctrl = (IUsgPower*)tmp_obj;
510  }
511  else
512  {
513  m_b_power_ctrl = NULL;
514  }
515 
516  // create B mode gain control
517  tmp_obj = NULL;
518  CreateUsgControl(m_data_view, IID_IUsgGain, SCAN_MODE_B, 0, (void**)&tmp_obj);
519  if (tmp_obj != NULL)
520  { m_b_gain_ctrl = (IUsgGain*)tmp_obj; }
521  else
522  { m_b_gain_ctrl = NULL; }
523 
524  // create B mode dynamic range control
525  tmp_obj = NULL;
526  CreateUsgControl(m_data_view, IID_IUsgDynamicRange, SCAN_MODE_B, 0, (void**)&tmp_obj);
527  if (tmp_obj != NULL)
528  {
529  m_b_dynrange_ctrl = (IUsgDynamicRange*)tmp_obj;
530  }
531  else
532  {
533  m_b_dynrange_ctrl = NULL;
534  }
535 
536  // create B mode frequency control
537  tmp_obj = NULL;
538  CreateUsgControl(m_data_view, IID_IUsgProbeFrequency3, SCAN_MODE_B, 0, (void**)&tmp_obj);
539  if (tmp_obj != NULL)
540  {
541  m_b_frequency_ctrl = (IUsgProbeFrequency3*)tmp_obj;
542  }
543  else
544  {
545  m_b_frequency_ctrl = NULL;
546  }
547 
548  // create focus depth control
549  tmp_obj = NULL;
550  CreateUsgControl(m_data_view, IID_IUsgFocus, SCAN_MODE_B, 0, (void**)&tmp_obj);
551  if (tmp_obj != NULL)
552  {
553  m_b_focus_ctrl = (IUsgFocus*)tmp_obj;
554  }
555  else
556  {
557  m_b_focus_ctrl = NULL;
558  }
559 
560  // attach to control value change connection point in order to be informed about changed values
561 
562  // get container of connection points
563  hr = m_data_view->QueryInterface(IID_IConnectionPointContainer, (void**)&cpc);
564  if (hr != S_OK)
565  {
566  cpc = NULL;
567  }
568 
569  // find connection point
570  if (cpc != NULL)
571  {
572  hr = cpc->FindConnectionPoint(IID_IUsgCtrlChangeCommon, &m_usg_control_change_cpnt);
573  }
574 
575  if (hr != S_OK)
576  {
577  m_usg_control_change_cpnt = NULL;
578  m_usg_control_change_cpnt_cookie = 0;
579  }
580  SAFE_RELEASE(cpc);
581 
582  // attach
583  if (m_usg_control_change_cpnt != NULL)
584  {
585  hr = m_usg_control_change_cpnt->Advise((IUnknown*)((IUsgCtrlChangeCommon*)this), &m_usg_control_change_cpnt_cookie);
586  }
587 
588  // start ultrasound scanning (Run)
589  m_data_view->put_ScanState(SCAN_STATE_RUN);
590 
591  return;
592  }
593  while (false);
594 
595  ReleaseUsgControls(false);
596 }
597 
598 //----------------------------------------------------------------------------
599 // NOT IMPLEMENTED. MUST USE OnControlChangedBSTR.
600 HRESULT TelemedUltrasound::OnControlChanged(REFIID riidCtrl, ULONG scanMode, LONG streamId, IUsgControl* pControlObj, LONG dispId, LONG flags)
601 {
602  return S_OK;
603 };
604 
605 //----------------------------------------------------------------------------
606 std::wstring GuidToWstring(const GUID& guid)
607 {
608  wchar_t guid_string[37];
609  swprintf_s(
610  guid_string, sizeof(guid_string) / sizeof(guid_string[0]),
611  L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
612  guid.Data1, guid.Data2, guid.Data3,
613  guid.Data4[0], guid.Data4[1], guid.Data4[2],
614  guid.Data4[3], guid.Data4[4], guid.Data4[5],
615  guid.Data4[6], guid.Data4[7]);
616  return guid_string;
617 }
618 
619 //----------------------------------------------------------------------------
620 LPCWSTR TelemedUltrasound::GetInterfaceNameByGuid(BSTR ctrlGUID)
621 {
622  std::wstring ctrlGUIDws(ctrlGUID, SysStringLen(ctrlGUID));
623 
624  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgPower)) == 0) { return L"IUsgPower"; }
625  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgGain)) == 0) { return L"IUsgGain"; }
626  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDepth)) == 0) { return L"IUsgDepth"; }
627  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgRejection2)) == 0) { return L"IUsgRejection2"; }
628  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgFocus)) == 0) { return L"IUsgFocus"; }
629  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDynamicRange)) == 0) { return L"IUsgDynamicRange"; }
630  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgProbeFrequency2)) == 0) { return L"IUsgProbeFrequency2"; }
631  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgProbeFrequency3)) == 0) { return L"IUsgProbeFrequency3"; }
632  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgViewArea)) == 0) { return L"IUsgViewArea"; }
633  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgImageEnhancement)) == 0) { return L"IUsgImageEnhancement"; }
634  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgClearView)) == 0) { return L"IUsgClearView"; }
635  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgFrameAvg)) == 0) { return L"IUsgFrameAvg"; }
636  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgImageOrientation)) == 0) { return L"IUsgImageOrientation"; }
637  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgLineDensity)) == 0) { return L"IUsgLineDensity"; }
638  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgPalette)) == 0) { return L"IUsgPalette"; }
639  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgTgc)) == 0) { return L"IUsgTgc"; }
640  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgImageProperties)) == 0) { return L"IUsgImageProperties"; }
641  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgMixerControl)) == 0) { return L"IUsgMixerControl"; }
642  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgScanLineSelector)) == 0) { return L"IUsgScanLineSelector"; }
643  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgSweepSpeed)) == 0) { return L"IUsgSweepSpeed"; }
644  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsg3dVolumeDensity)) == 0) { return L"IUsg3dVolumeDensity"; }
645  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsg3dVolumeSize)) == 0) { return L"IUsg3dVolumeSize"; }
646  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgSweepMode)) == 0) { return L"IUsgSweepMode"; }
647  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgScanLineProperties)) == 0) { return L"IUsgScanLineProperties"; }
648  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerPRF)) == 0) { return L"IUsgDopplerPRF"; }
649  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgBioeffectsIndices)) == 0) { return L"IUsgBioeffectsIndices"; }
650  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerColorPriority)) == 0) { return L"IUsgDopplerColorPriority"; }
651  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerSignalScale)) == 0) { return L"IUsgDopplerSignalScale"; }
652  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerSignalSmooth)) == 0) { return L"IUsgDopplerSignalSmooth"; }
653  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerWindow)) == 0) { return L"IUsgDopplerWindow"; }
654  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerSampleVolume)) == 0) { return L"IUsgDopplerSampleVolume"; }
655  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerWallFilter)) == 0) { return L"IUsgDopplerWallFilter"; }
656  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerSteerAngle)) == 0) { return L"IUsgDopplerSteerAngle"; }
657  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerCorrectionAngle)) == 0) { return L"IUsgDopplerCorrectionAngle"; }
658  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerColorMap)) == 0) { return L"IUsgDopplerColorMap"; }
659  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerColorThreshold)) == 0) { return L"IUsgDopplerColorThreshold"; }
660  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerBaseLine)) == 0) { return L"IUsgDopplerBaseLine"; }
661  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerPacketSize)) == 0) { return L"IUsgDopplerPacketSize"; }
662  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgPulsesNumber)) == 0) { return L"IUsgPulsesNumber"; }
663  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgCineStream)) == 0) { return L"IUsgCineStream"; }
664  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgCineSink)) == 0) { return L"IUsgCineSink"; }
665  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgSpatialFilter)) == 0) { return L"IUsgSpatialFilter"; }
666  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerColorTransparency)) == 0) { return L"IUsgDopplerColorTransparency"; }
667  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgAudioVolume)) == 0) { return L"IUsgAudioVolume"; }
668  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDopplerSpectralAvg)) == 0) { return L"IUsgDopplerSpectralAvg"; }
669  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgCompoundFrames)) == 0) { return L"IUsgCompoundFrames"; }
670  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgCompoundAngle)) == 0) { return L"IUsgCompoundAngle"; }
671  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgScanType)) == 0) { return L"IUsgScanType"; }
672  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgSteeringAngle)) == 0) { return L"IUsgSteeringAngle"; }
673  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgViewAngle)) == 0) { return L"IUsgViewAngle"; }
674  return L"";
675 }
676 
677 //----------------------------------------------------------------------------
678 LPCWSTR TelemedUltrasound::GetModeNameById(LONG scanMode)
679 {
680  if (scanMode == SCAN_MODE_UNKNOWN) { return L"UNKNOWN"; }
681  if (scanMode == SCAN_MODE_B) { return L"B"; }
682  if (scanMode == SCAN_MODE_M) { return L"M"; }
683  if (scanMode == SCAN_MODE_A) { return L"A"; }
684  if (scanMode == SCAN_MODE_PW) { return L"PW"; }
685  if (scanMode == SCAN_MODE_BM) { return L"BM"; }
686  if (scanMode == SCAN_MODE_BA) { return L"BA"; }
687  if (scanMode == SCAN_MODE_BPW) { return L"BPW"; }
688  if (scanMode == SCAN_MODE_CFM) { return L"CFM"; }
689  if (scanMode == SCAN_MODE_BCFM) { return L"BCFM"; }
690  if (scanMode == SCAN_MODE_BCFM_PW) { return L"BCFM_PW"; }
691  if (scanMode == SCAN_MODE_PDI) { return L"PDI"; }
692  if (scanMode == SCAN_MODE_BPDI) { return L"BPDI"; }
693  if (scanMode == SCAN_MODE_BPDI_PW) { return L"BPDI_PW"; }
694  if (scanMode == SCAN_MODE_DPDI) { return L"DPDI"; }
695  if (scanMode == SCAN_MODE_BDPDI) { return L"BDPDI"; }
696  if (scanMode == SCAN_MODE_BDPDI_PW) { return L"BDPDI_PW"; }
697  if (scanMode == SCAN_MODE_B2) { return L"B2"; }
698  if (scanMode == SCAN_MODE_PWAUDIO) { return L"PWAUDIO"; }
699  if (scanMode == SCAN_MODE_3D) { return L"3D"; }
700  if (scanMode == SCAN_MODES_CUSTOM) { return L"CUSTOM"; }
701  return L"";
702 
703 } // std::string TelemedUltrasound::GetModeNameById
704 
705 //----------------------------------------------------------------------------
706 // if scanning parameters are changed - update user interface controls
707 HRESULT TelemedUltrasound::OnControlChangedBSTR(BSTR ctrlGUID, LONG scanMode, LONG streamId, IUsgControl* pControlObject, LONG dispId, LONG flags)
708 {
709  std::wstring ctrlGUIDws(ctrlGUID, SysStringLen(ctrlGUID));
710 
711  if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgDepth)) == 0)
712  {
713  //DepthUpdateGUI();
714  }
715  else if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgGain)) == 0)
716  {
717  //B_GainUpdateGUI();
718  }
719  else if (ctrlGUIDws.compare(GuidToWstring(IID_IUsgProbeFrequency3)) == 0)
720  {
721  //B_FrequencyUpdateGUI();
722  }
723 
724  std::wstring interfaceName = GetInterfaceNameByGuid(ctrlGUID);
725 
726  if (!interfaceName.empty())
727  {
728  //str.Format(L"OnControlChangedBSTR; %s; scanMode=%s; streamId=%d; dispId=%d; flags=%d;", str1, GetModeNameById(scanMode), streamId, dispId, flags);
729  //WriteToLog(str);
730  }
731  else
732  {
733  //str.Format(L"OnControlChangedBSTR; ctrlGUID=%s; scanMode=%s; streamId=%d; dispId=%d; flags=%d;", CComBSTR(ctrlGUID), GetModeNameById(scanMode), streamId, dispId, flags);
734  //WriteToLog(str);
735  }
736 
737  return S_OK;
738 
739 } // HRESULT TelemedUltrasound::OnControlChangedBSTR
740 
741 // begin: IUnknown
742 
743 //----------------------------------------------------------------------------
744 STDMETHODIMP_(ULONG) TelemedUltrasound::AddRef()
745 {
746  ++m_refCount;
747  return m_refCount;
748 }
749 
750 //----------------------------------------------------------------------------
751 STDMETHODIMP_(ULONG) TelemedUltrasound::Release()
752 {
753  --m_refCount;
754  return m_refCount;
755 }
756 
757 //----------------------------------------------------------------------------
758 STDMETHODIMP TelemedUltrasound::QueryInterface(REFIID riid, void** ppv)
759 {
760  if (riid == IID_IUnknown || riid == IID_IUsgCtrlChangeCommon)
761  {
762  *ppv = (IUsgCtrlChangeCommon*)this;
763  return S_OK;
764  }
765  else if (riid == IID_IUsgDeviceChangeSink)
766  {
767  *ppv = (IUsgDeviceChangeSink*)this;
768  return S_OK;
769  }
770  else if (riid == IID_IDispatch)
771  {
772  *ppv = (IDispatch*)this;
773  return S_OK;
774  }
775  else
776  { return E_NOINTERFACE; }
777 }
778 
779 // end: IUnknown
780 
781 
782 // begin: IDispatch
783 
784 //----------------------------------------------------------------------------
786 {
787  if (pctinfo == NULL)
788  {
789  return E_INVALIDARG;
790  }
791  *pctinfo = 0;
792  return S_OK;
793 }
794 
795 //----------------------------------------------------------------------------
796 HRESULT TelemedUltrasound::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
797 {
798  if (pptinfo == NULL)
799  {
800  return E_INVALIDARG;
801  }
802  *pptinfo = NULL;
803  if (itinfo != 0)
804  {
805  return DISP_E_BADINDEX;
806  }
807  return S_OK;
808 }
809 
810 //----------------------------------------------------------------------------
811 HRESULT TelemedUltrasound::GetIDsOfNames(const IID& riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
812 {
813  // this is not used - must use the same fixed dispid's from Usgfw2 idl file
814  return S_OK;
815 }
816 
817 //----------------------------------------------------------------------------
818 HRESULT TelemedUltrasound::Invoke(DISPID dispIdMember, const IID& riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
819 {
820  // need 2 arguments for device messages
821  if ((dispIdMember >= 1) && (dispIdMember <= 6) && (pDispParams->cArgs == 2))
822  {
823  IUnknown* unkn = NULL;
824  ULONG* res = NULL;
825 
826  VARIANTARG* p1;
827  VARIANTARG* p;
828  p1 = pDispParams->rgvarg;
829 
830  p = p1;
831  if (p->vt == (VT_BYREF | VT_UI4))
832  {
833  res = p->pulVal;
834  }
835  p1++;
836 
837  p = p1;
838  if (p->vt == VT_UNKNOWN)
839  {
840  unkn = (IUnknown*)(p->punkVal);
841  }
842 
843  if (dispIdMember == 1)
844  {
845  OnProbeArrive(unkn, res);
846  }
847  else if (dispIdMember == 2)
848  {
849  OnBeamformerArrive(unkn, res);
850  }
851  else if (dispIdMember == 3)
852  {
853  OnProbeRemove(unkn, res);
854  }
855  else if (dispIdMember == 4)
856  {
857  OnBeamformerRemove(unkn, res);
858  }
859  else if (dispIdMember == 5)
860  {
861  OnProbeStateChanged(unkn, res);
862  }
863  else if (dispIdMember == 6)
864  {
865  OnBeamformerStateChanged(unkn, res);
866  }
867  }
868 
869  // need 6 arguments for control messages
870  else if ((dispIdMember == 2) && (pDispParams->cArgs == 6))
871  {
872  BSTR ctrlGUID = NULL;
873  LONG scanMode = 0;
874  LONG streamId = 0;
875  IUsgControl* pControlObject = NULL;
876  LONG dispId = 0;
877  LONG flags = 0;
878 
879  VARIANTARG* p1;
880  VARIANTARG* p;
881  p1 = pDispParams->rgvarg;
882 
883  p = p1;
884  flags = p->lVal;
885  p1++;
886 
887  p = p1;
888  dispId = p->lVal;
889  p1++;
890 
891  p = p1;
892  pControlObject = (IUsgControl*)(p->pdispVal);
893  p1++;
894 
895  p = p1;
896  streamId = p->lVal;
897  p1++;
898 
899  p = p1;
900  scanMode = p->lVal;
901  p1++;
902 
903  p = p1;
904  ctrlGUID = p->bstrVal;
905  p1++;
906 
907  OnControlChangedBSTR(ctrlGUID, scanMode, streamId, pControlObject, dispId, flags);
908  }
909 
910  return S_OK;
911 
912 } // HRESULT TelemedUltrasound::Invoke
913 
914 // end: IDispatch
915 
916 //----------------------------------------------------------------------------
917 void TelemedUltrasound::ReleaseUsgControls(bool release_usgfw2)
918 {
919  if (m_data_view != NULL)
920  {
921  m_data_view->put_ScanState(SCAN_STATE_STOP);
922  }
923  if (m_usg_control_change_cpnt != NULL)
924  {
925  m_usg_control_change_cpnt->Unadvise(m_usg_control_change_cpnt_cookie);
926  m_usg_control_change_cpnt_cookie = 0;
927  SAFE_RELEASE(m_usg_control_change_cpnt);
928  }
929  SAFE_RELEASE(m_depth_ctrl);
930  SAFE_RELEASE(m_b_power_ctrl);
931  SAFE_RELEASE(m_b_gain_ctrl);
932  SAFE_RELEASE(m_b_dynrange_ctrl);
933  SAFE_RELEASE(m_b_frequency_ctrl);
934  SAFE_RELEASE(m_b_focus_ctrl);
935  SAFE_RELEASE(m_mixer_control);
936  SAFE_RELEASE(m_data_view);
937  SAFE_RELEASE(m_probe);
938 
939  if (release_usgfw2)
940  {
941  if (m_usg_device_change_cpnt != NULL)
942  {
943  m_usg_device_change_cpnt->Unadvise(m_usg_device_change_cpnt_cookie);
944  m_usg_device_change_cpnt_cookie = 0;
945  SAFE_RELEASE(m_usg_device_change_cpnt);
946  }
947  SAFE_RELEASE(m_usgfw2);
948  }
949 
950 }
951 
952 //----------------------------------------------------------------------------
954 {
955  if (m_depth_ctrl == NULL)
956  {
957  LOG_ERROR("TelemedUltrasound::GetDepthMm failed: not connected to device");
958  return PLUS_FAIL;
959  }
960  LONG val;
961  if (m_depth_ctrl->get_Current(&val) != S_OK)
962  {
963  LOG_ERROR("TelemedUltrasound::GetDepthMm failed: failed to retrieve parameter value");
964  return PLUS_FAIL;
965  }
966  depthMm = val;
967  return PLUS_SUCCESS;
968 }
969 
970 //----------------------------------------------------------------------------
972 {
973  if (m_depth_ctrl == NULL)
974  {
975  LOG_ERROR("TelemedUltrasound::SetDepthMm failed: not connected to hardware interface");
976  return PLUS_FAIL;
977  }
978 
979  LONG currentDepthMm = 0;
980  if (m_depth_ctrl->get_Current(&currentDepthMm) != S_OK)
981  {
982  LOG_ERROR("TelemedUltrasound::SetDepthMm failed: failed to get value from device");
983  return PLUS_FAIL;
984  }
985 
986  if (fabs(depthMm - currentDepthMm) > 0.1)
987  {
988  currentDepthMm = depthMm;
989  m_depth_ctrl->put_Current(currentDepthMm);
990  }
991  return PLUS_SUCCESS;
992 }
993 
994 //----------------------------------------------------------------------------
996 {
997  if (m_b_frequency_ctrl == NULL)
998  {
999  LOG_ERROR("TelemedUltrasound::GetFrequencyMHz failed: not connected to device");
1000  return PLUS_FAIL;
1001  }
1002  FREQUENCY3 val;
1003  if (m_b_frequency_ctrl->get_Current(&val) != S_OK)
1004  {
1005  LOG_ERROR("TelemedUltrasound::GetFrequencyMHz failed: failed to retrieve parameter value");
1006  return PLUS_FAIL;
1007  }
1008  freqMhz = (double)(val.nFrequency) / 1000000.0;
1009  return PLUS_SUCCESS;
1010 }
1011 
1012 //----------------------------------------------------------------------------
1014 {
1015  if (m_b_frequency_ctrl == NULL)
1016  {
1017  LOG_ERROR("TelemedUltrasound::SetFrequencyMHz failed: not connected to device");
1018  return PLUS_FAIL;
1019  }
1020 
1021  FREQUENCY3 val_cur;
1022  m_b_frequency_ctrl->get_Current(&val_cur);
1023 
1024  int val_requested_nFrequency = freqMhz * 1000000.0;
1025  if (val_cur.nFrequency == val_requested_nFrequency)
1026  {
1027  return PLUS_SUCCESS;
1028  }
1029 
1030  IUsgValues* usg_values = NULL;
1031  m_b_frequency_ctrl->get_Values(&usg_values);
1032  if (usg_values == NULL)
1033  {
1034  LOG_ERROR("TelemedUltrasound::SetFrequencyMHz failed: failed to retrieve valid parameter values");
1035  return PLUS_FAIL;
1036  }
1037 
1038  // Find the closest item
1039  LONG val_closest_index = -1;
1040  LONG val_closest_nFrequency = 0;
1041  LONG val_count = 0;
1042  usg_values->get_Count(&val_count);
1043  for (LONG i1 = 0; i1 < val_count; i1++)
1044  {
1045  VARIANT item;
1046  usg_values->Item(i1, &item);
1047  if (item.vt == VT_RECORD)
1048  {
1049  FREQUENCY3 val;
1050  val = *((FREQUENCY3*)item.pvRecord);
1051  if ((val_cur.nThiMode == val.nThiMode) &&
1052  (val_closest_index < 0 || abs(val.nFrequency - val_requested_nFrequency) < abs(val_closest_nFrequency - val_requested_nFrequency)))
1053  {
1054  // found a value that is more similar to the requested one
1055  val_closest_index = i1;
1056  val_closest_nFrequency = val.nFrequency;
1057  }
1058  }
1059  VariantClear(&item);
1060  }
1061 
1062  // Set the closest item
1063  PlusStatus status = PLUS_SUCCESS;
1064  if (val_closest_index >= 0)
1065  {
1066  VARIANT item;
1067  usg_values->Item(val_closest_index, &item);
1068  if (item.vt == VT_RECORD)
1069  {
1070  val_cur = *((FREQUENCY3*)item.pvRecord);
1071  }
1072  m_b_frequency_ctrl->put_Current(val_cur);
1073  VariantClear(&item);
1074  }
1075  else
1076  {
1077  LOG_ERROR("TelemedUltrasound::SetFrequencyMHz failed: failed to find a suitable frequency setting");
1078  status = PLUS_FAIL;
1079  }
1080 
1081  SAFE_RELEASE(usg_values);
1082  return status;
1083 }
1084 
1085 //----------------------------------------------------------------------------
1087 {
1088  if (m_b_gain_ctrl == NULL)
1089  {
1090  LOG_ERROR("TelemedUltrasound::SetGainPercent failed: not connected to hardware interface");
1091  return PLUS_FAIL;
1092  }
1093  LONG currentGainPercent = 0;
1094  m_b_gain_ctrl->get_Current(&currentGainPercent);
1095  if (fabs(gainPercent - currentGainPercent) > 0.1)
1096  {
1097  currentGainPercent = gainPercent;
1098  m_b_gain_ctrl->put_Current(currentGainPercent);
1099  }
1100  return PLUS_SUCCESS;
1101 }
1102 
1103 //----------------------------------------------------------------------------
1105 {
1106  if (m_b_gain_ctrl == NULL)
1107  {
1108  LOG_ERROR("TelemedUltrasound::GetGainPercent failed: not connected to hardware interface");
1109  return PLUS_FAIL;
1110  }
1111  LONG currentGainPercent = 0;
1112  if (m_depth_ctrl->get_Current(&currentGainPercent) != S_OK)
1113  {
1114  LOG_ERROR("TelemedUltrasound::GetGainPercent failed: failed to get value from device");
1115  return PLUS_FAIL;
1116  }
1117  gainPercent = currentGainPercent;
1118  return PLUS_SUCCESS;
1119 }
1120 
1121 //----------------------------------------------------------------------------
1123 {
1124  if (m_b_power_ctrl == NULL)
1125  {
1126  LOG_ERROR("TelemedUltrasound::SetPowerDb failed: not connected to hardware interface");
1127  return PLUS_FAIL;
1128  }
1129  LONG currentPowerDb = 0;
1130  m_b_power_ctrl->get_Current(&currentPowerDb);
1131  if (fabs(powerDb - currentPowerDb) > 0.1)
1132  {
1133  currentPowerDb = powerDb;
1134  m_b_power_ctrl->put_Current(currentPowerDb);
1135  }
1136  return PLUS_SUCCESS;
1137 }
1138 
1139 //----------------------------------------------------------------------------
1141 {
1142  if (m_b_power_ctrl == NULL)
1143  {
1144  LOG_ERROR("TelemedUltrasound::GetPowerDb failed: not connected to hardware interface");
1145  return PLUS_FAIL;
1146  }
1147  LONG currentPowerDb = 0;
1148  if (m_b_power_ctrl->get_Current(&currentPowerDb) != S_OK)
1149  {
1150  LOG_ERROR("TelemedUltrasound::GetPowerDb failed: failed to get value from device");
1151  return PLUS_FAIL;
1152  }
1153  powerDb = currentPowerDb;
1154  return PLUS_SUCCESS;
1155 }
1156 
1157 //----------------------------------------------------------------------------
1159 {
1160  double focusDepth = focusDepthPercent / 100;
1161 
1162  if (m_b_focus_ctrl == NULL)
1163  {
1164  LOG_ERROR("TelemedUltrasound::SetFocusDepthPercent failed: not connected to hardware interface");
1165  return PLUS_FAIL;
1166  }
1167  int focus_mode = FOCUS_MODE_MULTI;
1168  int focus_set = 0;
1169  LONG focal_zones_count;
1170  m_b_focus_ctrl->put_CurrentMode(focus_mode);
1171  m_b_focus_ctrl->put_FocusSet(focus_mode, focus_set);
1172  m_b_focus_ctrl->GetFocalZonesCount(focus_mode, focus_set, &focal_zones_count);
1173 
1174  LONG* arr;
1175  arr = new LONG[focal_zones_count];
1176  for (int i = 0; i < focal_zones_count; i++)
1177  {
1178  arr[i] = 0;
1179  }
1180  float zone_width = 1.0 / focal_zones_count;
1181  int enabled_zone = focusDepth / zone_width;
1182  arr[enabled_zone] = 1;
1183  m_b_focus_ctrl->SetFocusState(focus_mode, focus_set, focal_zones_count, arr);
1184  delete[] arr;
1185  return PLUS_SUCCESS;
1186 }
1187 
1188 //----------------------------------------------------------------------------
1190 {
1191  if (m_b_focus_ctrl == NULL)
1192  {
1193  LOG_ERROR("TelemedUltrasound::GetFocusDepthPercent failed: not connected to hardware interface");
1194  return PLUS_FAIL;
1195  }
1196  LONG focus_mode;
1197  m_b_focus_ctrl->get_CurrentMode(&focus_mode);
1198  LONG focus_set;
1199  m_b_focus_ctrl->get_FocusSet(focus_mode, &focus_set);
1200  LONG focal_zones_count;
1201  m_b_focus_ctrl->GetFocalZonesCount(focus_mode, focus_set, &focal_zones_count);
1202 
1203  LONG* arr;
1204  double focusDepth = 0;
1205  arr = new LONG[focal_zones_count];
1206  m_b_focus_ctrl->GetFocusState(focus_mode, focus_set, focal_zones_count, arr);
1207  for (int i = 0; i < focal_zones_count; i++)
1208  {
1209  if (arr[i] != 0)
1210  {
1211  focusDepth = ((float)i) / focal_zones_count;
1212  break;
1213  }
1214  }
1215  focusDepthPercent = focusDepth * 100;
1216  return PLUS_SUCCESS;
1217 }
1218 
1219 //----------------------------------------------------------------------------
1221 {
1222  if (m_b_power_ctrl == NULL)
1223  {
1224  LOG_ERROR("TelemedUltrasound::DynRangeDb failed: not connected to hardware interface");
1225  return PLUS_FAIL;
1226  }
1227  LONG currentDynRangeDb = 0;
1228  m_b_dynrange_ctrl->get_Current(&currentDynRangeDb);
1229  if (fabs(dynRangeDb - currentDynRangeDb) > 0.1)
1230  {
1231  currentDynRangeDb = dynRangeDb;
1232  m_b_dynrange_ctrl->put_Current(currentDynRangeDb);
1233  }
1234  return PLUS_SUCCESS;
1235 }
1236 
1237 //----------------------------------------------------------------------------
1239 {
1240  if (m_b_power_ctrl == NULL)
1241  {
1242  LOG_ERROR("TelemedUltrasound::DynRangeDb failed: not connected to hardware interface");
1243  return PLUS_FAIL;
1244  }
1245  LONG currentDynRangeDb = 0;
1246  if (m_b_dynrange_ctrl->get_Current(&currentDynRangeDb) != S_OK)
1247  {
1248  LOG_ERROR("TelemedUltrasound::DynRangeDb failed: failed to get value from device");
1249  return PLUS_FAIL;
1250  }
1251  dynRangeDb = currentDynRangeDb;
1252  return PLUS_SUCCESS;
1253 }
1254 
1255 // NOTE.
1256 // Here we assume that is used one beamformer with one probe connector.
1257 // If you plan to use beamformer with several probe connectors or several beamformers
1258 // connected at the same time, you will need to store somewhere what probe is active and
1259 // take this into account when arrive messages about probe arrive/remove.
1260 // In most cases you need to do initialization when you do not have active probe and arrives
1261 // new probe. And do deinitialization when is disconnected active probe.
1262 // But if you perform scanning with one probe, and to second connector is
1263 // connected/disconnected another probe, then most likely you do not need to stop scanning or
1264 // reinitialize anything.
1265 
1266 //----------------------------------------------------------------------------
1267 HRESULT TelemedUltrasound::OnProbeArrive(IUnknown* pUsgProbe, ULONG* reserved)
1268 {
1269  std::string str;
1270  // *reserved - index in Usgfw2 ProbesCollection
1271  //str.Format(L"OnProbeArrive; idx=%d;", *reserved);
1272  //WriteToLog(str);
1273 
1275 
1276  return S_OK;
1277 }
1278 
1279 //----------------------------------------------------------------------------
1280 HRESULT TelemedUltrasound::OnProbeRemove(IUnknown* pUsgProbe, ULONG* reserved)
1281 {
1282  std::string str;
1283  // *reserved - index in Usgfw2 ProbesCollection
1284  //str.Format(L"OnProbeRemove; idx=%d;", *reserved);
1285  //WriteToLog(str);
1286  ReleaseUsgControls(false);
1287  return S_OK;
1288 }
1289 
1290 //----------------------------------------------------------------------------
1291 HRESULT TelemedUltrasound::OnBeamformerRemove(IUnknown* pUsgBeamformer, ULONG* reserved)
1292 {
1293  std::string str;
1294  // *reserved - index in Usgfw2 BeamformersCollection
1295  //str.Format(L"OnBeamformerRemove; idx=%d;", *reserved);
1296  //WriteToLog(str);
1297  return S_OK;
1298 }
1299 
1300 //----------------------------------------------------------------------------
1301 HRESULT TelemedUltrasound::OnBeamformerArrive(IUnknown* pUsgBeamformer, ULONG* reserved)
1302 {
1303  std::string str;
1304  // *reserved - index in Usgfw2 BeamformersCollection
1305  //str.Format(L"OnBeamformerArrive; idx=%d;", *reserved);
1306  //WriteToLog(str);
1307  return S_OK;
1308 }
1309 
1310 //----------------------------------------------------------------------------
1311 HRESULT TelemedUltrasound::OnProbeStateChanged(IUnknown* pUsgProbe, ULONG* reserved)
1312 {
1313  //WriteToLog(L"OnProbeStateChanged");
1314  return S_OK;
1315 }
1316 
1317 //----------------------------------------------------------------------------
1318 HRESULT TelemedUltrasound::OnBeamformerStateChanged(IUnknown* pUsgBeamformer, ULONG* reserved)
1319 {
1320  //WriteToLog(L"OnBeamformerStateChanged");
1321  return S_OK;
1322 }
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo)
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
EXTERN_C const IID IID_IUsgCineStream
Definition: USgfw2.h:11484
PlusStatus GetFocusDepthPercent(double &focusDepthPercent)
PlusStatus SetPowerDb(double powerDb)
virtual HRESULT STDMETHODCALLTYPE OnBeamformerArrive(IUnknown *pUsgBeamformer, ULONG *reserved)
EXTERN_C const IID IID_IProbe
Definition: USgfw2.h:3538
virtual HRESULT STDMETHODCALLTYPE OnBeamformerStateChanged(IUnknown *pUsgBeamformer, ULONG *reserved)
virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, const IID &riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
const char int const char const char * src
Definition: phidget22.h:2458
struct _IID IID
EXTERN_C const IID IID_IUsgLineDensity
Definition: USgfw2.h:6016
Phidget_MeshMode mode
Definition: phidget22.h:1332
unsigned char * CaptureFrame()
EXTERN_C const IID IID_IUsgDopplerColorThreshold
Definition: USgfw2.h:9880
EXTERN_C const IID IID_IUsgClearView
Definition: USgfw2.h:6678
EXTERN_C const IID IID_IUsgCtrlChangeCommon
Definition: USgfw2.h:7738
interface IUsgCtrlChangeCommon IUsgCtrlChangeCommon
Definition: USgfw2.h:294
igsioStatus PlusStatus
Definition: PlusCommon.h:40
unsigned short WORD
Definition: ATC3DGm.h:450
EXTERN_C const IID IID_IUsgDopplerSignalScale
Definition: USgfw2.h:10768
EXTERN_C const IID IID_IUsgDepth
Definition: USgfw2.h:5386
EXTERN_C const IID IID_IUsgTgc
Definition: USgfw2.h:6430
void FreezeDevice(bool freeze)
EXTERN_C const IID IID_IUsgCollection
Definition: USgfw2.h:3396
EXTERN_C const IID IID_IUsgSpatialFilter
Definition: USgfw2.h:12146
EXTERN_C const IID IID_IUsgDeviceChangeSink
Definition: USgfw2.h:2710
EXTERN_C const IID IID_IUsgCompoundFrames
Definition: USgfw2.h:15344
EXTERN_C const IID IID_IUsgViewArea
Definition: USgfw2.h:5866
for i
interface IUsgDeviceChangeSink IUsgDeviceChangeSink
Definition: USgfw2.h:91
PlusStatus GetPowerDb(double &powerDb)
interface IUsgDynamicRange IUsgDynamicRange
Definition: USgfw2.h:182
EXTERN_C const IID IID_IUsgDopplerColorPriority
Definition: USgfw2.h:9560
#define PLUS_FAIL
Definition: PlusCommon.h:43
virtual HRESULT STDMETHODCALLTYPE OnControlChangedBSTR(BSTR ctrlGUID, LONG scanMode, LONG streamId, IUsgControl *pControlObject, LONG dispId, LONG flags)
EXTERN_C const IID IID_IUsgMixerControl
Definition: USgfw2.h:2218
EXTERN_C const IID IID_IUsgFocus
Definition: USgfw2.h:6166
interface IUsgGain IUsgGain
Definition: USgfw2.h:161
EXTERN_C const IID IID_IUsgSweepSpeed
Definition: USgfw2.h:9224
EXTERN_C const IID IID_IUsgGain
Definition: USgfw2.h:4344
EXTERN_C const IID IID_IUsgDopplerSignalSmooth
Definition: USgfw2.h:12934
interface IUsgDataView IUsgDataView
Definition: USgfw2.h:49
interface IUsgCollection IUsgCollection
Definition: USgfw2.h:119
interface IUsgDepth IUsgDepth
Definition: USgfw2.h:210
EXTERN_C const IID IID_IUsgFrameAvg
Definition: USgfw2.h:4936
STDMETHODIMP_(ULONG) TelemedUltrasound
PlusStatus SetFocusDepthPercent(double focusDepthPercent)
virtual HRESULT STDMETHODCALLTYPE OnProbeStateChanged(IUnknown *pUsgProbe, ULONG *reserved)
unsigned long DWORD
Definition: ATC3DGm.h:451
EXTERN_C const IID IID_IUsgDopplerPRF
Definition: USgfw2.h:10180
PlusStatus GetGainPercent(double &gainPercent)
PlusStatus GetDepthMm(double &depthMm)
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(const IID &riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid)
Image slice number p
Definition: algo4.m:14
EXTERN_C const IID IID_IUsgDopplerCorrectionAngle
Definition: USgfw2.h:12506
EXTERN_C const IID IID_IUsgRejection2
Definition: USgfw2.h:5086
EXTERN_C const IID IID_IUsgViewAngle
Definition: USgfw2.h:15194
PlusStatus GetDynRangeDb(double &dynRangeDb)
EXTERN_C const IID IID_IUsgDynamicRange
Definition: USgfw2.h:4786
#define BYTESPERLINE(Width, BPP)
EXTERN_C const IID IID_IUsgDopplerColorMap
Definition: USgfw2.h:9410
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
FrameSizeType m_FrameSize
void SetMaximumFrameSize(const FrameSizeType &maxFrameSize)
EXTERN_C const IID IID_IUsgSweepMode
Definition: USgfw2.h:8924
EXTERN_C const IID IID_IUsgPalette
Definition: USgfw2.h:7150
#define SAFE_RELEASE(x)
LPBITMAPINFO DSGetBITMAPINFOForDIBSection(HBITMAP hBitmap)
EXTERN_C const CLSID CLSID_Usgfw2
Definition: USgfw2.h:17642
PlusStatus GetFrequencyMhz(double &freqMHz)
EXTERN_C const IID IID_IUsgProbeFrequency2
Definition: USgfw2.h:5236
EXTERN_C const IID IID_IUsgScanType
Definition: USgfw2.h:14894
EXTERN_C const IID IID_IUsgDopplerPacketSize
Definition: USgfw2.h:10918
interface IUsgScanMode IUsgScanMode
Definition: USgfw2.h:56
EXTERN_C const IID IID_IUsgScanLineProperties
Definition: USgfw2.h:8332
EXTERN_C const IID IID_IUsgCineSink
Definition: USgfw2.h:11822
PlusStatus SetDepthMm(double depthMm)
EXTERN_C const IID IID_IUsgBioeffectsIndices
Definition: USgfw2.h:13404
EXTERN_C const IID IID_IUsgImageProperties
Definition: USgfw2.h:7298
EXTERN_C const IID IID_IUsgProbeFrequency3
Definition: USgfw2.h:13548
const char int const char int flags
Definition: phidget22.h:2552
unsigned long ULONG
Definition: ATC3DGm.h:432
interface IUsgPower IUsgPower
Definition: USgfw2.h:175
interface IUsgControl IUsgControl
Definition: USgfw2.h:154
EXTERN_C const IID IID_IUsg3dVolumeDensity
Definition: USgfw2.h:14018
PlusStatus Connect(int probeId=0)
EXTERN_C const IID IID_IUsgDopplerWindow
Definition: USgfw2.h:10354
virtual HRESULT STDMETHODCALLTYPE OnProbeArrive(IUnknown *pUsgProbe, ULONG *reserved)
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
EXTERN_C const IID IID_IUsgPower
Definition: USgfw2.h:4636
EXTERN_C const IID IID_IUsgAudioVolume
Definition: USgfw2.h:13084
PlusStatus SetGainPercent(double gainPercent)
std::wstring GuidToWstring(const GUID &guid)
EXTERN_C const IID IID_IUsgPulsesNumber
Definition: USgfw2.h:11068
EXTERN_C const IID IID_IUsg3dVolumeSize
Definition: USgfw2.h:13868
interface IUsgProbeFrequency3 IUsgProbeFrequency3
Definition: USgfw2.h:525
interface IUsgValues IUsgValues
Definition: USgfw2.h:168
static LRESULT CALLBACK ImageWindowProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
void CreateUsgControls(int probeId=0)
EXTERN_C const IID IID_IUsgScanLineSelector
Definition: USgfw2.h:8774
EXTERN_C const IID IID_IUsgDopplerColorTransparency
Definition: USgfw2.h:13698
virtual HRESULT STDMETHODCALLTYPE OnProbeRemove(IUnknown *pUsgProbe, ULONG *reserved)
PhidgetHandle * arr
Definition: phidget22.h:1283
EXTERN_C const IID IID_IUsgDopplerBaseLine
Definition: USgfw2.h:10030
EXTERN_C const IID IID_IUsgSteeringAngle
Definition: USgfw2.h:15044
EXTERN_C const IID IID_IUsgImageOrientation
Definition: USgfw2.h:5536
EXTERN_C const IID IID_IUsgfw2
Definition: USgfw2.h:3054
EXTERN_C const IID IID_IUsgImageEnhancement
Definition: USgfw2.h:5696
virtual HRESULT STDMETHODCALLTYPE OnBeamformerRemove(IUnknown *pUsgBeamformer, ULONG *reserved)
virtual HRESULT STDMETHODCALLTYPE OnControlChanged(REFIID riidCtrl, ULONG scanMode, LONG streamId, IUsgControl *pControlObj, LONG dispId, LONG flags)
interface IUsgFocus IUsgFocus
Definition: USgfw2.h:245
PlusStatus SetDynRangeDb(double dynRangeDb)
EXTERN_C const IID IID_IUsgDopplerSpectralAvg
Definition: USgfw2.h:13254
PlusStatus SetFrequencyMhz(double freqMHz)
FrameSizeType m_MaximumFrameSize
std::vector< unsigned char > m_FrameBuffer
EXTERN_C const IID IID_IUsgDopplerSampleVolume
Definition: USgfw2.h:12316
EXTERN_C const IID IID_IUsgDopplerSteerAngle
Definition: USgfw2.h:9730
EXTERN_C const IID IID_IUsgDopplerWallFilter
Definition: USgfw2.h:10594
EXTERN_C const IID IID_IUsgCompoundAngle
Definition: USgfw2.h:15494