VERSION 1.0 CLASS BEGIN MultiUse = -1 'True Persistable = 0 'NotPersistable DataBindingBehavior = 0 'vbNone DataSourceBehavior = 0 'vbNone MTSTransactionMode = 0 'NotAnMTSObject END Attribute VB_Name = "cPlugin" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = True Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Classe de comunicação com o plugin ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Guarda o nome do objeto Private Const ST_MY_NAME As String = "cPlugin" ' Posição inválida de tempo Private Const LN_INVALID_TIME_POS As Long = 0 ' Tamanho do buffer de leitura Private Const WINAMP_API_BUFF_SIZE As Long = 1024 Private Const WINAMP_PATH_SIZE_W As Long = 520 ' Comandos de SendMessage / Valores Private Const IPC_GET_LINK = &H1 Private Const IPC_GET_CURRENT_TIME_POS = &H2 Private Const IPC_GET_LIST_POS = &H3 Private Const IPC_SND_NOOP = &H4 Private Const IPC_SND_CLOSED = &H5 Private Const IPC_GET_PHWND = &H6 Private Const IPC_GET_COMPATIBLE_VERSION = &H7 Private Const IPC_NOTHING = &H0 ' Comandos de Recepção Private Const IPC_SET_STOP = &H1 Private Const IPC_SET_STILL_STOP = &H2 Private Const IPC_SET_CLOSE = &H3 Private Const IPC_GET_NOOP = &H4 ' Comandos de Retorno Private Const IPC_RET_FALSE = &H0 Private Const IPC_RET_TRUE = &H1 ' Estados do plugin Private Type PLUGIN_STATUS psCoreSet As Boolean End Type ' Tipo TAG em wide-char Private Type MUSIC_TAG stFile As String * WINAMP_PATH_SIZE_W stArtist As String * WINAMP_API_BUFF_SIZE stAlbum As String * WINAMP_API_BUFF_SIZE stTitle As String * WINAMP_API_BUFF_SIZE lnDuration As Long End Type ' Guarda estado do plugin Private ps_Status As PLUGIN_STATUS ' Endereço de comunicação de saída Private ln_PluginHwnd As Long ' Endereço do player Private ln_PlayerHwnd As Long ' Conexão com o core Private obj_Core As cCore ' Referência dos dados da música Private cm_Music As cMusic ' Versão do plugin Private ln_PluginCompatibleVersion As Long ' Plugin com TAG (v1) Private bl_TAGv1 As Boolean ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade do objeto Music ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Get Music() As cMusic ' Retorna Set Music = cm_Music End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade do handle do plugin ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Get PluginHwnd() As Long ' Retorna PluginHwnd = ln_PluginHwnd End Property Public Property Let PluginHwnd(lnValue As Long) ' Seta ln_PluginHwnd = lnValue End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade do core ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Get Core() As cCore ' Retorna Set Core = obj_Core End Property Public Property Let Core(cInput As cCore) ' Seta Set obj_Core = cInput ' Informa que há core ps_Status.psCoreSet = True End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade do tipo de precisão de duração da faixa ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Get MiliTrackLength() As Boolean ' Retorna MiliTrackLength = bl_TAGv1 End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Acorda o plugin ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Sub Wakeup() Dim ret As Long On Error GoTo ErrTreat: ' Envia uma mensagem ao plugin ret = SendMessage(ln_PluginHwnd, WM_USER, lnHandler, IPC_GET_LINK) ' Verifica se a resposta fora positiva If (ret = IPC_RET_TRUE) Then ' Retorna o hwnd do player ln_PlayerHwnd = SendMessage(ln_PluginHwnd, WM_USER, IPC_NOTHING, IPC_GET_PHWND) ' Retorna versão de compatibilidade do plugin ln_PluginCompatibleVersion = SendMessage(ln_PluginHwnd, WM_USER, IPC_NOTHING, IPC_GET_COMPATIBLE_VERSION) ' Trata versões do plugin LoadPluginVersion ' Verifica se há core If ps_Status.psCoreSet Then ' Avisa ao core que o plugin está pronto obj_Core.PluginEvent peUp End If Else ' Exibe mensagem de erro ShowErrMessage Msg("StartErrorBadHandle"), vbCritical, Msg("ErrorTitle") ' Fecha programa fMain.closeProgram End If Exit Sub ErrTreat: LogErrMessage Err.Description, ST_MY_NAME + ".Wakeup" End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Trata diferentes versões do plugin ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub LoadPluginVersion() ' Verifica a versão Select Case ln_PluginCompatibleVersion ' Sem versão Case 0 ' Tag versão antiga bl_TAGv1 = False ' Versão 1 Case 1 ' Tag versão nova bl_TAGv1 = True End Select End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Atualiza o timer geral ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Sub Update() ' Envia mensagem ao plugin, o retorno será o timer ln_TrackPosition = SendMessage(ln_PluginHwnd, WM_USER, IPC_NOTHING, IPC_GET_CURRENT_TIME_POS) ' Modo debug? #If debugmode Then fDebug.cPlugin_LastPluginTime = ln_TrackPosition #End If ' Se posição for inválida If (ln_TrackPosition = LN_INVALID_TIME_POS) Then ' Se o plugin não estiver mais respondendo If Not Alive Then ' Fecha o programa fMain.closeProgram End If End If End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade da faixa atual ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Get PlaylistPosisition() As Long ' Envia mensagem ao plugin, o retorno será a posição PlaylistPosisition = SendMessage(ln_PluginHwnd, WM_USER, IPC_NOTHING, IPC_GET_LIST_POS) End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade do hwnd do player ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Get PlayerHwnd() As Long ' Retorna valor coletado no wakeup PlayerHwnd = ln_PlayerHwnd End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Finaliza o programa ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Sub closeProgram() On Error GoTo ErrTreat: ' Se possui core aberto If ps_Status.psCoreSet Then ' Repassa ao core obj_Core.PluginEvent peClose End If ' Se o plugin estiver aberto If Alive Then ' Envia mensagem ao plugin, informando que o programa fora fechado pelo usuário SendMessage ln_PluginHwnd, WM_USER, IPC_NOTHING, IPC_SND_CLOSED End If ' Fecha o programa fMain.closeProgram Exit Sub ErrTreat: LogErrMessage Err.Description, ST_MY_NAME + ".closeProgram" End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Retorna se o plugin está vivo ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Get Alive() As Boolean Dim ret As Long ' Envia uma mensagem ao plugin ret = SendMessage(ln_PluginHwnd, WM_USER, IPC_NOTHING, IPC_SND_NOOP) ' Verifica se a resposta fora positiva If (ret = IPC_RET_TRUE) Then ' Retorna que está vivo Alive = True Else ' Retorna que o plugin não existe mais Alive = False End If End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Recepção de mensagens ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Function ProcessMessage(Msg As Long, wParam As Long, lParam As Long, rParam As Long) As Boolean On Error GoTo ErrTreat: ' Verifica qual o tipo da mensagem Select Case Msg ' Se for cópia de estrutura Case WM_COPYDATA ' Se conseguiu atualizar informações If updateTag(lParam) Then ' Se há core If ps_Status.psCoreSet Then ' Informa ao core que atualizou a música obj_Core.PluginEvent pePlay End If End If ' Retorna que processou ProcessMessage = True ' Se for um comando do player Case WM_USER ' Se há core If ps_Status.psCoreSet Then ' Modo debug? #If debugmode Then fDebug.cPlugin_LastMsg = lParam #End If ' Verifica qual é o comando Select Case lParam ' Parou a música Case IPC_SET_STOP ' Informa ao core que parou obj_Core.PluginEvent peStop ' Se a música continua parada Case IPC_SET_STILL_STOP ' Informa ao core obj_Core.PluginEvent peNothing ' Se fechou o programa Case IPC_SET_CLOSE ' Informa ao core que fechou o plugin obj_Core.PluginEvent peClose ' Fecha o programa fMain.closeProgram ' Comando NOOP Case IPC_GET_NOOP ' Retorna rParam = IPC_RET_TRUE End Select End If ' Retorna que processou ProcessMessage = True ' Outros casos Case Else ' Retorna que não processou dados ProcessMessage = False End Select Exit Function ErrTreat: LogErrMessage Err.Description, ST_MY_NAME + ".ProcessMessage", Msg End Function ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Atualiza o TAG da música ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Function updateTag(lnAddress As Long) As Boolean Dim metaInfo As COPYDATASTRUCT Dim metaData As MUSIC_TAG On Error GoTo ErrTreat: ' Copia informações para memória CopyMemoryAddr metaInfo, lnAddress, Len(metaInfo) ' Verifica se é válido If (metaInfo.cbData = Len(metaData)) Then ' Copia para memória CopyMemoryAddr metaData, metaInfo.lpData, metaInfo.cbData ' Atualiza objeto de música cm_Music.Album = retString(unspaceString(wcharTOwstring(metaData.stAlbum))) cm_Music.Artist = retString(unspaceString(wcharTOwstring(metaData.stArtist))) cm_Music.Title = retString(unspaceString(wcharTOwstring(metaData.stTitle))) cm_Music.FileAddress = retString(wcharTOwstring(metaData.stFile)) ' Se tiver usando tag versão nova (v1) If bl_TAGv1 Then ' Seta duração em milisegundos cm_Music.MiliDuration = metaData.lnDuration Else ' Seta duração em segundos cm_Music.Duration = metaData.lnDuration End If ' Seta que atualizou updateTag = True Else ' Não foi possível atualizar updateTag = False End If Exit Function ErrTreat: LogErrMessage Err.Description, ST_MY_NAME + ".updateTag", lnAddress End Function ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Adiciona o WM_USER como mensagem segura ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub addWinSecurity() On Error Resume Next ' Tenta adicionar ChangeWindowMessageFilter WM_USER, MSGFLT_ADD End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Ao iniciar/finalizar a classe ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Class_Initialize() On Error GoTo ErrTreat: #If objcount Then fObjCount.CountInfo ST_MY_NAME, True #End If ' Inicia valores ln_PlayerHwnd = LN_NO_ADDRESS bl_TAGv1 = False ' Adiciona segurança de mensagem addWinSecurity ' Inicia variáveis ps_Status.psCoreSet = False ' Inicia objetos Set cm_Music = New cMusic Set obj_Core = Nothing Exit Sub ErrTreat: LogErrMessage Err.Description, ST_MY_NAME + ".Class_Initialize" End Sub Private Sub Class_Terminate() ' Libera objetos Set cm_Music = Nothing Set obj_Core = Nothing #If objcount Then fObjCount.CountInfo ST_MY_NAME, False #End If End Sub