2016-04-09 22 views
20

Ich versuche, eine einfache Hilfeanwendung zu schreiben, die den Benutzer auffordert, einen Camcorder einzuschalten, wenn kein Signal erkannt wird, was in diesem Fall bedeuten würde, dass der Camcorder ausgeschaltet ist und/oder das HDMI-Kabel nicht eingesteckt ist die PCMCIA-Aufnahmekarte. Wenn das Signal vorhanden ist, starte ich die entsprechende Aufnahmeanwendung, in diesem Fall Wirecast.Wie erkennt man, ob das HDMI-Kabel an die PCMCIA-Karte angeschlossen ist/kein Signal?

Wie könnte ich vielleicht über das Erstellen von C# in VisualStudio gehen?

aktualisieren

Ich glaube, ich bin viel jetzt näher durch einen Vorschlag in einer der Kommentare auf Basis versuchen, was darauf hindeutet, GraphEdit zu nutzen und zu sehen, was auf der Hardware zur Verfügung steht. Ich konnte innerhalb der Eigenschaften des Aufnahmegeräts ein "Signal erkannt" -Flag finden, das sich von 0 auf 1 ändert, wenn der Camcorder ein-/ausgeschaltet ist oder das HDMI-Kabel nicht angeschlossen ist, was ich will.

Nun, wie würde ich über das Zugreifen auf diese Flagge durch Code gehen? Ich denke ich bin wirklich nah dran, aber weiß nicht wie ich auf die Struktur cElems und pElems von caGUID zugreifen kann. cElems gibt den Wert 3 zurück. Dies ist die gleiche Anzahl von Registerkarten, die im unten abgebildeten GraphEdit-Eigenschaftenfenster in einem Screenshot angezeigt werden. pElems gibt jedes Mal einen anderen Wert zurück, wenn ich die App starte, daher bin ich mir nicht sicher, was in dieser Struktur passiert. Ich würde denken, dass die Flagge, nach der ich suche, irgendwo in diesen Strukturen liegt.

Code:

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

Wenn Ihr Capture-Programm Directshow nutzt, gibt es wahrscheinlich eine COM-Schnittstelle, die Informationen über physikalische Ports auf dem Eingangs Hardware aussetzt. Ich schlage vor, das DirectShow-Programm "GraphEdit" zu betrachten, um ein Diagramm zum Lesen von Multimediaströmen von Ihrer Hardware zu erstellen und um zu sehen, was ausgesetzt ist. – Dai

+1

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

+0

@ Mikes3ds, glaube ich nicht, dass Bibliothek helfen würde? Die von mir verwendete PCI-Karte bleibt immer angeschlossen, aber ich muss wissen, ob das HDMI-Kabel an diese Karte angeschlossen ist und ob ein Signal vorhanden ist. Es sieht so aus, als würde diese Bibliothek nur dazu dienen, zu erkennen, ob die Karte selbst hinzugefügt oder entfernt wurde. – klcjr89

Antwort

3

Ich glaube, ich habe es gerade herausgefunden! Ich stolperte über die IAMAnalogVideoDecoder Methode: get_HorizontalLocked.

Diese Methode gibt für mich True oder False zurück, wenn der Camcorder ausgeschaltet ist und/oder das HDMI-Kabel nicht angeschlossen ist, was perfekt für meine Bedürfnisse ist.

DirectShowLib sind hier zu finden: 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

Das ist wirklich auf dem Anbieter abhängen kann, aber mit einem ähnlichen Gerät zu testen, ist der Verkäufer auf einen benutzerdefinierten Registrierungsschlüssel zu schreiben, wenn das Gerät eingesteckt ist und entfernt.

  • Registrierungsänderungen zu erfassen, vor und nach einem Ereignis, das ich RegShot verwenden, gibt ein praktisches Tutorial über here, die den Prozess beschreibt, ist.
  • Von diesem, sobald Sie hoffentlich bestimmt haben, welchen Schlüssel sie aktualisieren, können Sie über WMI der Registrierung abonnieren. Check out this answer for how to do this
4

ich nicht zu C# übersetzen kann, weil ich Windows nicht mehr wirklich verwenden, aber wenn Sie mit der Übersetzung des folgenden C++ zu C# in Ordnung sind, dann können Sie es verwenden, ..

Es gibt diese WinAPI namens RegisterDeviceNotification, die Sie wissen lässt, wenn ein Gerät angeschlossen ist oder sein Status über einen WinProc-Callback geändert wurde.

von meinem Github Genommen: auch https://github.com/Brandon-T/HDMI

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

Liste der GUID, die ich in meinen eigenen Projekten verwendet haben:

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 
}; 

Dann erstelle ich ein Klasse zur Überwachung eines bestimmten Geräts:

#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 
    } 
} 

Schließlich schaffe ich ein Fenster/message-Fenster, um die Geräte zu überwachen:

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; 
}