powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Получение длинных имен аудиоустройств на Vista/Win7
2 сообщений из 2, страница 1 из 1
Получение длинных имен аудиоустройств на Vista/Win7
    #37942405
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, начало здесь. 13101290
Только вопрос перестал соответствовать названию той темы, посему решил открыть новую.
Дмитрий77Мне очень не нравится, ваш же код это показывает:
Код: vbnet
1.
2.
3.
4.
5.
6.
Private Const MAXPNAMELEN As Long = 32
...
    szPname As String * MAXPNAMELEN
...
    Device = "Динамики (Устройство с поддержк" 'Дефолтное имя устойства Windows 7
    					       'именно в таком виде так как буфер 32 байта - определено из API Viewer)


Хотя это и не мешает выбирать подобный девайс на Win7 (благодаря тому что согласно структуре кода этот глюк "обратимый").

Сейчас работаю в этом направлении. Хотя направление решения уже найдено:

Идея:
waveOutGetDevCaps, Win7 and long device names

Кажется реализация:
http://files.codes-sources.com/fichier_fullscreen.aspx?id=47768&f=class%2FclsAfMasterVolume.cls]class/clsAfMasterVolume.cls du code source VOLUME MASTER : ETAT VOLUME WINDOWS - MODIFIER LE VOLUME, LE MUTE, ET OBTENIR DES INFORMATIONS SUR LA CARTE SON [MODULE DE CLASSE]

Если удастся допилить, возможно выложу.

Короче удалось таки распилить и допилить.
Глядя на этот пример .
Француз если не ошибаюсь вообще до ассамблера дошел со своей
Код: vbnet
1.
Private Function CallPointer(ByVal fnc As Long, ParamArray params()) As Long


при этом до иглы добраться не сумел. У немцев все проще:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Private Function Invoke_(unk As IUnknown, ByVal VtblIndex As Long, _
                         ParamArray Args() As Variant) As Variant
  Dim pArgs() As Long, vt() As Integer, c As Long, i As Long, hr As Long

  c = UBound(Args) + 1
  ReDim pArgs(0 To c + (c > 0)): ReDim vt(0 To UBound(pArgs))
  For i = 0 To c - 1
    vt(i) = VarType(Args(i)): pArgs(i) = VarPtr(Args(i))
  Next i
  hr = DispCallFunc(ObjPtr(unk), VtblIndex * 4, CC_STDCALL, _
                    vbLong, c, vt(0), pArgs(0), Invoke_)
  If hr < 0 Then Err.Raise hr
End Function


Переложил на французский пример, выяснилось что куча структур по сути то и не нужна, а нужно знать только "номер функции" в структуре. И француз похоже эти номера перепутал на самом интересном месте, пришлось подбирать методом тыка.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
'Private Type IPropertyStoreVtbl 'http://msdn.microsoft.com/en-us/library/bb761474%28VS.85%29.aspx
'' IUnknown                                Interface
'  QueryInterface                          As Long '[0]
'  AddRef                                  As Long '[1]
'  Release                                 As Long '[2]
'' IPropertyStore                          Interface
'  GetCount                                As Long '[3]
'  GetAt                                   As Long '[4]
'  GetValue                                As Long '[5]
'  SetValue                                As Long '[6]??
'  Commit                                  As Long'End Type


Плюс используется странный тип As IUnknown , VB его "не предлагает", но как ни странно съедает, этого не понимаю.
Короче получилось (полный тестовый проект приложен):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
Public Function PrintEndpointNames(the_listbox As ListBox) As Boolean
  If IsVistaSimple = False Then
    PrintEndpointNames = False
    Exit Function
  Else
    PrintEndpointNames = True
  End If
  
  the_listbox.Clear

  Dim tGuidMMDeviceEnumerator As GUID
  IIDFromString StrPtr(CLSID_MMDeviceEnumerator), tGuidMMDeviceEnumerator
  
  Dim tGuidIMMDeviceEnumerator As GUID
  IIDFromString StrPtr(IID_IMMDeviceEnumerator), tGuidIMMDeviceEnumerator

  Dim hr As Long
  hr = 0
  
  Dim PKEY_Device_FriendlyName As PROPERTYKEY
  With PKEY_Device_FriendlyName
    IIDFromString StrPtr(GUID_PKEY_Device_FriendlyName), .the_GUID 'CLSIDFromString
    .the_PID = PID_PKEY_Device_FriendlyName
  End With
  
  Dim hlMMDeviceEnumerator          As IUnknown
  Set hlMMDeviceEnumerator = Nothing
  
  Dim hlMMDeviceCollection          As IUnknown
  Set hlMMDeviceCollection = Nothing
  
  Dim hlMMDevice                    As IUnknown
  Set hlMMDevice = Nothing
  
  Dim hlPropertyStore               As IUnknown
  Set hlPropertyStore = Nothing
    
  Dim hlPointerID As Long
  hlPointerID = 0

' get the device enumerator
  hr = CoCreateInstance(tGuidMMDeviceEnumerator, 0, _
                        CLSCTX_ALL, tGuidIMMDeviceEnumerator, _
                        hlMMDeviceEnumerator)
  If hr = S_OK Then
    'get the endpoint collection
    hr = Invoke_(hlMMDeviceEnumerator, 3, eRender, DEVICE_STATE_ACTIVE Or DEVICE_STATE_UNPLUGGED, _
      VarPtr(hlMMDeviceCollection)) '[3]=IMMDeviceEnumerator::EnumAudioEndpoints
    If hr = S_OK Then
      'get the size of the collection
      Dim lCount As Long
      lCount = 0
      hr = Invoke_(hlMMDeviceCollection, 3, VarPtr(lCount)) '[3]=IMMDeviceCollection::GetCount
      If hr = S_OK Then
        Dim i As Long
        Dim bExitLoop As Boolean
        bExitLoop = False
        For i = 0 To lCount - 1
          'Get pointer to endpoint number i.
          hr = Invoke_(hlMMDeviceCollection, 4, Abs(i), VarPtr(hlMMDevice)) '[4]=IMMDeviceCollection::Item
                   'Abs(i), т.к.[in]UINT nDevice, ни Long ни Integer понимать не хочет
          If Not (hr = S_OK) Then
            bExitLoop = True
          Else
            'Get the endpoint ID string.
            hr = Invoke_(hlMMDevice, 5, VarPtr(hlPointerID)) '[5]=IMMDevice::GetId
            If Not (hr = S_OK) Then
              bExitLoop = True
            Else
              'get the human readable name
              hr = Invoke_(hlMMDevice, 4, STGM_READ, VarPtr(hlPropertyStore)) '[4]=IMMDevice::OpenPropertyStore
              If Not (hr = S_OK) Then
                bExitLoop = True
              Else
                Dim varName As PROPVARIANT
                hr = Invoke_(hlPropertyStore, 5, VarPtr(PKEY_Device_FriendlyName), VarPtr(varName))
                '[5]=IPropertyStore::GetValue
                If Not (hr = S_OK) Then
                  bExitLoop = True
                Else
                  the_listbox.AddItem PointerToString(varName.pwszVal)
                  CoTaskMemFree hlPointerID
                  hlPointerID = 0
                  PropVariantClear varName
                  SAFE_RELEASE hlPropertyStore
                  SAFE_RELEASE hlMMDevice
                End If
              End If
            End If
          End If
          If bExitLoop Then Exit For
        Next i
      End If
    End If
  End If
  SAFE_RELEASE hlMMDeviceEnumerator
  SAFE_RELEASE hlMMDeviceCollection
End Function

Private Function SAFE_RELEASE(objecta As IUnknown) As Long
  SAFE_RELEASE = 0
  If Not (objecta Is Nothing) Then
    'SAFE_RELEASE = Invoke_(objecta, 2) '[2]=IUnknown::Release 'может привести к краш-да ну его
    Set objecta = Nothing
  End If
End Function



Остались правда вопросы:
1) Данный код выводит AudioDevices->Player
А нужно еще AudioDevices->Recorder
2) Там возвращается Unicode-строка
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Private Type PROPVARIANT 'http://msdn.microsoft.com/en-us/library/aa380072(v=vs.85).aspx
  vt                                      As Integer 'VT_LPWSTR
  wReserved1                              As Integer
  wReserved2                              As Integer
  wReserved3                              As Integer
  pwszVal                                 As Long   ' union LPWSTR pwszVal;
                                                    'A pointer to a null-terminated Unicode string
                                                    'in the user default locale.
  Padding As Long ' 16 Bytes
End Type


и если винда русская то при стандартном преобразовании -знаки вопроса.
А мне надо получить ANSI я так понимаю независимо от языка.
Ладно, создам отдельную тему про это.
...
Рейтинг: 0 / 0
Получение длинных имен аудиоустройств на Vista/Win7
    #37942596
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Остались правда вопросы:
1) Данный код выводит AudioDevices->Player
А нужно еще AudioDevices->Recorder
Кажется понял:
Код: vbnet
1.
2.
3.
4.
5.
6.
Private Enum EDataFlow
  eRender ' Player's
  eCapture 'Recorder's
  eAll 'Player's + Recorder's
  EDataFlow_enum_count
End Enum



Не понимаю почему в списке нет "мутных" девайсов типа "Modem #4 Line Playback",
waveOutGetDevCaps/waveInGetDevCaps их показывают (и многие проги их показывают),
в XP в панель управления -> аудио они есть, в Win 7 в панели чего-то не нахожу (хотя wave... выдают их).
Миксер-контролов volume/mute у них нет. С чем есть никогда не понимал.
Но подозреваю что их имена никогда не будут больше 31 символа.

Не объяснит никто?
...
Рейтинг: 0 / 0
2 сообщений из 2, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Получение длинных имен аудиоустройств на Vista/Win7
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]