Не хватает возможности автоматического переключения драйвера в режим DVB (из SDR). Для астрометы и подобных SDR-совместимых тюнеров.
Как бы это приделать к ProgDVB?
Чтобы при запуске ProgDVB - был какой-то плагин, проверяющий состояние драйвера и далее запускающий переключение режима в DVB при необходимости (или выдающий какой-то флаг отказа дальнейшего запуска ProgDVB если драйвер в режиме SDR).
Есть конечно радикальное решение - написать лоадер для ProgDVB…
Re: DVB/SDR переключение драйвера
#2А внутри bda.device, как сейчас для астрометы - уже поздно переключать?
Re: DVB/SDR переключение драйвера
#3Поздно.
Дело в том что в режиме SDR - вообще другой драйвер, и нет никакого BDA устройства.
Детект текущего режима делается сканированием SetupDi…(), поиском там VEN_ID/DEV_ID тюнера и проверкой установленного для устройства драйвера (SetupDiGetDeviceProperty DEVPKEY_Device_Children DEVPKEY_Device_DeviceDesc DEVPKEY_Device_Service). Это для Vista+. Для WinXP всё сложнее (CM_Get_Child CM_Get_Device_ID CM_Get_Sibling). Тюнер - композитное USB-устройство…
Если драйвер не подходящий - то для его переключения надо найти в системе все подходящие драйвера (SetupDiEnumDriverInfo) и переустановить нужный (DiInstallDevice). Причём нужно повышение привилегий и отдельные сборки для 64 и 32 бит (DiInstallDevice не работает в среде wow64, там надо запускать 64 битную версию программы).
Надо какой-то внешний модуль делать. Который бы вызывался при запуске ProgDVB. И проверял бы состояние.
И логику действий разную предусмотреть.
1. если тюнер в режиме DVB - продолжается нормальный запуск
2. если тюнер в режиме SDR и запуск был вручную - создать/выгрузить и запустить внешнюю (через UAC) программу для переключения.
3. если попытка переключения в DVB не удалась - тоже ошибка и отмена запуска.
4. если тюнер в режиме SDR и запуск был автоматический (подтвердить UAC некому) - то отмена запуска, ошибка.
Re: DVB/SDR переключение драйвера
#4Но этот sdr будет один для всех(разных) устройств? Или его в ebda для каждого устройства нужно
Re: DVB/SDR переключение драйвера
#5В идеале конечно для каждого устройства отдельно.
Но я думаю что это врядли кому-то надо - те у кого одновременно несколько тюнеров стоят - занимаются какой-то профессиональной деятельностью и переключение DVB/SDR им не нужно.
Поэтому API для переключения может быть вообще без привязки к конкретному тюнеру.
А как привязывать к конкретному тюнеру - я не очень представляю. Поскольку это надо делать на уровне физического устройства (когда например драйвера может совсем не быть некоторое время), а не после драйвера. Разве что по пути InstanceID к устройству. Но перевтыкание в другой порт - и путь другой.
Re: DVB/SDR переключение драйвера
#7Что бы была площадка для эксперементов, могу при первом старта BDA предварительно просто загружатать например sdr.dll. Или sdr.ebda, что бы передавать какие то базовые параметры.
Re: DVB/SDR переключение драйвера
#8Ну, наверно hWnd окна (относительного которого выводить MessageBox с ошибкой например).
И коды возврата, влияющие на дальнейшую работу ProgDVB - продолжать запуск, прекратить запуск.
Например:
// Проверка состояния тюнера,
// возвращает 1 если OK (тюнер в режиме DVB), 0 если тюнер в SDR-режиме, -1 если что-то не понятное (тюнера нет, не идентифицирован режим и т.п.).
INT IsDVBmode(HWND)
// Переключение тюнера в режим DVB. Вызывается только если (0 == IsDVBmode), при 1 или -1 - не вызывается.
// Возвращает 1 если переключение успешно, 0 если переключения не было, -1 ну тоже какая-то нештатная проблема с переключением и переключения не было.
INT SwitchToDVB(HWND)
А стартует ли BDA если твтюнера в системе вообще нет?
Re: DVB/SDR переключение драйвера
#9Никто кроме bda модуля не знает про bda. Соотвественно при старте модуля можно делать что угодно.
То есть в каких то случаях вообще BDA модулю нельзя запускатся?
То есть в каких то случаях вообще BDA модулю нельзя запускатся?
Re: DVB/SDR переключение драйвера
#10Если тюнер в режиме SDR - то по сути тюнера в системе нет.
Сейчас, в такой ситуации - при запуске ошибка «[bda.a3fb] Device not started!»
Re: DVB/SDR переключение драйвера
#11Я вот подумал… Очевидно что не так много тюнеров переключаемых в SDR режим, и для каждого переключаемого тюнера видимо свой алгоритм. Наверно надо в рамках доп.API это делать, например вот если выбрано дополнительное API - астромета…
Например получив ошибку «[bda.a3fb] Device not started!» не выводить её, а сделать проверку на SDR и далее по итогам (если тюнер в режиме SDR) - выводить окно типа «Тюнер в режиме SDR. Выполнить переключение в режим DVB?» Переключить/Игнорировать/Выход.
Или просто «Тюнер в режиме SDR.» Игнорировать/Выход.
Re: DVB/SDR переключение драйвера
#12Вот можно например для начала просто усовершенствовать обработку ошибок, если не удалось запустить BDA и при этом было API астрометы для него.
Тогда делать проверку IsDVBmodeAstrometa131() и выводить подсказку про SDR если обнаружен режим SDR…
Важно что подсказка должна быть если обнаружен SDR, а не если не обнаружен DVB
Астромета есть ещё 135, но там нет SDR режима, поэтому для неё никакой доп.проверки нет.
Т.е. считать что тюнер в режиме SDR можно только по явному обнаружению SDR, а не методом исключения.
Тогда делать проверку IsDVBmodeAstrometa131() и выводить подсказку про SDR если обнаружен режим SDR…
Важно что подсказка должна быть если обнаружен SDR, а не если не обнаружен DVB
Астромета есть ещё 135, но там нет SDR режима, поэтому для неё никакой доп.проверки нет.
Т.е. считать что тюнер в режиме SDR можно только по явному обнаружению SDR, а не методом исключения.
Code: Select all
BOOL sub_device(HDEVINFO hSubDevInfo, wchar_t* id, LPWSTR tDeviceDesc, LPWSTR tService, LPWSTR tDriverVersion)
{
SP_DEVINFO_DATA DeviceInfoData;
WCHAR Buff_InstanceId[MAX_PATH] = L"";
DEVPROPTYPE dpt = 0;
for (UINT index = 0; ; index++) {
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
if (!SetupDiEnumDeviceInfo(hSubDevInfo, index, &DeviceInfoData))
{
return FALSE;
}
if (!SetupDiGetDevicePropertyW(hSubDevInfo, &DeviceInfoData, &DEVPKEY_Device_InstanceId, &dpt, (PBYTE)Buff_InstanceId, sizeof(Buff_InstanceId), NULL, 0))
{
continue;
}
if (StrCmpIW(Buff_InstanceId, id) == 0)
{
tDeviceDesc[0] = 0;
tService[0] = 0;
tDriverVersion[0] = 0;
SetupDiGetDevicePropertyW(hSubDevInfo, &DeviceInfoData, &DEVPKEY_Device_DeviceDesc, &dpt, (PBYTE)tDeviceDesc, 100*2, NULL, 0);
SetupDiGetDevicePropertyW(hSubDevInfo, &DeviceInfoData, &DEVPKEY_Device_Service, &dpt, (PBYTE)tService, 100*2, NULL, 0);
SetupDiGetDevicePropertyW(hSubDevInfo, &DeviceInfoData, &DEVPKEY_Device_DriverVersion, &dpt, (PBYTE)tDriverVersion, 50*2, NULL, 0);
return TRUE;
}
}
return FALSE;
}
// -1 = тюнер не опознан, или может это астромета-135 (а не 131)
// 0 = тюнер в режиме SDR, надо вывести предупреждение пользователю типа «BDA устройство не запущено потому что тюнер в режиме SDR»
// 1 = тюнер в режиме DVB
INT IsDVBmodeAstrometa131()
{
WCHAR text_tuner0131_DeviceDesc[100] = { 0 };
WCHAR text_tuner0131_Service[100] = { 0 };
WCHAR text_tuner0131_DriverVersion[50] = { 0 };
INT result = -1;
HDEVINFO hDevInfo;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
BYTE DeviceInterfaceDetailDataB[MAX_PATH * 2 + 100];
SP_DEVICE_INTERFACE_DETAIL_DATA* DeviceInterfaceDetailData = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(DeviceInterfaceDetailDataB);
DEVPROPTYPE dpt = 0;
WCHAR ChildrenListBuffer[1000];
SP_DEVINFO_DATA DeviceInfo;
HDEVINFO hSubDevInfo;
hDevInfo = SetupDiGetClassDevsW(&(GUID_DEVINTERFACE_USB_DEVICE), 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES); // корневые (композитные/составные) устройства
if (hDevInfo != INVALID_HANDLE_VALUE)
{
hSubDevInfo = SetupDiGetClassDevsW(&(GUID_DEVINTERFACE_USB_DEVICE), L"USB", NULL, DIGCF_ALLCLASSES); // все устройства включая дочерние устройства
if (hSubDevInfo != INVALID_HANDLE_VALUE)
{
for (UINT index = 0; ; index++)
{
DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
if (!SetupDiEnumDeviceInterfaces(hDevInfo, 0, &(GUID_CLASS_USB_DEVICE), index, &DeviceInterfaceData))
{
break;
}
DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
DeviceInterfaceDetailData->DevicePath[0] = 0;
DeviceInfo.cbSize = sizeof(DeviceInfo);
if (SetupDiGetDeviceInterfaceDetailW(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, sizeof(DeviceInterfaceDetailDataB), 0, &DeviceInfo))
{
if (StrCmpNIW(DeviceInterfaceDetailData->DevicePath, L"\\\\?\\usb#vid_15f4&pid_0131#", 26) == 0)
{
ChildrenListBuffer[0] = 0;
ChildrenListBuffer[1] = 0;
if (SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfo, &DEVPKEY_Device_Children, &dpt, (PBYTE)ChildrenListBuffer, sizeof(ChildrenListBuffer), NULL, 0))
{
flag_tuner0131_present = 1;
wchar_t* p = ChildrenListBuffer;
while (true) {
if (p[0] == 0) break;
if (StrCmpNIW(p, L"USB\\VID_15F4&PID_0131&MI_00\\", 28) == 0)
{
if (sub_device(hSubDevInfo, p, text_tuner0131_DeviceDesc, text_tuner0131_Service, text_tuner0131_DriverVersion))
{
if (StrCmpIW(text_tuner0131_Service, L"AMDVBT2USB") == 0)
{
result = 1;
}
else if (StrCmpIW(text_tuner0131_Service, L"WinUSB") == 0)
{
result = 0;
}
else
{
result = -1;
}
}
}
p += lstrlenW(p) + 1;
}
}
}
}
}
SetupDiDestroyDeviceInfoList(hSubDevInfo);
}
SetupDiDestroyDeviceInfoList(hDevInfo);
}
return result;
}
Re: DVB/SDR переключение драйвера
#13Думаю. Ведь SDR к ProgDVB не имеет отношения? Нужно только опредить режим? Или есть какая то польза?
Re: DVB/SDR переключение драйвера
#14Да.
Да. Чтобы не запускать впустую ProgDVB, если тюнер в режиме SDR. И чтобы было понятнее почему ошибка Device not started! - то ли тюнер вывалился физически, то ли его забыли в SDR.
В идеале бы ещё и переключение режима сделать, но это требует запуска через UAC и админские права…
Для SDR - куча разных софтовых радиоприёмников. Причём не только для любителей слушать рации, а и например обычное FM-радио в ассортименте под SDR написано. Даже стереозвук декодируют и RDS тексты принимают.
Штатная астрометовская утилита для FM-радио - весьма тормозная и глючная.
А сторонний софт под WDM-устройства с радио практически не существует, более-менее разве что в capture-режиме в VirtualDub можно добраться до FM-радио.
И получается что SDR режим нужен даже чтобы просто FM-радио послушать на астромете.