Jump to content
Sign in to follow this  
majstang

Get COM arrays

Recommended Posts

majstang

Hello!

 

Here is a few samples of getting DVBViewer COM safearrays with AutoHotkey:

- ChannelCollection.GetChannelList(List)

- FavoritesManager.GetFavoritesList(List)

- EPGManager.GetAsArray(0,0,0,List)

 

/*
;----------------------------------------------------------------------------
;---ChannelCollection.GetChannelList(vref)-----------------------------------
;----------------------------------------------------------------------------
#NoEnv
iDVBViewer := ComObjActive("DVBViewerServer.DVBViewer")
; https://lexikos.github.io/v2/docs/commands/ComObject.htm#ByRef
VarSetCapacity(var, 24, 0)
vref := ComObject(0x400C, &var)
expected_type := 0x2000 | 0xC
if ((count := iDVBViewer.ChannelCollection.GetChannelList(vref)) && NumGet(var,,"UShort") & expected_type) {
	List := ComObject(expected_type, NumGet(var, 8, "Ptr"), 1)
	Loop %count% {
      Root := List[A_Index - 1, 0]
      Name := List[A_Index - 1, 1]
      Category := List[A_Index - 1, 2]
      Encrypted := List[A_Index - 1, 3]
      TunerType := List[A_Index - 1, 4]
      Frequency := List[A_Index - 1, 5]
      SymbolRate := List[A_Index - 1, 6]
      LNB := List[A_Index - 1, 7]
      PMT := List[A_Index - 1, 8]
      ECM_0 := List[A_Index - 1, 9]
      SatModulation := List[A_Index - 1, 10]
      AVFormat := List[A_Index - 1, 11]
      FEC := List[A_Index - 1, 12]
      CAID_0 :=  List[A_Index - 1, 13]
      Polarity := List[A_Index - 1, 14]
      ECM_1 := List[A_Index - 1, 15]
      LNBSelection := List[A_Index - 1, 16]
      CAID_1 := List[A_Index - 1, 17]
      Diseqc := List[A_Index - 1, 18]
      ECM_2 := List[A_Index - 1, 19]
      AudioPID := List[A_Index - 1, 20]
      CAID_2 := List[A_Index - 1, 21]
      VideoPID := List[A_Index - 1, 22]
      TransportStreamID := List[A_Index - 1, 23]
      telePID := List[A_Index - 1, 24]
      NetworkID := List[A_Index - 1, 25]
      SID := List[A_Index - 1, 26]
      PCRPID := List[A_Index - 1, 27]
      ChannelGroup := List[A_Index - 1, 28]  
	  MsgBox % Root . "`r`nName: " . Name . "`r`nCategory: " . Category . "`r`nEncrypted: " . Encrypted . "`r`nTunerType: " . TunerType 
	  . "`r`nFrequency: " . Frequency . "`r`nSymbolRate: " . SymbolRate . "`r`nLNB: " . LNB . "`r`nPMT: " . PMT . "`r`nECM_0: " . ECM_0
	  . "`r`nSatModulation: " . SatModulation . "`r`nAVFormat: " . AVFormat . "`r`nFEC: " . FEC . "`r`nCAID_0: " . CAID_0
	  . "`r`nPolarity: " . Polarity . "`r`nECM_1: " . ECM_1 . "`r`nLNBSelection: " . LNBSelection . "`r`nCAID_1: " . CAID_1
	  . "`r`nDiseqc: " . Diseqc . "`r`nECM_2: " . ECM_2 . "`r`nAudioPID: " . AudioPID . "`r`nCAID_2: " . CAID_2
	  . "`r`nVideoPID: " . VideoPID . "`r`nTransportStreamID: " . TransportStreamID . "`r`ntelePID: " . telePID
	  . "`r`nNetworkID: " . NetworkID . "`r`nSID: " . SID . "`r`nPCRPID: " . PCRPID . "`r`nChannelGroup: " . ChannelGroup
	} 
	; to access the name of, say, the second channel directly
	MsgBox % List[1, 1]
} 
else {
	DllCall("ole32\VariantClear", "Ptr", &var)
} 
*/
;----------------------------------------------------------------------------
/*
;----------------------------------------------------------------------------
;---FavoritesManager.GetFavoritesList(vref)----------------------------------
;----------------------------------------------------------------------------
#NoEnv
iDVBViewer := ComObjActive("DVBViewerServer.DVBViewer")
; https://lexikos.github.io/v2/docs/commands/ComObject.htm#ByRef
VarSetCapacity(var, 24, 0)
vref := ComObject(0x400C, &var)
expected_type := 0x2000 | 0xC
if ((count := iDVBViewer.FavoritesManager.GetFavoritesList(vref)) && NumGet(var,,"UShort") & expected_type) {
	List := ComObject(expected_type, NumGet(var, 8, "Ptr"), 1)
	Loop %count% {
		Groupname := List[A_Index - 1, 0]
		Name := List[A_Index - 1, 1]
		ChannelID := List[A_Index - 1, 2]
		ID_Number := List[A_Index - 1, 3]
		MsgBox % ID_Number . "`r`nGroup: " . Groupname . "`r`nName: " . Name . "`r`nChannel ID: " . ChannelID
	}  
	; to access the name of, say, the second favourite directly
	MsgBox % List[1, 1]
} 
else {
	DllCall("ole32\VariantClear", "Ptr", &var)
}
;----------------------------------------------------------------------------
*/
/*
;----------------------------------------------------------------------------
;---EPGManager.GetAsArray(0,0,0,vref)----------------------------------------
;----------------------------------------------------------------------------
#NoEnv
iDVBViewer := ComObjActive("DVBViewerServer.DVBViewer")   
; https://lexikos.github.io/v2/docs/commands/ComObject.htm#ByRef
VarSetCapacity(var, 24, 0)
vref := ComObject(0x400C, &var)
expected_type := 0x2000 | 0xC
if ((count := iDVBViewer.EPGManager.GetAsArray(0,0,0,vref)) && NumGet(var,,"UShort") & expected_type) {
	List := ComObject(expected_type, NumGet(var, 8, "Ptr"), 1)
	Loop %count% {
      EPGChannelID := List[A_Index - 1, 0] ;  // Longword (unsigned int)
      EventID := List[A_Index - 1, 1]      ;  // Longword (unsigned int)
      Time := List[A_Index - 1, 2]         ;  // Datetime (Double)
      Duration := List[A_Index - 1, 3]     ;  // Datetime (Double)
      Event := List[A_Index - 1, 4]        ;  // String
      Title := List[A_Index - 1, 5]        ;  // String
      Description := List[A_Index - 1, 6]  ; 	// String
      CharSet := List[A_Index - 1, 7]      ;  // Byte
      Content := List[A_Index - 1, 8]      ;  // Byte   
      MsgBox % EPGChannelID . "`r`nEventID: " . EventID . "`r`nTime: " . Time . "`r`nDuration: " . Duration
	  . "`r`nEvent: " . Event . "`r`nTitle: " . Title . "`r`nDescription: " . Description
	  . "`r`nCharSetList: " . CharSetList . "`r`nContent: " . Content
	} 
    ; to access the EventID of, say, the second EPG_entry directly
	MsgBox % List[1, 1]
} 
else {
	DllCall("ole32\VariantClear", "Ptr", &var)
}
;----------------------------------------------------------------------------
*/

 

Share this post


Link to post
majstang

A more specific Autohotkey sample of utilizing the COM EPGManager.GetAsArray(List) to get all EPG info for shows that are currently aired on your channels. The DMS webinterface uses something similar yellow marking all NOW shows. DVBViewer uses a red vertical line in its EPG marking the now shows instead. This code also fixes the issue with missing time when show starts at midnight (00:00:00) (AHK and VBScript issues). More about that problem here: http://www.DVBViewer.tv/forum/topic/59829-com-epgmanagerget-ttime-000000-missing/?do=findComment&comment=462393

Thanks Griga for explaining it so well. The fix is applied for Time (TDateTime) only although duration is also returned as a floating point (double) (the problem cannot be spotted for duration).

#NoEnv
iDVBViewer := ComObjActive("DVBViewerServer.DVBViewer")

; https://lexikos.github.io/v2/docs/commands/ComObject.htm#ByRef
VarSetCapacity(var, 24, 0)
vref := ComObject(0x400C, &var)
expected_type := 0x2000 | 0xC

DllCall("oleaut32\SystemTimeToVariantTime", "Ptr", (_ := SystemTime.Now()).p, "Double*", oleSt)
if ((count := iDVBViewer.EPGManager.GetAsArray(0, oleSt, oleSt, vref)) && NumGet(ComObjValue(vref),, "UShort") & expected_type) {
	VarSetCapacity(rgIndices, 4*2), st := IsObject(_) ? _ : new SystemTime ; allocate space to store array indices for SafeArrayPtrOfIndex and reuse SystemTime class object if it exists
	List := ComObject(expected_type, NumGet(ComObjValue(vref), 8, "Ptr"), 1)

	Loop %count% {
		EPGChannelID := List[A_Index - 1, 0] ;  // Longword (unsigned int)
		EventID := List[A_Index - 1, 1]      ;  // Longword (unsigned int)
		Time := List[A_Index - 1, 2]         ;  // Datetime (Double)
		Duration := List[A_Index - 1, 3]     ;  // Datetime (Double)
		Event := List[A_Index - 1, 4]        ;  // String
		Title := List[A_Index - 1, 5]        ;  // String
		Description := List[A_Index - 1, 6]  ; 	// String
		CharSet := List[A_Index - 1, 7]      ;  // Byte
		Content := List[A_Index - 1, 8]      ;  // Byte   
        
		if (Time) {
			NumPut(2, NumPut(A_Index - 1, rgIndices, "Int"), "Int") 
			if (DllCall("oleaut32\SafeArrayPtrOfIndex", "Ptr", ComObjValue(List), "Ptr", &rgIndices, "Ptr*", varTime) == 0 && varTime) 
				if (NumGet(varTime+0,, "UShort") & 19)  
					if (DllCall("oleaut32\VariantTimeToSystemTime", "Double", NumGet(varTime+0, 8, "Double"), "Ptr", st.p))
						FormatTime, rawTime, % st.ToString(), yyyy-MM-dd HH:mm:ss
		}
		MsgBox % "EPGChannelID= " EPGChannelID . "`r`nEventID: " . EventID . "`r`nTime: " . (rawTime ? rawTime : "") 
		. "`r`nDuration: " . Duration . "`r`nEvent: " . Event . "`r`nTitle: " . Title . "`r`nDescription: " . Description 
		. "`r`nCharSetList: " . CharSetList . "`r`nContent: " . Content
		rawTime := "" ; clear the rawTime variable so that the next call doesn't get the old date if conversion fails
	
	}

} 
else {
	DllCall("ole32\VariantClear", "Ptr", &var)
}
; Written by Lexikos for EnableUIAccess
/*
    SystemTime - Wrapper for Win32 SYSTEMTIME Structure
        http://msdn.microsoft.com/en-us/library/ms724950
    Usage Examples:
    ; Create structure from string.
    st := SystemTime.FromString(A_Now)
    ; Shortcut:
    st := SystemTime.Now()
    ; Update values.
    st.FromString(A_Now)
    ; Retrieve components.
    year    := st.Year
    month   := st.Month
    weekday := st.DayOfWeek
    day     := st.Day
    hour    := st.Hour
    minute  := st.Minute
    second  := st.Second
    ms      := st.Milliseconds
    ; Set or perform math on component.
    st.Year += 10
    ; Create structure to receive output from DllCall.
    st := new SystemTime
    DllCall("GetSystemTime", "ptr", st.p)
    MsgBox % st.ToString()
    ; Fill external structure.
    st := SystemTime.FromPointer(externalPointer)
    st.FromString(A_Now)
    ; Convert external structure to string.
    MsgBox % SystemTime.ToString(externalPointer)
*/
class SystemTime
{
    FromString(str)
    {
        if this.p
            st := this
        else
            st := new this
        if !(p := st.p)
            return 0
        FormatTime wday, %str%, WDay
        wday -= 1
        FormatTime str, %str%, yyyy M '%wday%' d H m s '0'
        Loop Parse, str, %A_Space%
            NumPut(A_LoopField, p+(A_Index-1)*2, "ushort")
        return st
    }
    FromPointer(pointer)
    {
        return { p: pointer, base: this }   ; Does not call __New.
    }
    ToString(st = 0)
    {
        if !(p := (st ? (IsObject(st) ? st.p : st) : this.p))
            return ""
        VarSetCapacity(s, 28), s := SubStr("000" NumGet(p+0, "ushort"), -3)
        Loop 6
            if A_Index != 2
                s .= SubStr("0" NumGet(p+A_Index*2, "ushort"), -1)
        return s
    }
    Now()
    {
        return this.FromString(A_Now)
    }
    __New()
    {
        if !(this.SetCapacity("struct", 16))
        || !(this.p := this.GetAddress("struct"))
            return 0
        NumPut(0, NumPut(0, this.p, "int64"), "int64")
    }
    __GetSet(name, value="")
    {
        static fields := {Year:0, Month:2, DayOfWeek:4, Day:6, Hour:8
                            , Minute:10, Second:12, Milliseconds:14}
        if fields.HasKey(name)
            return value=""
                ? NumGet(       this.p + fields[name], "ushort")
                : NumPut(value, this.p + fields[name], "ushort")
    }
    static __Get := SystemTime.__GetSet
    static __Set := SystemTime.__GetSet
}

 

Edited by majstang

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...