clase VLC para crear un player - algunos problemas

clase VLC para crear un player - algunos problemas

Postby carlos vargas » Thu Oct 11, 2018 10:27 pm

Estimados amigos, estoy intentando hacerme un player tipo frontend que use el programa vcl de forma interna.
En este caso uso el control activex

el caso es que tengo problemas para reproducir archivo cuyo nombre tenga letras acentuadas o la letra eñe por ejemplo.
me parece que es un problema del control activex, yq ue tengo lo mismo hecho con vfp y va de lujo.
en el metodo SetFile tengo esto
::oControl:playlist:add( "File:///" + cFileName )
que es donde me parece se da el problema.

alguna ayuda.

la verdad me gustaria usar el modo api en c, pero no tengo idea de como iniciar, ya tengo las lib para bcc73 extraida del vlclib.dll
pero nada mas.

Mi idea es hacer un programa para rokonolas digitales, que use vlc como reproductor interno...
aca con fwh
Image

aca con vfp
Image
Code: Select all  Expand view  RUN

#include "fivewin.ch"

/*---------------------------------------------------------------------------------------------*/

#define TRUE    .t.
#define FALSE   .f.

/*---------------------------------------------------------------------------------------------*/

PROCEDURE Main()
   LOCAL oIcon, oVLCX

   PRIVATE oWndMP
   PRIVATE oVlc
   PRIVATE cInfoFN, oInfoFN
   
   cInfoFN := "INFO"
   
   DEFINE ICON oIcon FILE "d:\vlc_foxpro\images\myplayer.ico"
   
   DEFINE WINDOW oWndMP FROM 0, 0 TO 600, 800 TITLE "MyPlayer" ICON oIcon PIXEL //NOMAXIMIZE
     
   @ 010, 010 ACTIVEX oVLCX OF oWndMP PROGID "VideoLAN.VLCPlugin.2" SIZE 600, 460
   
   @ 010, 620 BUTTON "Abrir archivo" OF oWndMP SIZE 80, 24 PIXEL ACTION MP_LoadFile()

   @ 040, 620 BUTTON "Play"          OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Play()
   @ 070, 620 BUTTON "Pause"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Pause()
   @ 100, 620 BUTTON "Stop"          OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Stop()
   
   @ 150, 620 BUTTON "Vol +"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:VolumenPlus()
   @ 180, 620 BUTTON "Vol -"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:VolumenMinus()
   
   @ 480, 010 GET oInfoFN VAR cInfoFN OF oWndMP SIZE 600, 40 PIXEL WHEN FALSE MEMO
   
   //oInfoFN:lDisColors  := FALSE
   //oInfoFN:nClrTextDis := CLR_YELLOW
   //oInfoFN:nClrPaneDis := CLR_HRED
   
   ACTIVATE WINDOW oWndMP ON INIT MP_OnInit( oVLCX ) CENTER

   //oVLC_Control:End()
   oWndMP:End()
   
RETURN

/*---------------------------------------------------------------------------------------------*/

PROCEDURE MP_OnInit( oVLCX )
   oVlc := TVlc():new( oVLCX )
RETURN

/*---------------------------------------------------------------------------------------------*/

PROCEDURE MP_LoadFile()
   LOCAL cFileName := cGetFile( "Video |*.mp4|Musica |*.mp3", "Selecione medio", nil, "", .f., .t. )
   oVlc:SetFile( cFileName )
   oInfoFN:SetText( cFileName )
RETURN

/*---------------------------------------------------------------------------------------------*/

CLASS TVlc
   DATA oControl
   DATA nStepVolume, nVolumen
   
   METHOD New( oControl ) CONSTRUCTOR
   METHOD GetVersion()
   METHOD SetFile()
   METHOD IsPlaying()
   METHOD Play()
   METHOD Pause()
   METHOD Stop()
   METHOD GetLength()
   METHOD GetPosition()
   METHOD GetTimePos()
   METHOD FullScreen()
   METHOD VolumenPlus()
   METHOD VolumenMinus()
ENDCLASS

/*---------------------------------------------------------------------------------------------*/

METHOD New( oControl ) CLASS TVlc
   IF hb_isObject( oControl )
      ::nVolumen := 50
      ::nStepVolume := 2

      ::oControl := oControl
      ::oControl:Toolbar  := .f.
      ::oControl:volume   := 50  
   ENDIF
RETURN Self

/*---------------------------------------------------------------------------------------------*/

METHOD GetVersion() CLASS TVlc
RETURN ::oControl:GetVersionInfo()

/*---------------------------------------------------------------------------------------------*/

METHOD SetFile( cFileName ) CLASS TVlc
   LOCAL lRet := .f.
   IF !empty( cFileName )
      ::oControl:playlist:items:clear()
      ::oControl:playlist:add( "File:///" + cFileName )
      lRet := .t.
   ENDIF
RETURN lRet

/*---------------------------------------------------------------------------------------------*/

METHOD IsPlaying() CLASS TVlc
RETURN ::oControl:playlist:IsPlaying()

/*---------------------------------------------------------------------------------------------*/

METHOD Play() CLASS TVlc
   IF !::IsPlaying()
      ::oControl:playlist:play()
   ENDIF
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD Pause() CLASS TVlc
   IF ::IsPlaying()
      ::oControl:playlist:pause()
   ENDIF
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD Stop() CLASS TVlc
   IF ::IsPlaying()
      ::oControl:playlist:stop()
   ENDIF  
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD GetLength() CLASS TVlc
RETURN ::oControl:input:length()

/*---------------------------------------------------------------------------------------------*/

METHOD GetPosition() CLASS TVlc
RETURN ::oControl:input:position()

/*---------------------------------------------------------------------------------------------*/

METHOD GetTimePos() CLASS TVlc
RETURN ::oControl:input:time()

/*---------------------------------------------------------------------------------------------*/

METHOD FullScreen() CLASS TVlc
   ::oControl:video:toggleFullscreen()  
RETURN NIL  

/*---------------------------------------------------------------------------------------------*/

METHOD VolumenPlus() CLASS TVlc
   IF ::nVolumen < 100
      ::nVolumen := ::nVolumen + ::nStepVolume
      IF ::nVolumen>100
         ::nVolumen := 100  
      ENDIF
      ::oControl:volume := ::nVolumen
   ENDIF  
RETURN NIL
 
/*---------------------------------------------------------------------------------------------*/

METHOD VolumenMinus() CLASS TVlc
   IF ::nVolumen > 0
      ::nVolumen := ::nVolumen - ::nStepVolume
      IF ::nVolumen < 0
         ::nVolumen := 0
      ENDIF
      ::oControl:volume := ::nVolumen
   ENDIF  
RETURN NIL
 
/*---------------------------------------------------------------------------------------------*/


 
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
 
Posts: 1721
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: clase VLC para crear un player - algunos problemas

Postby Antonio Linares » Fri Oct 12, 2018 7:18 am

Carlos,

El mensaje que usa las letras acentuadas ó eñe es enviado a un objeto OLE y no al activex:

::oControl:playlist:add( "File:///" + cFileName )

La función que se usa es hb_oleItemToString() en harbour/contrib/hbwin/olecore.c y esa función debe usar codepages de Harbour

Estas usando el codepage adecuado ?

REQUEST HB_Lang_ESWIN, HB_CODEPAGE_ESWIN

HB_LangSelect( "ESWIN" )
HB_SetCodePage( "ESWIN" )
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: clase VLC para crear un player - algunos problemas

Postby carlos vargas » Fri Oct 12, 2018 5:17 pm

Mil Gracia antonio, era eso que indicabas :-)

Antonio, fijate que me gustaria usar el modo api, en lugar del activex, https://wiki.videolan.org/LibVLC_Visual_C/, ya tengo la dll, el encabezado (archivos .h del api), las lib para bc compiler.
una la extraje directamente con implib, la otra la extraje usando impdef, y la tercera, la igual con impdef pero agregando un gion a los nombres de las funciones.
mas de alguna de las lib funciona, pero el caso es que no tengo idea como iniciar, si me pudieras ayudar, con el inicio yo continuaria el desarrollo, mi intencion es la clase TVlc.
aca esta lo que tengo hasta el momento:http://castillolawyers.zapto.org/owncloud/index.php/s/uyfkrLsNCoBPfEB

aca funcionando con activex con los cambios que me indicaste.
Code: Select all  Expand view  RUN
#include "fivewin.ch"

/*---------------------------------------------------------------------------------------------*/

#define TRUE    .t.
#define FALSE   .f.

/*---------------------------------------------------------------------------------------------*/

REQUEST HB_Lang_ESWIN, HB_CODEPAGE_ESWIN

PROCEDURE Main()
   LOCAL oIcon, oVLCX

   PRIVATE oWndMP
   PRIVATE oVlc
   PRIVATE cInfoFN, oInfoFN

   HB_LangSelect( "ESWIN" )
   HB_SetCodePage( "ESWIN" )

   cInfoFN := "INFO"
   
   DEFINE ICON oIcon FILE "d:\vlc_foxpro\images\myplayer.ico"
   
   DEFINE WINDOW oWndMP FROM 0, 0 TO 600, 800 TITLE "MyPlayer" ICON oIcon PIXEL //NOMAXIMIZE
     
   @ 010, 010 ACTIVEX oVLCX OF oWndMP PROGID "VideoLAN.VLCPlugin.2" SIZE 600, 460
   
   @ 010, 620 BUTTON "Abrir archivo" OF oWndMP SIZE 80, 24 PIXEL ACTION MP_LoadFile()

   @ 040, 620 BUTTON "Play"          OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Play()
   @ 070, 620 BUTTON "Pause"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Pause()
   @ 100, 620 BUTTON "Stop"          OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Stop()
   
   @ 150, 620 BUTTON "Vol +"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:VolumenPlus()
   @ 180, 620 BUTTON "Vol -"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:VolumenMinus()
   
   @ 480, 010 GET oInfoFN VAR cInfoFN OF oWndMP SIZE 600, 40 PIXEL WHEN FALSE MEMO
   
   //oInfoFN:lDisColors  := FALSE
   //oInfoFN:nClrTextDis := CLR_YELLOW
   //oInfoFN:nClrPaneDis := CLR_HRED
   
   ACTIVATE WINDOW oWndMP ON INIT MP_OnInit( oVLCX ) CENTER

   //oVLC_Control:End()
   oWndMP:End()
   
RETURN
 
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
 
Posts: 1721
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: clase VLC para crear un player - algunos problemas

Postby Antonio Linares » Fri Oct 12, 2018 7:15 pm

Carlos,

Podrias empezar así:

Code: Select all  Expand view  RUN
#pragma BEGINDUMP

#include <hbapi.h>
#include <vlc.h>

HB_FUNC( VLC_CREATE )
{
   hb_retnl( VLC_Create() );
}

HB_FUNC( VLC_INIT )
{
   char ** pCommands = ( char ** ) hb_xgrab( sizeof( char * ) * hb_parinfa( 3, 0 ) );
   int i;

   for( i = 0; i < hb_parinfa( 3, 0 ); i++ )
      pCommands[ i ] = hb_parvc( 3, i + 1 );

   hb_retnl( VLC_Init( hb_parnl( 1 ), hb_parnl( 2 ), pCommands ) );
   hb_xfree( ( void * ) pCommands );
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: clase VLC para crear un player - algunos problemas

Postby carlos vargas » Fri Oct 12, 2018 9:57 pm

Antonio...
El caso es que por error te envie el link a un sitio que usa las api obsoletas.
la cual usa un modo de llamar a comandos lo cual no es lo que deseo.

necesitaria:
crear la venta y iniciar el control en hWnd del control que se cree en la ventana,
esa es la parte que no tengo claro.
ya luego la llamada a las funciones me encargo, ya que usalmente no llevan muchos parametros y son sencillas. (aparentemente)

salu2
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
 
Posts: 1721
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: clase VLC para crear un player - algunos problemas

Postby Silvio.Falconi » Sat Oct 13, 2018 6:59 am

Estimado Sr. Vargas, ¿está tu prueba trabajando con Harbour y fwh?
Me parece interesante que podría ayudarla.
También podría ser útil para mí en la escuela mostrar algo a los estudiantes directamente desde mis aplicaciones
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 7068
Joined: Thu Oct 18, 2012 7:17 pm

Re: clase VLC para crear un player - algunos problemas

Postby carlos vargas » Sun Oct 14, 2018 3:17 am

Claro, harbour con fwh.
aca lo mas reciente, hay que tener instalado vlc el cual incluye el control activex.
no hay problema con que lo uses, desde que esta acá en el foro es para uso comun.
mplayer.prg, si bien esta reconociendo los eventos, al inicio use un timer para controlar el avance de la reproducción.
hay que entender que esta es una prueba de uso y uso los eventos que necesitare, la cual fue exitosa al 100%.

Code: Select all  Expand view  RUN

#include "fivewin.ch"

/*---------------------------------------------------------------------------------------------*/

#define TRUE    .t.
#define FALSE   .f.

/*---------------------------------------------------------------------------------------------*/

REQUEST HB_Lang_ESWIN, HB_CODEPAGE_ESWIN

PROCEDURE Main()
   LOCAL oIcon, oVLCX

   PRIVATE oWndMP, oVlc, oTimer
   PRIVATE oInfoFN1, oInfoFN2

   HB_LangSelect( "ESWIN" )
   HB_SetCodePage( "ESWIN" )
   
   DEFINE ICON oIcon FILE "d:\vlc_foxpro\images\myplayer.ico"
   
   DEFINE WINDOW oWndMP FROM 0, 0 TO 600, 800 TITLE "MyPlayer" ICON oIcon PIXEL NOMAXIMIZE
     
   @ 010, 010 ACTIVEX oVLCX OF oWndMP PROGID "VideoLAN.VLCPlugin.2" SIZE 600, 460
   
   @ 010, 620 BUTTON "Abrir archivo" OF oWndMP SIZE 80, 24 PIXEL ACTION MP_LoadFile()

   @ 040, 620 BUTTON "Play"          OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Play()
   @ 070, 620 BUTTON "Pause"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Pause()
   @ 100, 620 BUTTON "Stop"          OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Stop()
   
   @ 150, 620 BUTTON "Vol +"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:VolumenPlus()
   @ 180, 620 BUTTON "Vol -"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:VolumenMinus()

   @ 480, 010 SAY oInfoFN1 PROMPT "" SIZE 600, 40 PIXEL OF oWndMP COLOR CLR_BLUE, CLR_CYAN CENTER VCENTER
   @ 522, 010 SAY oInfoFN2 PROMPT "" SIZE 600, 20 PIXEL OF oWndMP COLOR CLR_BLUE, CLR_CYAN CENTER  VCENTER

   oInfoFN1:SetColor(CLR_BLUE,CLR_CYAN)
   oInfoFN2:SetColor(CLR_BLUE,CLR_CYAN)

   ACTIVATE WINDOW oWndMP ON INIT MP_OnInit( oVLCX ) VALID MP_OnClose() CENTER

   //oVLC_Control:End()
   oWndMP:End()
   
RETURN

/*---------------------------------------------------------------------------------------------*/

PROCEDURE MP_OnInit( oVLCX )
   oTimer := TTimer():new( 1000, {|| OnTimer() }, oWndMP )  
   
   oVlc := TVlc():new( oVLCX )
   oVlc:bOnSetFile := {|| oInfoFN1:SetText( oVlc:cFileName ), oInfoFN2:SetText( "" ) }
   oVlc:bOnPlay    := {|| oTimer:Activate()   }
   oVlc:bOnPause   := {|| oTimer:DeActivate() }
   oVlc:bOnStop    := {|| oTimer:DeActivate() }
   oVlc:bOnEnd     := {|| oTimer:DeActivate() }
   oVlc:SetStepVolume(5)
RETURN

/*---------------------------------------------------------------------------------------------*/

FUNCTION MP_OnClose()
   oTimer:End()
RETURN TRUE

/*---------------------------------------------------------------------------------------------*/

PROCEDURE OnTimer()
   LOCAL cInfo2 := "Length: " + oVlc:GetLengthStr() + ;
                   ", nPos: " + oVlc:GetTimeStr() + ;
                   ", Volume: " + StrZero( oVlc:nVolume, 3 )
   
   oInfoFN2:SetText( cInfo2 )
RETURN

/*---------------------------------------------------------------------------------------------*/

PROCEDURE MP_LoadFile()
   LOCAL cFileName := cGetFile( "Video |*.mp4;*.avi;*.wmv|Musica |*.mp3;*.wma", "Selecione medio", nil, "", FALSE, TRUE )
   oVlc:SetFile( cFileName )
   oInfoFN1:SetText( cFileName )
RETURN

/*---------------------------------------------------------------------------------------------*/

CLASS TVlc
   DATA oControl
   DATA nStepVolume, nVolume
   DATA bOnSetFile
   DATA bOnPlay, bOnPause, bOnStop, bOnEnd
   DATA bOnVolumePlus,  bOnVolumeMinus, bOnVolumeChange
   DATA bOnFullScreen
   DATA cFileName
   DATA lStart
   
   METHOD New( oControl ) CONSTRUCTOR
   METHOD GetVersion()
   METHOD SetFile()
   METHOD IsPlaying()
   METHOD Play()
   METHOD Pause()
   METHOD Stop()
   METHOD GetLength()
   METHOD GetLengthStr()
   METHOD GetTime()
   METHOD GetTimeStr()
   METHOD GetPosition()
   METHOD FullScreen()
   METHOD SetVolume( nVolume )
   METHOD GetVolume()
   METHOD VolumenPlus()
   METHOD VolumenMinus()
   METHOD SetStepVolume( nStep ) INLINE ::nStepVolume := nStep;
   
   METHOD Time2MiliSec( cTime )
   METHOD MiliSec2Time( nMiliSec )
     
   METHOD OnEvent()

ENDCLASS

/*---------------------------------------------------------------------------------------------*/

METHOD New( oControl ) CLASS TVlc
   IF hb_isObject( oControl )
     
      oControl:bOnEvent := { |event, aParams, pParams| ::OnEvent( event, aParams, pParams ) }
     
      ::nVolume := 50
      ::nStepVolume := 1

      ::bOnSetFile      := NIL
      ::bOnPlay         := NIL
      ::bOnPause        := NIL
      ::bOnStop         := NIL
      ::bOnEnd          := NIL
      ::bOnVolumeChange := NIL
      ::bOnVolumePlus   := NIL
      ::bOnVolumeMinus  := NIL
      ::bOnFullScreen   := NIL

      ::oControl := oControl
      ::oControl:Toolbar  := FALSE
      ::oControl:volume   := ::nVolume
     
      ::lStart := FALSE
   ENDIF
RETURN Self

/*---------------------------------------------------------------------------------------------*/

METHOD GetVersion() CLASS TVlc
RETURN ::oControl:GetVersionInfo()

/*---------------------------------------------------------------------------------------------*/

METHOD SetFile( cFileName ) CLASS TVlc
   LOCAL lRet := .f.
   IF !empty( cFileName )
      ::cFileName := cFileName
      ::oControl:playlist:items:clear()
      ::oControl:playlist:add( "File:///" + ::cFileName )
      IF HB_IsBlock( ::bOnSetFile )
         eval( ::bOnSetFile, Self )  
      ENDIF
      lRet := TRUE
   ENDIF
RETURN lRet

/*---------------------------------------------------------------------------------------------*/

METHOD IsPlaying() CLASS TVlc
RETURN ::oControl:playlist:IsPlaying()

/*---------------------------------------------------------------------------------------------*/

METHOD Play() CLASS TVlc
   IF !::IsPlaying()
      ::oControl:playlist:play()
      IF hb_IsBlock( ::bOnPlay )
         eval( ::bOnPlay, Self )
      ENDIF
   ENDIF
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD Pause() CLASS TVlc
   IF ::IsPlaying()
      ::oControl:playlist:pause()
      IF hb_IsBlock( ::bOnPause )
         eval( ::bOnPause, Self )
      ENDIF
   ENDIF
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD Stop() CLASS TVlc
   IF ::IsPlaying()
      ::oControl:playlist:stop()
      IF hb_IsBlock( ::bOnStop )
         eval( ::bOnStop, Self )
      ENDIF
   ENDIF  
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD GetLength() CLASS TVlc
RETURN ::oControl:input:length()

/*---------------------------------------------------------------------------------------------*/

METHOD GetLengthStr() CLASS TVlc
RETURN ::MiliSec2Time( ::oControl:input:length() )

/*---------------------------------------------------------------------------------------------*/

METHOD GetPosition() CLASS TVlc
RETURN ::oControl:input:position()

/*---------------------------------------------------------------------------------------------*/

METHOD GetTime() CLASS TVlc
RETURN ::oControl:input:time()

/*---------------------------------------------------------------------------------------------*/

METHOD GetTimeStr() CLASS TVlc
RETURN ::MiliSec2Time( ::oControl:input:time() )

/*---------------------------------------------------------------------------------------------*/

METHOD FullScreen() CLASS TVlc
   ::oControl:video:toggleFullscreen()
   IF hb_IsBlock( ::bOnFullScreen )
      eval( ::bOnFullScreen, Self )
   ENDIF
RETURN NIL  

/*---------------------------------------------------------------------------------------------*/

METHOD GetVolume() CLASS TVlc
RETURN ::oControl:volume

/*---------------------------------------------------------------------------------------------*/

METHOD SetVolume( nVolume ) CLASS TVlc
   IF nVolume >= 0 .and. nVolume <= 100
      ::nVolume := nVolume
      ::oControl:volume := ::nVolume
      IF hb_IsBlock( ::bOnVolumeChange )
         eval( ::bOnVolumeChange, Self )
      ENDIF
   ENDIF
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD VolumenPlus() CLASS TVlc
   IF ::nVolume < 100
      ::nVolume := ::nVolume + ::nStepVolume
      IF ::nVolume > 100
         ::nVolume := 100  
      ENDIF
      ::oControl:volume := ::nVolume
      IF hb_IsBlock( ::bOnVolumePlus )
         eval( ::bOnVolumePlus, Self )
      ENDIF
   ENDIF  
RETURN NIL
 
/*---------------------------------------------------------------------------------------------*/

METHOD VolumenMinus() CLASS TVlc
   IF ::nVolume > 0
      ::nVolume := ::nVolume - ::nStepVolume
      IF ::nVolume < 0
         ::nVolume := 0
      ENDIF
      ::oControl:volume := ::nVolume
      IF hb_IsBlock( ::bOnVolumeMinus )
         eval( ::bOnVolumeMinus, Self )
      ENDIF
   ENDIF  
RETURN NIL
 
/*---------------------------------------------------------------------------------------------*/

METHOD Time2MiliSec( cTime ) CLASS TVlc
   LOCAL nMiliSec := 0
   LOCAL nH, nM, nS, nT
   IF !empty( cTime )
      nH = VAL( SUBSTR( cTime, 1, 2 ) )
      nM = VAL( SUBSTR( cTime, 4, 2 ) )
      nS = VAL( SUBSTR( cTime, 7, 2 ) )
      nT = ( nH * 3600 ) + ( nM * 60 ) + nS
      nMiliSec := nT * 1000
   ENDIF
RETURN nMiliSec

/*---------------------------------------------------------------------------------------------*/

METHOD MiliSec2Time( nMiliSec ) CLASS TVlc
   LOCAL cTime := "00:00:00"
   LOCAL nHora, nMinuto, nSegundo
   IF nMiliSec > 0
      nMiliSec := int( nMiliSec / 1000 )
      nHora    := int( nMiliSec / 3600 )
      nMiliSec := nMiliSec - ( nHora * 3600 )
      nMinuto  := int( nMiliSec / 60 )
      nSegundo := nMiliSec - ( nMinuto * 60 )
      cTime := StrZero( nHora, 2 ) + ":" + StrZero( nMinuto, 2 ) + ":" + StrZero( nSegundo, 2 )
   ENDIF
RETURN cTime

/*---------------------------------------------------------------------------------------------*/

METHOD OnEvent( event, aParams, pParams ) CLASS TVlc
   DO CASE
      CASE event == "MediaPlayerNothingSpecial"        &&mediaplayer en espera
      CASE event == "MediaPlayerMediaChanged"
      CASE event == "MediaPlayerOpening"               &&al iniciar reproduccion
      CASE event == "MediaPlayerPlaying"               &&mediplayer esta en reproduccion
      CASE event == "MediaPlayerPaused"                &&pausar reproduccion        
      CASE event == "MediaPlayerPausableChanged"
      CASE event == "MediaPlayerStopped"               &&detener reproduccion
      CASE event == "MediaPlayerEndReached"            &&finalizar reproduccion
         IF hb_IsBlock( ::bOnEnd )
            eval( ::bOnEnd, Self )
         ENDIF            
      CASE event == "MediaPlayerMuted"                 &&enmudecer reproduccion
      CASE event == "MediaPlayerUnmuted"               &&quitar enmudecer reproduccion
      CASE event == "MediaPlayerAudioVolume"           &&cambia volumen de reproduccion
      CASE event == "MediaPlayerTimeChanged"
      CASE event == "MediaPlayerSeekableChanged"
      CASE event == "MediaPlayerPositionChanged"
      CASE event == "MediaPlayerEncounteredError"
      CASE event == "MediaPlayerBackward"
      CASE event == "MediaPlayerForward"
      CASE event == "MediaPlayerBuffering"
      CASE event == "MediaPlayerChapterChanged"
      CASE event == "MediaPlayerLengthChanged"
      CASE event == "MediaPlayerStopAsyncDone"
      CASE event == "MediaPlayerTitleChanged"
      CASE event == "MediaPlayerVOut"
   ENDCASE
RETURN NIL

/*---------------------------------------------------------------------------------------------*/
//EOF
/*---------------------------------------------------------------------------------------------*/
 
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
 
Posts: 1721
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: clase VLC para crear un player - algunos problemas

Postby Silvio.Falconi » Mon Oct 15, 2018 9:55 am

sorry where I can found the activex or I must install Vcl application ?
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 7068
Joined: Thu Oct 18, 2012 7:17 pm

Re: clase VLC para crear un player - algunos problemas

Postby carlos vargas » Mon Oct 15, 2018 4:40 pm

yes. install vcl, this include the activex.
version most recent.
Code: Select all  Expand view  RUN
#include "fivewin.ch"

/*---------------------------------------------------------------------------------------------*/

#define TRUE    .t.
#define FALSE   .f.

/*---------------------------------------------------------------------------------------------*/

REQUEST HB_Lang_ESWIN, HB_CODEPAGE_ESWIN

PROCEDURE Main()
   LOCAL oIcon, oVLCX

   PRIVATE oWndMP, oVlc, oTimer
   PRIVATE oInfoFN1, oInfoFN2

   HB_LangSelect( "ESWIN" )
   HB_SetCodePage( "ESWIN" )
   
   DEFINE ICON oIcon FILE "d:\vlc_foxpro\images\myplayer.ico"
   
   DEFINE WINDOW oWndMP FROM 0, 0 TO 600, 800 TITLE "MyPlayer" ICON oIcon PIXEL NOMAXIMIZE
     
   @ 010, 010 ACTIVEX oVLCX OF oWndMP PROGID "VideoLAN.VLCPlugin.2" SIZE 600, 460
   
   @ 010, 620 BUTTON "Abrir archivo" OF oWndMP SIZE 80, 24 PIXEL ACTION MP_LoadFile()

   @ 040, 620 BUTTON "Play"          OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Play()
   @ 070, 620 BUTTON "Pause"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Pause()
   @ 100, 620 BUTTON "Stop"          OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:Stop()
   
   @ 150, 620 BUTTON "Vol +"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:VolumenPlus()
   @ 180, 620 BUTTON "Vol -"         OF oWndMP SIZE 80, 24 PIXEL ACTION oVlc:VolumenMinus()

   @ 480, 010 SAY oInfoFN1 PROMPT "" SIZE 600, 40 PIXEL OF oWndMP COLOR CLR_BLUE, CLR_CYAN CENTER VCENTER
   @ 522, 010 SAY oInfoFN2 PROMPT "" SIZE 600, 20 PIXEL OF oWndMP COLOR CLR_BLUE, CLR_CYAN CENTER VCENTER

   oInfoFN1:SetColor( CLR_BLUE, CLR_CYAN )
   oInfoFN2:SetColor( CLR_BLUE, CLR_CYAN )

   ACTIVATE WINDOW oWndMP ON INIT MP_OnInit( oVLCX ) VALID MP_OnClose() CENTER

   //oVLC_Control:End()
   oWndMP:End()
   
RETURN

/*---------------------------------------------------------------------------------------------*/

PROCEDURE MP_OnInit( oVLCX )  
   oVlc := TVlc():new( oVLCX )
   oVlc:bOnSetFile := {|| oInfoFN1:SetText( oVlc:cFileName ), oInfoFN2:SetText( "" ) }
   oVlc:bOnTimeChanged := {|| oInfoFN2:SetText( "Length: "   + oVlc:GetLengthStr() + ", nPos: "   + oVlc:GetTimeStr() + ", Volume: " + StrZero( oVlc:nVolume, 3 ) ) }
   oVlc:SetStepVolume(5)
RETURN

/*---------------------------------------------------------------------------------------------*/

FUNCTION MP_OnClose()
RETURN TRUE

/*---------------------------------------------------------------------------------------------*/

PROCEDURE MP_LoadFile()
   LOCAL cFileName := cGetFile( "Video |*.mp4;*.avi;*.wmv|Musica |*.mp3;*.wma", "Selecione medio", nil, "", FALSE, TRUE )
   oVlc:SetFile( cFileName )
RETURN

/*---------------------------------------------------------------------------------------------*/

CLASS TVlc
   DATA oControl
   DATA nStepVolume, nVolume
   DATA bOnSetFile
   DATA bOnPlay, bOnPause, bOnStop, bOnEnd
   DATA bOnVolumePlus, bOnVolumeMinus, bOnVolumeChange
   DATA bOnMuted, bOnUnMuted
   DATA bOnTimeChanged
   DATA bOnFullScreen
   DATA cFileName

   METHOD New( oControl ) CONSTRUCTOR
   METHOD GetVersion()
   METHOD SetFile()
   METHOD IsPlaying()
   METHOD Play()
   METHOD Pause()
   METHOD Stop()
   METHOD GetLength()
   METHOD GetLengthStr()
   METHOD GetTime()
   METHOD GetTimeStr()
   METHOD Position( nPos )
   METHOD FullScreen()
   METHOD SetVolume( nVolume )
   METHOD GetVolume()
   METHOD VolumenPlus()
   METHOD VolumenMinus()
   METHOD SetStepVolume( nStep ) INLINE ::nStepVolume := nStep;
   
   METHOD Time2MiliSec( cTime )
   METHOD MiliSec2Time( nMiliSec )
     
   METHOD OnEvent(event, aParams, pParams)

ENDCLASS

/*---------------------------------------------------------------------------------------------*/

METHOD New( oControl ) CLASS TVlc
   IF hb_isObject( oControl )
     
      oControl:bOnEvent := { |event, aParams, pParams| ::OnEvent( event, aParams, pParams ) }
     
      ::nVolume := 50
      ::nStepVolume := 1

      ::bOnSetFile      := NIL
      ::bOnPlay         := NIL
      ::bOnPause        := NIL
      ::bOnStop         := NIL
      ::bOnEnd          := NIL
      ::bOnVolumePlus   := NIL
      ::bOnVolumeMinus  := NIL
      ::bOnFullScreen   := NIL
      ::bOnMuted        := NIL
      ::bOnUnMuted      := NIL
      ::bOnVolumeChange := NIL
      ::bOnTimeChanged  := NIL

      ::oControl := oControl
      ::oControl:Toolbar  := FALSE
      ::oControl:volume   := ::nVolume
   ENDIF
RETURN Self

/*---------------------------------------------------------------------------------------------*/

METHOD GetVersion() CLASS TVlc
RETURN ::oControl:GetVersionInfo()

/*---------------------------------------------------------------------------------------------*/

METHOD SetFile( cFileName ) CLASS TVlc
   LOCAL lRet := FALSE
   IF !empty( cFileName )
      ::cFileName := cFileName
      ::oControl:playlist:items:clear()
      ::oControl:playlist:add( "File:///" + ::cFileName )
      IF HB_IsBlock( ::bOnSetFile )
         eval( ::bOnSetFile, Self )  
      ENDIF
      lRet := TRUE
   ENDIF
RETURN lRet

/*---------------------------------------------------------------------------------------------*/

METHOD IsPlaying() CLASS TVlc
RETURN ::oControl:playlist:IsPlaying()

/*---------------------------------------------------------------------------------------------*/

METHOD Play() CLASS TVlc
   IF !::IsPlaying()
      ::oControl:playlist:playitem(0)
   ENDIF
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD Pause() CLASS TVlc
   IF ::IsPlaying()
      ::oControl:playlist:pause()
   ENDIF
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD Stop() CLASS TVlc
   IF ::IsPlaying()
      ::oControl:playlist:stop()
   ENDIF  
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD GetLength() CLASS TVlc
RETURN ::oControl:input:length()

/*---------------------------------------------------------------------------------------------*/

METHOD GetLengthStr() CLASS TVlc
RETURN ::MiliSec2Time( ::oControl:input:length() )

/*---------------------------------------------------------------------------------------------*/

METHOD Position( nPos ) CLASS TVlc
   IF hb_isNil( nPos )
      RETURN ::oControl:input:Position  
   ELSE
      IF nPos >= 0 .and. nPos <= 1
         ::oControl:input:Position := nPos
      ENDIF
   ENDIF
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD GetTime() CLASS TVlc
RETURN ::oControl:input:time()

/*---------------------------------------------------------------------------------------------*/

METHOD GetTimeStr() CLASS TVlc
RETURN ::MiliSec2Time( ::oControl:input:time() )

/*---------------------------------------------------------------------------------------------*/

METHOD FullScreen() CLASS TVlc
   ::oControl:video:toggleFullscreen()
   IF hb_IsBlock( ::bOnFullScreen )
      eval( ::bOnFullScreen, Self )
   ENDIF
RETURN NIL  

/*---------------------------------------------------------------------------------------------*/

METHOD GetVolume() CLASS TVlc
RETURN ::oControl:volume

/*---------------------------------------------------------------------------------------------*/

METHOD SetVolume( nVolume ) CLASS TVlc
   IF nVolume >= 0 .and. nVolume <= 100
      ::nVolume := nVolume
      ::oControl:volume := ::nVolume
   ENDIF
RETURN NIL

/*---------------------------------------------------------------------------------------------*/

METHOD VolumenPlus() CLASS TVlc
   IF ::nVolume < 100
      ::nVolume := ::nVolume + ::nStepVolume
      IF ::nVolume > 100
         ::nVolume := 100  
      ENDIF
      ::oControl:volume := ::nVolume
      IF hb_IsBlock( ::bOnVolumePlus )
         eval( ::bOnVolumePlus, Self )
      ENDIF
   ENDIF  
RETURN NIL
 
/*---------------------------------------------------------------------------------------------*/

METHOD VolumenMinus() CLASS TVlc
   IF ::nVolume > 0
      ::nVolume := ::nVolume - ::nStepVolume
      IF ::nVolume < 0
         ::nVolume := 0
      ENDIF
      ::oControl:volume := ::nVolume
      IF hb_IsBlock( ::bOnVolumeMinus )
         eval( ::bOnVolumeMinus, Self )
      ENDIF
   ENDIF  
RETURN NIL
 
/*---------------------------------------------------------------------------------------------*/

METHOD Time2MiliSec( cTime ) CLASS TVlc
   LOCAL nMiliSec := 0
   LOCAL nH, nM, nS, nT
   IF !empty( cTime )
      nH = VAL( SUBSTR( cTime, 1, 2 ) )
      nM = VAL( SUBSTR( cTime, 4, 2 ) )
      nS = VAL( SUBSTR( cTime, 7, 2 ) )
      nT = ( nH * 3600 ) + ( nM * 60 ) + nS
      nMiliSec := nT * 1000
   ENDIF
RETURN nMiliSec

/*---------------------------------------------------------------------------------------------*/

METHOD MiliSec2Time( nMiliSec ) CLASS TVlc
   LOCAL cTime := "00:00:00"
   LOCAL nHora, nMinuto, nSegundo
   IF nMiliSec > 0
      nMiliSec := int( nMiliSec / 1000 )
      nHora    := int( nMiliSec / 3600 )
      nMiliSec := nMiliSec - ( nHora * 3600 )
      nMinuto  := int( nMiliSec / 60 )
      nSegundo := nMiliSec - ( nMinuto * 60 )
      cTime := StrZero( nHora, 2 ) + ":" + StrZero( nMinuto, 2 ) + ":" + StrZero( nSegundo, 2 )
   ENDIF
RETURN cTime

/*---------------------------------------------------------------------------------------------*/

METHOD OnEvent( event, aParams, pParams ) CLASS TVlc
   DO CASE
      CASE event == "MediaPlayerNothingSpecial"        &&mediaplayer en espera
      CASE event == "MediaPlayerMediaChanged"
      CASE event == "MediaPlayerOpening"               &&al iniciar reproduccion
      CASE event == "MediaPlayerPlaying"               &&mediplayer esta en reproduccion
         IF hb_IsBlock( ::bOnPlay )
            eval( ::bOnPlay, Self )
         ENDIF
      CASE event == "MediaPlayerPaused"                &&pausar reproduccion
         IF hb_IsBlock( ::bOnPause )
            eval( ::bOnPause, Self )
         ENDIF
      CASE event == "MediaPlayerStopped"               &&detener reproduccion
         IF hb_IsBlock( ::bOnStop )
            eval( ::bOnStop, Self )
         ENDIF
      CASE event == "MediaPlayerEndReached"            &&finalizar reproduccion
         IF hb_IsBlock( ::bOnEnd )
            eval( ::bOnEnd, Self )
         ENDIF            
      CASE event == "MediaPlayerMuted"                 &&enmudecer reproduccion
         IF hb_IsBlock( ::bOnMuted )
            eval( ::bOnMuted, Self )
         ENDIF                  
      CASE event == "MediaPlayerUnmuted"               &&quitar enmudecer reproduccion
         IF hb_IsBlock( ::bOnUnMuted )
            eval( ::bOnUnMuted, Self )
         ENDIF
      CASE event == "MediaPlayerAudioVolume"           &&cambia volumen de reproduccion
         IF hb_IsBlock( ::bOnVolumeChange )
            eval( ::bOnVolumeChange, Self )
         ENDIF
      CASE event == "MediaPlayerTimeChanged"
         IF hb_IsBlock( ::bOnTimeChanged )
            eval( ::bOnTimeChanged, Self )
         ENDIF
      CASE event == "MediaPlayerPausableChanged"
      CASE event == "MediaPlayerSeekableChanged"
      CASE event == "MediaPlayerPositionChanged"
      CASE event == "MediaPlayerEncounteredError"
      CASE event == "MediaPlayerBackward"
      CASE event == "MediaPlayerForward"
      CASE event == "MediaPlayerBuffering"
      CASE event == "MediaPlayerChapterChanged"
      CASE event == "MediaPlayerLengthChanged"
      CASE event == "MediaPlayerStopAsyncDone"
      CASE event == "MediaPlayerTitleChanged"
      CASE event == "MediaPlayerVOut"
   ENDCASE
RETURN NIL

/*---------------------------------------------------------------------------------------------*/
//EOF
/*---------------------------------------------------------------------------------------------*/
 
Last edited by carlos vargas on Mon Oct 15, 2018 8:24 pm, edited 1 time in total.
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
 
Posts: 1721
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: clase VLC para crear un player - algunos problemas

Postby Silvio.Falconi » Mon Oct 15, 2018 5:08 pm

Sorry
I download and install the rel Version 3.0.4 • Windows 64bit

I must compile with specific libs ?

I compiled with Harbour and fwh

here crash

Firma problema:
Nome evento problema: APPCRASH
Nome applicazione: test.Exe
Versione applicazione: 0.0.0.0
Timestamp applicazione: 00000000
Nome modulo con errori: test.Exe
Versione modulo con errori: 0.0.0.0
Timestamp modulo con errori: 00000000
Codice eccezione: c0000005
Offset eccezione: 0003961d
Versione SO: 6.1.7600.2.0.0.768.3
ID impostazioni locali: 1040
Informazioni aggiuntive 1: 0a9e
Ulteriori informazioni 2: 0a9e372d3b4ad19135b953a78882e789
Ulteriori informazioni 3: 0a9e
Ulteriori informazioni 4: 0a9e372d3b4ad19135b953a78882e789

Leggere l'informativa sulla privacy online:
http://go.microsoft.com/fwlink/?linkid= ... cid=0x0410

Se l'informativa sulla privacy online non è disponibile, leggere quella offline:
C:\Windows\system32\it-IT\erofflps.txt
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 7068
Joined: Thu Oct 18, 2012 7:17 pm

Re: clase VLC para crear un player - algunos problemas

Postby carlos vargas » Mon Oct 15, 2018 6:55 pm

i use vlc 3.0.4 32 bits.
y build the exe with 92\fwh\samples\buildh myplayer
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
 
Posts: 1721
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: clase VLC para crear un player - algunos problemas

Postby Silvio.Falconi » Mon Oct 15, 2018 7:43 pm

Carlos now try to download version 32 bit
But I think it's strange
I compile with Harbour and fwh oldest ( see the bottom of my messages)
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 7068
Joined: Thu Oct 18, 2012 7:17 pm

Re: clase VLC para crear un player - algunos problemas

Postby Silvio.Falconi » Mon Oct 15, 2018 7:54 pm

Carlos,
With 32 bit version run ok ( on win7 64 bit) as you can see here ( tried Mp4 and Mp3)

Image

cambios probables
ponga el nombre del archivo y el progreso del archivo en la barra de mensajes (parte inferior) de la ventana
Expanda el control hasta OWnd: oclient y vea cómo hacer el zoom máximo
poner los botones en la barra de botones

Pero tal vez ya lo hayas pensado, ¿verdad?
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 7068
Joined: Thu Oct 18, 2012 7:17 pm

Re: clase VLC para crear un player - algunos problemas

Postby carlos vargas » Tue Oct 16, 2018 3:50 pm

NO Silvio, esto es una prueba de funcionalidad, ya que mi intencion es crean un programa de rokonola digital, similar a productos como rokobox, psrokola o mfrokola,
los cuales tiene funcionalidades limitadas en cuanto al reproductor, por tanto muchas cualidades propias de un media player no seran requeridas, solo las mas utilizadas,
tales como agregar archivo, reproducir, finalizar, tiempo del archivo en reproducion, avance en tiempo de reproduccion.-
ya luego viene la parte visual, y administrativa, configuración, etc.

por eso me gustaria usar el api en lugar de activex (lo cual limita a windows como SO), ya que con productos tales como fivelinux podria usar linux como sistema operativo, lo cual es mi mayor interes.
un programa de rokonola digital para linux y windows.

salu2
carlos vargas
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
 
Posts: 1721
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: clase VLC para crear un player - algunos problemas

Postby Silvio.Falconi » Tue Oct 16, 2018 7:13 pm

En la lista de preguntas y respuestas (FAQ) de VCL, leí que habría posibilidades de adquirir y transmitir videos.
Ya probaste esta posibilidad o no te importa, por ejemplo, podría ser interesante transmitir videos caseros mientras estás en todo el mundo.

https://www.videolan.org/developers/bitstream.html
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 7068
Joined: Thu Oct 18, 2012 7:17 pm

Next

Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 47 guests