2016-04-09 10 views
20

Sto provando a scrivere una semplice applicazione di supporto che viene utilizzata per richiedere all'utente di accendere una videocamera se non viene rilevato alcun segnale, che in questo caso significherebbe che il camcorder è spento e/o il cavo HDMI non è collegato a la scheda di acquisizione PCMCIA. Se il segnale è presente, avvio la rispettiva applicazione di registrazione, in questo caso Wirecast.Come rilevare se il cavo HDMI è collegato alla scheda PCMCIA/nessun segnale?

Come potrei andare a creare questo utilizzando C# in VisualStudio?

Aggiornamento

penso di essere un sacco più vicino adesso cercando un suggerimento con sede in uno dei commenti che suggeriscono di utilizzare GraphEdit e vedere cosa è disponibile l'hardware. Sono stato in grado di trovare all'interno delle proprietà del dispositivo di acquisizione, un indicatore "Signal Detected" che cambia da 0 a 1 se il camcorder è acceso/spento o il cavo HDMI è scollegato, che è quello che voglio.

Ora, come potrei fare per accedere a questo flag tramite il codice? Penso di essere molto vicino, ma non so come accedere alla struttura di cElems e pElems dal caGUID. cElems restituisce un valore di 3, che è lo stesso numero di schede visualizzate nella finestra delle proprietà GraphEdit mostrata di seguito in uno screenshot. pElems restituisce un valore diverso ogni volta che eseguo l'app, quindi non sono sicuro di cosa sta succedendo in quella struttura. Penserei che la bandiera che sto cercando si trovi da qualche parte all'interno di quelle strutture.

Codice:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using DirectShowLib; 

namespace Test 
{ 
    static class Program 
    { 
     [STAThread] 

     static void Main() 
     { 
      using (System.Threading.Mutex mutex = new System.Threading.Mutex(false, "Global\\" + appGuid)) 
      { 
       if (!mutex.WaitOne(0, false)) 
       { 
        return; 
       } 

       DsDevice[] capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice); 

       foreach (var dev in capDevices) 
       { 
        if (dev.DevicePath == @"@device:pnp:\\?\pci#ven_1131&dev_7160&subsys_12abf50a&rev_03#6&37bccbbe&0&000800e1#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\{6f814be9-9af6-43cf-9249-c0340100021c}") 
        { 
         IFilterGraph2 m_FilterGraph = (IFilterGraph2)new FilterGraph(); 

         IBaseFilter capFilter = null; 
         ICaptureGraphBuilder2 capGraph = null; 

         capGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); 

         int hr; 

         hr = capGraph.SetFiltergraph(m_FilterGraph); 
         hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); 

         ISpecifyPropertyPages pProp = capFilter as ISpecifyPropertyPages; 

         FilterInfo filterInfo; 
         hr = capFilter.QueryFilterInfo(out filterInfo); 

         DsCAUUID caGUID; 

         hr = pProp.GetPages(out caGUID); 

         Console.WriteLine(caGUID.cElems); 
         Console.WriteLine(caGUID.pElems); 

         // caGUID.cElems returns '3', which is the correct number of tabs in the property pages shown in GraphEdit. 
         // caGUID.pElems returns a different value every time 

         break; 
        } 
       } 

       Application.EnableVisualStyles(); 
       Application.SetCompatibleTextRenderingDefault(false); 
       Application.Run(new Form1()); 
      } 
     } 

     private static string appGuid = "z0a76b5a-02cd-15c5-b9d9-d303zcdde7b9"; 
    } 
} 

enter image description hereenter image description here

+1

Se il programma di cattura utilizza DirectShow, probabilmente c'è un'interfaccia COM che espone informazioni sulle porte fisiche disponibili sull'hardware di ingresso. Suggerisco di guardare il programma "GraphEdit" di DirectShow per costruire un grafico per la lettura di flussi multimediali dal vostro hardware e vedere cosa viene esposto. – Dai

+1

http://www.codeproject.com/Articles/21503/Hardware-Helper-Library-for-C – Mikes3ds

+0

@ Mikes3ds, non penso che la libreria sarebbe d'aiuto? La scheda PCI che sto usando rimane sempre collegata, ma ho bisogno di sapere se il cavo HDMI è collegato a questa scheda e se ha un segnale presente. Sembra che quella libreria sarebbe solo per rilevare se la carta stessa è stata aggiunta o rimossa. – klcjr89

risposta

3

Credo di averlo appena capito! Mi sono imbattuto nel metodo IAMAnalogVideoDecoder: get_HorizontalLocked.

Questo metodo restituisce true o false per me quando il camcorder è spento e/o il cavo HDMI è scollegato, che è perfetto per le mie esigenze.

DirectShowLib può essere trovato qui: https://sourceforge.net/projects/directshownet/files/

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using DirectShowLib; 

namespace Test 
{ 
    static class Program 
    { 
     [STAThread] 

     static void Main() 
     { 
      using (System.Threading.Mutex mutex = new System.Threading.Mutex(false, "Global\\" + appGuid)) 
      { 
       if (!mutex.WaitOne(0, false)) 
       { 
        return; 
       } 

       DsDevice[] capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice); 

       foreach (var device in capDevices) 
       { 
        if (device.DevicePath == @"@device:pnp:\\?\pci#ven_1131&dev_7160 
         &subsys_12abf50a&rev_03#6&37bccbbe&0&000800e1#{65e8773d-8f56 
         -11d0-a3b9-00a0c9223196}\{6f814be9-9af6-43cf 
         -9249-c0340100021c}") 
        { 
         IFilterGraph2 m_FilterGraph = (IFilterGraph2)new FilterGraph(); 

         IBaseFilter capFilter = null; 
         ICaptureGraphBuilder2 capGraph = null; 

         capGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); 

         int hr; 

         hr = capGraph.SetFiltergraph(m_FilterGraph); 
         hr = m_FilterGraph.AddSourceFilterForMoniker(device.Mon, null, device.Name, out capFilter); 

         IAMAnalogVideoDecoder videoDec = capFilter as IAMAnalogVideoDecoder; 

         bool signalDetected = false; 

         hr = videoDec.get_HorizontalLocked(out signalDetected); 

         if (signalDetected == true) 
         { 
          System.Diagnostics.Process.Start(
          @"C:\Users\PC\Documents\HIDDEN_FOLDER\WirecastLaunch.wcst"); 

          return; 
         } 
         else 
         { 
          // Poll for 'signal' change 
         } 

         break; 
        } 
       } 

       Application.EnableVisualStyles(); 
       Application.SetCompatibleTextRenderingDefault(false); 
       Application.Run(new Form1()); 
      } 
     } 

     private static string appGuid = "z0a76b5a-02cd-15c5-b9d9-d303zcdde7b9"; 
    } 
} 
0

Questo in realtà può dipendere dal fornitore, ma il test con un dispositivo simile, il venditore è iscritto a una chiave del Registro personalizzato quando il dispositivo è collegato e rimosso.

  • per rilevare le modifiche del Registro di sistema prima e dopo un evento che uso RegShot, c'è un tutorial pratico sopra here che descrive il processo.
  • Da questo, una volta che si è determinato con sicurezza quale chiave si sta aggiornando, è possibile iscriversi tramite WMI al Registro di sistema. Partenza this answer for how to do this
4

non riesco a tradurre in C#, perché io uso più di Windows in realtà, ma se si sta bene con la traduzione il seguente C++ a C#, è possibile utilizzare lo ..

C'è questo WinAPI chiamato RegisterDeviceNotification che consente di sapere quando un dispositivo è collegato o il suo stato modificato tramite un WinProc-Callback ..

Tratto da mia Github: https://github.com/Brandon-T/HDMI

Vedi anche: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363480(v=vs.85).aspx e https://msdn.microsoft.com/en-us/library/windows/desktop/aa363431(v=vs.85).aspx

Elenco dei GUID di che ho usato nei miei progetti:

GUID devices[] = { 
    {0x4D36E96E, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}, //PlugNPlay Display 
    {0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}, //GUID_DEVINTERFACE_USB_DEVICE 
    {0x0850302A, 0xB344, 0x4FDA, 0x9B, 0xE9, 0x90, 0x57, 0x6B, 0x8D, 0x46, 0xF0}, //GUID_BTHPORT_DEVICE_INTERFACE 
    {0xE6F07B5F, 0xEE97, 0x4a90, 0xB0, 0x76, 0x33, 0xF5, 0x7B, 0xF4, 0xEA, 0xA7}, //GUID_DEVINTERFACE_MONITOR 
    {0x1CA05180, 0xA699, 0x450A, 0x9A, 0x0C, 0xDE, 0x4F, 0xBE, 0x3D, 0xDD, 0x89}, //GUID_DISPLAY_DEVICE_ARRIVAL 
    {0x5B45201D, 0xF2F2, 0x4F3B, 0x85, 0xBB, 0x30, 0xFF, 0x1F, 0x95, 0x35, 0x99}, //GUID_DEVINTERFACE_DISPLAY_ADAPTER 
    {0x1AD9E4F0, 0xF88D, 0x4360, 0xBA, 0xB9, 0x4C, 0x2D, 0x55, 0xE5, 0x64, 0xCD}, //GUID_DEVINTERFACE_VIDEO_OUTPUT_ARRIVAL 
}; 

Poi creare un classe per monitorare un dispositivo specifico:

#include <windows.h> 
#include <dbt.h> 
#include <algorithm> 

class Device 
{ 
private: 
    HDEVNOTIFY hNotify; 

public: 
    Device() : hNotify(NULL) {} 
    Device(HWND window, GUID dev_guid); 
    Device(Device&& dev) : hNotify(NULL) {std::swap(hNotify, dev.hNotify);} 
    ~Device() {UnregisterDeviceNotification(hNotify);} 

    Device(const Device& dev) = delete; 
    Device& operator = (const Device& dev) = delete; 
    Device& operator = (Device&& dev) {std::swap(hNotify, dev.hNotify);return *this;} 
}; 

Device::Device(HWND window, GUID dev_guid) : hNotify(NULL) 
{ 
    if (window) 
    { 
     DEV_BROADCAST_DEVICEINTERFACE filter; 
     memset(&filter, 0, sizeof(filter)); 
     filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); 
     filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 
     filter.dbcc_classguid = dev_guid; 
     hNotify = RegisterDeviceNotification(window, &filter, DEVICE_NOTIFY_WINDOW_HANDLE); //DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES 
    } 
} 

Infine, creare un/messaggio-Finestra di monitorare i dispositivi:

int Create() 
{ 
    WNDCLASSEX wx = {0}; 
    wx.cbSize = sizeof(WNDCLASSEX); 
    wx.lpfnWndProc = WndProc; 
    wx.hInstance = GetModuleHandle(NULL); 
    wx.lpszClassName = "HDMI_MONITOR"; 
    if (RegisterClassEx(&wx)) 
    { 
     MSG msg = {0}; 
     CreateWindowEx(0, "HDMI_MONITOR", "HDMI_MONITOR", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); 
     while(GetMessage(&msg, NULL, 0, 0) > 0) 
     { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
     return msg.wParam; 
    } 
    return 0; 
} 


//The callback function: 
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    static std::unique_ptr<Device> dev; 

    switch(msg) 
    { 
     case WM_CREATE: 
     { 
      dev.reset(new Device(hwnd, devices[0])); //GUID for plug-n-play devices.. 
     } 
     break; 

     case WM_DEVICECHANGE: 
     { 
      DEV_BROADCAST_DEVICEINTERFACE* info = (DEV_BROADCAST_DEVICEINTERFACE*) lParam; 

      switch(wParam) 
      { 
       case DBT_DEVICEARRIVAL: 
        std::cout<<"Device was plugged in\n"; 
        break; 

       case DBT_DEVICEREMOVECOMPLETE: 
        std::cout<<"Device was un-plugged in\n"; 
        break; 

       default: 
        std::cout<<"wParam: "<<(void*)wParam<<"\n"; 
        break; 
      } 
     } 
     break; 

     case WM_DESTROY: 
      PostQuitMessage(0); 
      break; 

     default: 
      return DefWindowProc(hwnd, msg, wParam, lParam); 
    } 
    return 0; 
} 
Problemi correlati