Quiz

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
Noos88260
Messages : 8
Inscription : dim. 04/janv./2026 9:02
Localisation : FRANCE

Quiz

Message par Noos88260 »

Bonjour et encore merci a vous tous pour tous ces exemples de code qui est fourni dans ce forum.
Je vous mais en lien un jeux de Quiz qui fonctionne avec les téléphones (ou tous autre chose qui a une connexion) car si il y a une bonne personne qui voudrais regardé après mon code car j'ai des bugs que je n'arrive pas a me débarrassé.
1er Bug : Le score mais je pense que ca vient de la List ParaJoueur qui est utilisé dans 2 thears différents
2em Bug : Si il y plus de 4 téléphones connecté c'est horrible a jouer
3em Bug : Musique qui vient sans qu'on lui demande.

Lien : https://drive.google.com/file/d/14uR_MP ... sp=sharing

Merci pour celui qui va s'arracher les cheveux :D
Bonn journée

J'ai oublié, aller faire un tour à l'executable Config pour prendre en compte votre adresse ip
Dernière modification par Noos88260 le dim. 25/janv./2026 11:53, modifié 2 fois.
Avatar de l’utilisateur
venom
Messages : 3183
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: Quiz

Message par venom »

Bien-sûr, je vais cliquer sur ton lien avec plaisir et sans crainte :lol:






@++
Windows 10 x64, PureBasic 6.30 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
Noos88260
Messages : 8
Inscription : dim. 04/janv./2026 9:02
Localisation : FRANCE

Re: Quiz

Message par Noos88260 »

Oui bien-sur, c'est un lien Drive de Google dont j'ai tous mis à l'intérieur environ 800Mo. (Il y a aussi tous les Logiciels que j'ai créer pour réaliser la base de donnée, si ça peux servir)
Avatar de l’utilisateur
Noos88260
Messages : 8
Inscription : dim. 04/janv./2026 9:02
Localisation : FRANCE

Re: Quiz

Message par Noos88260 »

Bonjour à tous! J'ai modifier le programme concernant la gestion des joueurs (tableau "paraJoueur") avec les essaie que j'ai fait ca fonctionne bien mieux, aussi la vidéo de présentation avec les pc portable dont le DPI différent des PC fixe et aussi une erreur sur la gestion des scores dont j'espère qu'il n'y auras plus de souci.

Partagé moi votre expérience de ce jeux s'il vous plait.
(J'ai put constaté que LoadMovie() ne fonctionnais pas sur les PC dont la carte graphique n'était pas correctement installé)

J'ai remis le lien à jour a mon premier message.
Bon Week-end
Avatar de l’utilisateur
Noos88260
Messages : 8
Inscription : dim. 04/janv./2026 9:02
Localisation : FRANCE

Re: Quiz

Message par Noos88260 »

Bonjour a tous, je pense ne plus avoir de soucis dans mon jeux.
Je vous met les modifications pour ceux que ça intéresserais car il n'y a pas eu beaucoup d'échange à ce sujet mais en cas ou ça pourras intéressé une ou deux personne :D

Jeux complet : https://drive.google.com/file/d/14uR_MP ... sp=sharing

Jeux.pbi

Code : Tout sélectionner

; =================================================================
; Jeu de Quiz 
; By Noos88 et plein de morceau de code trouver sur PureBasic/forum
; =================================================================

UseSQLiteDatabase()
UseJPEGImageDecoder()
UsePNGImageDecoder()

IncludeFile "Include\Global.pbi"
IncludeFile "Include\Enumeration.pbi"
IncludeFile "Include\QR.pbi"
IncludeFile "Include\Structure.pbi"
IncludeFile "Fmod\fmodex-min.pbi"
IncludeFile "Include\sapi-all.pbi"
IncludeFile "Include\Procedure.pbi"

WWWDirectory.s = Source+"www\"
Burreau.i = 0

ExamineDesktops()
InitMovie()

If OpenPreferences(Source+"Data\Preference.txt")
  PreferenceGroup("Jeux")
  Hauteur_Voix.s = ReadPreferenceString("Hauteur_Voix", "0")
  NbrPartie.i = ReadPreferenceInteger("Nbr_parties", 1)
  NivQuestion.i = ReadPreferenceInteger("NivQuestion", 3)
  MTous_type.i = ReadPreferenceInteger("MTous_type", 1)
  VTous_type.i = ReadPreferenceInteger("VTous_type", 1)
  NbrPointX2.i = ReadPreferenceInteger("NbrPointX2",2)
  NbrBlock.i = ReadPreferenceInteger("NbrBlock",2)
  NbrVoleur.i = ReadPreferenceInteger("NbrVoleur",2)
  
  ;Declare FMOD System
  FMOD_System_Create(@fmodsystem)
  
  ;Init FMOD System
  FMOD_System_Init(FmodSystem, 32, #FMOD_INIT_NORMAL, 0)
  
  Jeux = #Enregistrement
  
  AdresseIPJeux.s = "http://"+ReadPreferenceString("AdresseIP","192.168.1.1")+":"+Str(ReadPreferenceInteger("Port", 6835))
  
  img = qrcodegen::CreateTextImage(AdresseIPJeux)
  If img
    If ImageWidth(img) < 400
      magnifiedSize = ImageWidth(img) * (400 / ImageWidth(img))
      ResizeImage(img, magnifiedSize, magnifiedSize, #PB_Image_Raw)
    EndIf
  EndIf 
  
  LoadImage(#Titre,"Data\Quiz03.png")
  LoadImage(#Score,"Data\Score.png")
  LoadImage(#MediaMusique,Source + "Data\Musique.png")
  LoadImage(#MediaVideo,Source + "Data\Film.png")
  
  Height = DesktopHeight(Burreau)
  Width  = DesktopWidth(Burreau)
  
  LoadFont(#Police, "Impact", 20, #PB_Font_Bold)
  ShowWindow_(FindWindow_("Shell_TrayWnd",""),#SW_HIDE); Desactive barre des taches
  If OpenWindow(#Window,0,0,Width,Height,Title,#PB_Window_BorderLess);|#PB_Window_Maximize) 
    sapi_Init(WindowID(#Window))
    sapi_SetVoice(ReadPreferenceString("Voix", ""))
    
    Hauteur = WindowHeight(#Window)
    Largeur = WindowWidth(#Window)
    
    CreateImage(#Image,Largeur,Hauteur)
    CreateImage(#ImageFont,Int(Largeur *0.4), Int(Hauteur *0.3),24,RGB(255,255,255))
    ImageGadget(#Font, 0, 0, Largeur, Largeur,ImageID(#Image))
    
    AddKeyboardShortcut(#Window, #PB_Shortcut_Return, #Entree)
    AddKeyboardShortcut(#Window, #PB_Shortcut_Space, #Espace)
    AddKeyboardShortcut(#Window, #PB_Shortcut_Escape, #Echap)
    
    PageAccueilPostif(img)
    sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix +Chr(34)+ ">Bonjour et bienvenu sur le jeux de quiz, veuillez vous connecté à l'aide du QR code!</pitch>")
    ;- Données
    
    
    If OpenDatabase(#BaseDeDonnees, GetCurrentDirectory()+"Quiz.db", "", "")
      
      ReDim NumQuestion(NbrPartie)
      If NivQuestion = 1
        CommandeQuestion.s = "SELECT * FROM Question WHERE Difficulte = 'Débutant' ORDER BY random() LIMIT "+Str(NbrPartie)+"; " ;Niveau Débutant
      ElseIf NivQuestion = 2
        CommandeQuestion.s = "SELECT * FROM Question WHERE Difficulte <> 'Expert' ORDER BY random() LIMIT "+Str(NbrPartie)+"; " ;Niveau Débutant et Confirmé
      ElseIf NivQuestion = 3
        CommandeQuestion.s = "SELECT * FROM Question WHERE Difficulte <> 'Débutant' ORDER BY random() LIMIT "+Str(NbrPartie)+"; " ;Niveau Confirmé et Expert
      Else
        CommandeQuestion.s = "SELECT * FROM Question ORDER BY random() LIMIT "+Str(NbrPartie)+"; " ;Tous niveaux
      EndIf 
      If ExexuteDataQuery(#BaseDeDonnees, CommandeQuestion)
        Num.i = 0
        While NextDatabaseRow(#BaseDeDonnees)
          NumQuestion(Num) = Val(RSet(GetDatabaseString(#BaseDeDonnees,0),4))
          Num +1
        Wend
        FinishDatabaseQuery(#BaseDeDonnees)
      EndIf 
      
      ReDim NumMusique(NbrPartie)
      If MTous_type = #True
        CommandeMusique.s = "SELECT * FROM Musique ORDER BY random() LIMIT "+Str(NbrPartie)+"; "
      Else 
        CommandeMusique.s = "SELECT * FROM Musique WHERE Genre = 'Variété' ORDER BY Random() LIMIT "+Str(NbrPartie)+"; "
      EndIf   
      If ExexuteDataQuery(#BaseDeDonnees, CommandeMusique)
        Num.i = 0
        While NextDatabaseRow(#BaseDeDonnees)
          NumMusique(Num) = Val(RSet(GetDatabaseString(#BaseDeDonnees,0),4))
          Num +1
        Wend
        FinishDatabaseQuery(#BaseDeDonnees)
      EndIf  
      
      ReDim NumVideo(NbrPartie)
      If VTous_type = #True
        CommandeFilm.s = "SELECT * FROM Video ORDER BY random() LIMIT "+Str(NbrPartie)+";"
      Else
        CommandeFilm.s = "SELECT * FROM Video WHERE Genre = 'Dessin animé' ORDER BY Random() LIMIT "+Str(NbrPartie)+";"
      EndIf
      If ExexuteDataQuery(#BaseDeDonnees, CommandeFilm)
        Num.i = 0
        While NextDatabaseRow(#BaseDeDonnees)
          NumVideo(Num) = Val(RSet(GetDatabaseString(#BaseDeDonnees,0),4))
          Num +1
        Wend
        FinishDatabaseQuery(#BaseDeDonnees)
      EndIf  
      
      
      Index.s = LectureFile(WWWDirectory + "Index.html")
      Go.s = LectureFile(WWWDirectory + "Go.html")
      Go2.s = LectureFile(WWWDirectory + "Go2.html")
      DelayUp.s = LectureFile(WWWDirectory + "TropTard.html")
      Script5secondes.s = LectureFile(WWWDirectory+ "Script5secondes.js")
      Bonne_reponse.s = LectureFile( WWWDirectory + "Bonne_reponse.html")
      Mauvaise_reponse.s = LectureFile( WWWDirectory + "Mauvaise_reponse.html")
      Nouveau_Joueur.s = LectureFile( WWWDirectory + "Nouveau_Joueur.html")
      Patiente.s = LectureFile( WWWDirectory + "Patiente.html")
      Patiente2.s = LectureFile( WWWDirectory + "Patiente2.html")
      ListeJoueurs.s = LectureFile( WWWDirectory + "Liste.html")
      Pieges.s = LectureFile( WWWDirectory + "Pieges.html")
      Fin.s = LectureFile( WWWDirectory + "Fin.html")
      
      If CreateNetworkServer(#Serveur, ReadPreferenceInteger("Port", 6835))
        
        ; Création du stream de lecture 
        FMOD_System_CreateStream(FmodSystem, Ascii(Source+ "Data\Into.mp3"), #FMOD_SOFTWARE, 0, @sound)    
        ;Play a sound on a free channel
        FMOD_System_PlaySound(fmodsystem, #FMOD_CHANNEL_FREE, sound, 0, @channel)
        ;Volume
        FMOD_Channel_SetVolume(Channel, 0.1)
        
        CreateThread(@GestionNetwork(),0)
        
        Repeat
          Event = WaitWindowEvent(10)
          Select Event
            Case #PB_Event_Menu
              Select EventMenu()
                Case #Entree 
                  If nbrJoueur <> -1 And Jeux = #Enregistrement
                    Jeux = #Explication
                    nbrBonReponse.i = Round(nbrJoueur/2,#PB_Round_Up)
                    If ReadPreferenceInteger("Presentation", #True)
                      If LoadMovie(#Video, Source+"Data\Explication.mp4")
                        ResizeWindow(#Window, #PB_Ignore, #PB_Ignore, Width/DesktopResolutionX(), Height/DesktopResolutionY())
                        
                        PlayMovie(#Video, WindowID(#Window))
                        TextExplication.s = "Explications du jeux Quiz:"+
                                            "Sur "+Str(NbrPartie)+" parties, vous allez avoir une série de question, musique et video à repondre avec 4 choix possible, il vous est suffi d'appuyer sur Go"+
                                            "de votre téléphone pour y répondre dans un délais de 5 secondes <silence msec="+Chr(34)+"500"+Chr(34)+"/>"+
                                            "Dépéchez vous de répondre car seul la moitier des joueurs qui auront la bonne réponse auront le double de point <silence msec="+Chr(34)+"300"+Chr(34)+"/>"+
                                            "Les 3 questions fini, vous aurez le droit de sélectionner une stratégie de jeux,"+
                                            "volé ou bloqué votre adversaire et même de multiplier votre score de partie fois 2."  
                        sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">" + TextExplication +"</pitch>")
                        Explication = #True
                      EndIf 
                    Else
                      ;                       FMOD_Channel_GetPosition(Channel,@CurrentPos,1)
                      ;                       FMOD_Channel_Stop(Channel)
                      CreateThread(@PageJeuxQuestion(),0)
                    EndIf
                  EndIf
                  
                Case #Espace
                  
                Case #Echap
                  CloseNetworkServer(#Serveur)
                  CloseDatabase(#BaseDeDonnees)
                  sapi_DeInit()
                  ShowWindow_(FindWindow_("Shell_TrayWnd",""),#SW_SHOW); Active barre des taches
                  End
              EndSelect
              
          EndSelect
          
          ;  Movie
          If Explication = #True
            If MovieStatus(#Video) = MovieLength(#Video) ;Détection de la Fin de la video
              FreeMovie(#Video) 
              ResizeWindow(#Window, #PB_Ignore, #PB_Ignore, Width, Height)
              Explication = #False
              FMOD_Channel_Stop(Channel)
              CreateThread(@PageJeuxQuestion(),0)
            EndIf 
          EndIf
          
        ForEver 
        
      EndIf
    Else
      MessageRequester("Erreur","Pas de base de donnée disponible")
    EndIf 
  EndIf 
EndIf 
Avatar de l’utilisateur
Noos88260
Messages : 8
Inscription : dim. 04/janv./2026 9:02
Localisation : FRANCE

Re: Quiz

Message par Noos88260 »

Procedure.pbi

Code : Tout sélectionner

Declare LectureMusic(*Parametre.Musique)
Declare.s InvCaractere(Chaine.s)
Declare EnvoieData(ClientID, Html.s)
Declare ExexuteDataQuery(ID.i,Commande.s)
Declare PageAccueilPostif(img)
Declare PageAccueil(IndicJoueur.i,img)
Declare PageJeuxQuestion(*Valeur)
Declare PageJeuxMusique(*Valeur)
Declare PageJeuxFilm(*Valeur)
Declare.s LectureFile(Fichier.s)
Declare PassageQuestion(*Valeur)
Declare PassageMusique(*Valeur)
Declare PassageVideo(*Valeur)
Declare Score()
Declare FinJeux(*Valeur)
Declare AjoutPoint(Identifiant.i, Points.i)
Declare GestionNetwork(*Valeur)
Declare GetIDClient(Client.i)
Declare AffichageTemp(*IDImage)

Procedure.i GetIDClient(Client.i)
  Protected idx.i = 1
  If FindString(Donnee_Joueur,Str(Client))
    Repeat
      Chaine.s = StringField(Donnee_Joueur,idx,";")
      If FindString(Chaine, Str(Client))
        IDClient.i = Val(StringField(Chaine,1,"="))   
        Break
      EndIf
      idx +1 
    ForEver
  Else
    IDClient = #False
  EndIf
  ProcedureReturn IDClient
EndProcedure

Procedure AjoutPoint(Identifiant.i, Points.i)
  ParaJoueur(Identifiant)\Point = ParaJoueur(Identifiant)\Point +Points
  If Jeux = #QuizMusique : ParaJoueur(Identifiant)\ScoreMusique = ParaJoueur(Identifiant)\ScoreMusique +Points
  ElseIf Jeux = #QuizFilm : ParaJoueur(Identifiant)\ScoreVideo = ParaJoueur(Identifiant)\ScoreVideo + Points
  ElseIf Jeux = #QuizQuestion : ParaJoueur(Identifiant)\ScoreQuestion = ParaJoueur(Identifiant)\ScoreQuestion + Points
  EndIf      
  
EndProcedure

Procedure LectureMusic(*Parametre.Musique)
  FinMediaSon = #False
  ; Création du stream de lecture 
  FMOD_System_CreateStream(FmodSystem, Ascii(*Parametre\File), #FMOD_SOFTWARE, 0, @sound)
  
  ;Play a sound on a free channel
  FMOD_System_PlaySound(fmodsystem, #FMOD_CHANNEL_FREE, sound, 0, @channel)
  
  Depart.i = ElapsedMilliseconds()
  
  For x = 0 To 100
    Vol.f = Vol + 1
    FMOD_Channel_SetVolume(Channel, Vol/100)
    Delay(10)
  Next
  
  Repeat
    Delay(100) 
    If FinReponse = #True
      Break
    EndIf 
  Until ElapsedMilliseconds() > Depart+ 30000
  
  For x = 0 To 100
    Vol.f = Vol - 1
    FMOD_Channel_SetVolume(Channel, Vol/100)
    Delay(10)
  Next
  FinMediaSon = #True
  ;   ClearStructure(*Parametres, Musique)
  ;   FreeMemory(*Parametres)
EndProcedure

Procedure.s InvCaractere(Chaine.s)
  Chaine.s = ReplaceString(Chaine,"$27","'")
  ProcedureReturn ReplaceString(Chaine,"$22",Chr(34))
EndProcedure

Procedure EnvoieData(ClientID, Html.s)
  Htmlp.s =""
  Html.s = Html + 
           ~"</body></html>"+ Space(20)+ #CRLF$ 
  LengthSHtml = Len(Html) 
  DayOfWeek.s = StringField("Sun, Mon,Tue,Wed,Thu,Fri,Sat", DayOfWeek(Date()) + 1, ",")
  Day = Day(Date())
  Month.s = StringField("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", Month(Date()), ",")
  Year.s = Str(Year(Date()))
  Time.s = FormatDate("%hh:%ii:%ss GMT", Date())
  Htmlp.s = "HTTP/1.1 200 OK" + #CRLF$ +
            "Date: " + DayOfWeek + ", " + Day + " " + Month + " " + Year + " " + Time  + #CRLF$ +
            "Server: "+ Title + #CRLF$ +
            "Content-Length: "+Str(LengthSHtml)  + #CRLF$ +  ;+ 
            "Content-Type: text/html" + #CRLF$ + #CRLF$
  SendNetworkString(ClientID,Htmlp + Html , #PB_UTF8)
EndProcedure

Procedure ExexuteDataQuery(ID.i,Commande.s)
  If IsDatabase(ID)
    If DatabaseQuery(ID, Commande)
      ProcedureReturn #True    
    Else 
      MessageRequester("Base de donnée", "Erreur sur base de donnée:"+ #CR$+ DatabaseError())
      ProcedureReturn #False
    EndIf
  Else
    MessageRequester("Base de donnée", "Base de donnée pas initialisé")
    ProcedureReturn #False
  EndIf
EndProcedure 

Procedure PageAccueilPostif(img)
  For Alpha = 0 To 255 Step 10
    If StartVectorDrawing(ImageVectorOutput(#Image))
      
      VectorSourceColor(RGBA(255, 255, 255, Alpha)) ; Couleur de font
      FillVectorOutput()
      MovePathCursor(Int(Largeur *0.25), 0)
      DrawVectorImage(ImageID(#Titre), Alpha, Int(Largeur *0.5), Int(Hauteur *0.4))
      
      MovePathCursor(Int(Largeur *0.75), Int(Hauteur *0.1))
      DrawVectorImage(ImageID(img), Alpha, Int(Largeur *0.2), Int(Hauteur *0.25))
      
      MovePathCursor(Int(Largeur *0.1), Int(Hauteur *0.4))
      VectorFont(FontID(#Police), Hauteur/20)
      VectorSourceColor(RGBA(0, 0, 50, Alpha))
      DrawVectorText("Bonjour et bienvenue sur le jeux de Quiz")
      MovePathCursor(Int(Largeur *0.1), Int(Hauteur *0.4)+ VectorTextHeight("A"))
      DrawVectorText("Veuillez vous connecté à l'aide du QR code")
      MovePathCursor(Int(Largeur *0.1), Int(Hauteur *0.4)+ (2*VectorTextHeight("A")))
      DrawVectorText("Ou à l'adresse suivante:   "+AdresseIPJeux)
      StopVectorDrawing()
      Delay(10)
      
    EndIf 
    SetGadgetState(#Font, ImageID(#Image)) ; Affichage
  Next Alpha
EndProcedure

Procedure PageAccueil(IndicJoueur.i,img)
  Protected LongueurText.i, HauteurText.i
  If StartVectorDrawing(ImageVectorOutput(#Image))
    VectorSourceColor(RGBA(255, 255, 255, 255)) ; Couleur de font
    FillVectorOutput()
    MovePathCursor(Int(Largeur *0.25), 0)
    DrawVectorImage(ImageID(#Titre), 255, Int(Largeur *0.5), Int(Hauteur *0.4))
    
    MovePathCursor(Int(Largeur *0.75), Int(Hauteur *0.1))
    DrawVectorImage(ImageID(img), 255, Int(Largeur *0.2), Int(Hauteur *0.25))
    
    MovePathCursor(Int(Largeur *0.1), Int(Hauteur *0.4))
    VectorFont(FontID(#Police), Hauteur/20)
    VectorSourceColor(RGBA(0, 0, 50, 255))
    DrawVectorText("Bonjour et bienvenue sur le jeux de Quiz")
    MovePathCursor(Int(Largeur *0.1), Int(Hauteur *0.4)+ VectorTextHeight("A"))
    DrawVectorText("Veuillez vous connecté à l'aide du QR code")
    MovePathCursor(Int(Largeur *0.1), Int(Hauteur *0.4)+ (2*VectorTextHeight("A")))
    DrawVectorText("Ou à l'adresse suivante:   "+AdresseIPJeux)
    
    If IndicJoueur = #True
      VectorSourceColor(RGBA(255, 137, 0, 255))
      MovePathCursor(Int(largeur*0.02),Int(Hauteur*0.02))
      DrawVectorText(Str(nbrJoueur+1)+ " joueurs")
      
      For Ai = 0 To nbrJoueur
        VectorSourceColor(ParaJoueur(Ai)\Couleur)
        NomJoueur.s = ParaJoueur(Ai)\Nom + ", "
        If LongueurText+VectorTextWidth(NomJoueur) >= (Largeur *0.96)
          LongueurText = 0
          HauteurText.i = HauteurText + VectorTextHeight("A")
          MovePathCursor(Int(Largeur *0.02)+LongueurText, Int(Hauteur *0.4)+HauteurText+ (3*VectorTextHeight("A")))
        Else    
          MovePathCursor(Int(Largeur *0.02)+LongueurText, Int(Hauteur *0.4)+HauteurText+ (3*VectorTextHeight("A")))
        EndIf      
        DrawVectorText(NomJoueur)
        LongueurText.i =  VectorTextWidth(NomJoueur) + LongueurText
      Next Ai
      
      VectorSourceColor(RGBA(255,0,0,255))
      MovePathCursor(Int(Largeur *0.1), Int(Hauteur *0.9))
      
      DrawVectorText("Appuyer sur la touche entrée pour démmarré le jeux")
    EndIf 
    
    StopVectorDrawing()
  EndIf 
  SetGadgetState(#Font, ImageID(#Image)) ; Affichage
EndProcedure

Procedure PageJeuxQuestion(*Valeur)
  FMOD_Channel_SetVolume(Channel, 0.04)
  Jeux = #QuizQuestion
  For Ji = 0 To nbrJoueur
    ParaJoueur(Ji)\Reponse = #False
    ParaJoueur(Ji)\Etape = 1
  Next Ji
  JoueurBonneReponse = 0
  FinReponse = #False
  ClearList(Proposition())
  
  If ExexuteDataQuery(#BaseDeDonnees, "SELECT * FROM Question WHERE ID='"+Str(NumQuestion(NbrPartieJouer))+"'; ")
    While NextDatabaseRow(#BaseDeDonnees)
      Theme.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 2))
      Question.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 3))
      BonRep.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 4))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 4))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 5))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 6))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 7))     
      Anecdote.s =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 8))
      LoadImage(#Media,Source + "Media\Images\"+ GetDatabaseString(#BaseDeDonnees, 9))  
    Wend
    FinishDatabaseQuery(#BaseDeDonnees)
  EndIf 
  
  RandomizeList(Proposition()) 
  SelectElement(Proposition(),0) : Prop1.s = Proposition()  
  SelectElement(Proposition(),1) : Prop2.s = Proposition()
  SelectElement(Proposition(),2) : Prop3.s = Proposition()
  SelectElement(Proposition(),3) : Prop4.s = Proposition()
  
  If Prop1 = BonRep : BonSelection.s = "A"
  ElseIf Prop2 = BonRep : BonSelection.s = "B"
  ElseIf Prop3 = BonRep : BonSelection.s = "C"
  ElseIf Prop4 = BonRep : BonSelection.s = "D"
  EndIf
  
  If StartVectorDrawing(ImageVectorOutput(#Image))     
    VectorSourceColor(RGBA(255, 255, 255, 255)) ; Couleur de font
    FillVectorOutput()
    MovePathCursor(Int(Largeur *0.3), 0)
    DrawVectorImage(ImageID(#Titre), 255, Int(Largeur *0.4), Int(Hauteur *0.3))
    MovePathCursor(Int(Largeur *0.25), Int(Hauteur *0.3))
    DrawVectorImage(ImageID(#Media), 255, Int(Largeur *0.5), Int(Hauteur *0.5))  
    MovePathCursor(Largeur*0.02, Int(Hauteur *0.8))
    VectorFont(FontID(#Police), Hauteur/20)
    VectorSourceColor(RGBA(0, 0, 50, 255)) 
    DrawVectorParagraph(Question,Largeur-Int(Largeur*0.02),Int(Hauteur*0.2))
    StopVectorDrawing()     
  EndIf 
  
  sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">" + Question +"</pitch>)")
  
  SetGadgetState(#Font, ImageID(#Image)) ; Affichage
  CreateThread(@AffichageTemp(),0)
EndProcedure

Procedure PageJeuxMusique(*Valeur)
  Jeux = #QuizMusique
  For Ji = 0 To nbrJoueur
    ParaJoueur(Ji)\Reponse = #False
    ParaJoueur(Ji)\Etape = 1
  Next Ji
  JoueurBonneReponse = 0
  FinReponse = #False
  ClearList(Proposition())
  ClearList(Proposition2())
  
  If ExexuteDataQuery(#BaseDeDonnees, "SELECT * FROM Musique WHERE ID='"+Str(NumMusique(NbrPartieJouer))+"'; ")
    While NextDatabaseRow(#BaseDeDonnees)
      Genre.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 1))
      Annee.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 2))
      Titre.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 3))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 3))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 4))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 5))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 6))
      
      Chanteur.s =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 7))
      AddElement(Proposition2()) : Proposition2() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 7))
      AddElement(Proposition2()) : Proposition2() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 8))
      AddElement(Proposition2()) : Proposition2() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 9))
      AddElement(Proposition2()) : Proposition2() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 10))
      
      MediaMusique.s=  InvCaractere(GetDatabaseString(#BaseDeDonnees, 11))
      
      RandomizeList(Proposition()) 
      SelectElement(Proposition(),0) : Titre1.s = Proposition()  
      SelectElement(Proposition(),1) : Titre2.s = Proposition()
      SelectElement(Proposition(),2) : Titre3.s = Proposition()
      SelectElement(Proposition(),3) : Titre4.s = Proposition()
      
      RandomizeList(Proposition2()) 
      SelectElement(Proposition2(),0) : Chanteur1.s = Proposition2()  
      SelectElement(Proposition2(),1) : Chanteur2.s = Proposition2()
      SelectElement(Proposition2(),2) : Chanteur3.s = Proposition2()
      SelectElement(Proposition2(),3) : Chanteur4.s = Proposition2()    
      
    Wend
    FinishDatabaseQuery(#BaseDeDonnees)
  EndIf 
  
  If Titre1 = Titre : BonSelection1.s = "A"
  ElseIf Titre2 = Titre : BonSelection1.s = "B"
  ElseIf Titre3 = Titre : BonSelection1.s = "C"
  ElseIf Titre4 = Titre : BonSelection1.s = "D"
  EndIf
  
  If Chanteur1 = Chanteur : BonSelection.s = "A"
  ElseIf Chanteur2 = Chanteur : BonSelection.s = "B"
  ElseIf Chanteur3 = Chanteur : BonSelection.s = "C"
  ElseIf Chanteur4 = Chanteur : BonSelection.s = "D"
  EndIf
  
  If StartVectorDrawing(ImageVectorOutput(#Image))     
    VectorSourceColor(RGBA(255, 255, 255, 255)) ; Couleur de font
    FillVectorOutput()
    MovePathCursor(Int(Largeur *0.3), 0)
    DrawVectorImage(ImageID(#Titre), 255, Int(Largeur *0.4), Int(Hauteur *0.3))
    MovePathCursor(Int(Largeur *0.25), Int(Hauteur *0.3))
    DrawVectorImage(ImageID(#MediaMusique), 255, Int(Largeur *0.5), Int(Hauteur *0.5))
    VectorFont(FontID(#Police), Hauteur/20)
    MovePathCursor((Largeur-VectorTextWidth(Genre+ " "+ Annee))/2, Int(Hauteur *0.8))  
    VectorSourceColor(RGBA(0, 0, 50, 255))
    DrawVectorText(Genre+ " "+ Annee)
    StopVectorDrawing()    
  EndIf 
  SetGadgetState(#Font, ImageID(#Image)) ; Affichage
  
  sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">" + ReplaceString(Genre, "/", " ") +" des années "+Annee +"</pitch>")
  
  For x = 1 To 10
    Delay(500)
    If sapi_IsVoiceRunning() = 0
      Break
    EndIf 
  Next x
  
  *Parametres.Musique = AllocateMemory(SizeOf(Musique))
  *Parametres\File = Source+ "Media\Musiques\"+ MediaMusique
  CreateThread(@LectureMusic(), *Parametres)
  CreateThread(@AffichageTemp(),0)
EndProcedure

Procedure PageJeuxFilm(*Valeur)
  Jeux = #QuizFilm
  For Ji = 0 To nbrJoueur
    ParaJoueur(Ji)\Reponse = #False
    ParaJoueur(Ji)\Etape = 1
  Next Ji
  JoueurBonneReponse = 0
  FinReponse = #False
  ClearList(Proposition())
  ClearList(Proposition2())
  
  If ExexuteDataQuery(#BaseDeDonnees, "SELECT * FROM Video WHERE ID='"+Str(NumVideo(NbrPartieJouer))+"'; ")
    While NextDatabaseRow(#BaseDeDonnees)
      
      Genre.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 1))
      Annee.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 2))
      BonRep.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 3))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 3))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 4))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 5))
      AddElement(Proposition()) : Proposition() =  InvCaractere(GetDatabaseString(#BaseDeDonnees, 6))       
      
      MediaMusique.s = InvCaractere(GetDatabaseString(#BaseDeDonnees, 7))
      MediaFilm.s=  InvCaractere(GetDatabaseString(#BaseDeDonnees, 8))
      
      RandomizeList(Proposition()) 
      SelectElement(Proposition(),0) : Prop1.s = Proposition()  
      SelectElement(Proposition(),1) : Prop2.s = Proposition()
      SelectElement(Proposition(),2) : Prop3.s = Proposition()
      SelectElement(Proposition(),3) : Prop4.s = Proposition()
      
    Wend
    FinishDatabaseQuery(#BaseDeDonnees)
  EndIf 
  
  If Prop1 = BonRep : BonSelection.s = "A"
  ElseIf Prop2 = BonRep : BonSelection.s = "B"
  ElseIf Prop3 = BonRep : BonSelection.s = "C"
  ElseIf Prop4 = BonRep : BonSelection.s = "D"
  EndIf
  
  If StartVectorDrawing(ImageVectorOutput(#Image))     
    VectorSourceColor(RGBA(255, 255, 255, 255)) ; Couleur de font
    FillVectorOutput()
    MovePathCursor(Int(Largeur *0.3), 0)
    DrawVectorImage(ImageID(#Titre), 255, Int(Largeur *0.4), Int(Hauteur *0.3))
    MovePathCursor(Int(Largeur *0.25), Int(Hauteur *0.3))
    DrawVectorImage(ImageID(#MediaVideo), 255, Int(Largeur *0.5), Int(Hauteur *0.5))
    VectorFont(FontID(#Police), Hauteur/20)
    MovePathCursor((Largeur-VectorTextWidth(Genre+ " "+ Annee))/2, Int(Hauteur *0.8))  
    VectorSourceColor(RGBA(0, 0, 50, 255))
    DrawVectorText(Genre+ " "+ Annee)
    StopVectorDrawing()    
  EndIf 
  SetGadgetState(#Font, ImageID(#Image)) ; Affichage
  
  sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">" + ReplaceString(Genre, "/", " ") +" des années "+Annee +"</pitch>")
  
  For x = 1 To 10
    Delay(500)
    If sapi_IsVoiceRunning() = 0
      Break
    EndIf 
  Next x
  *Parametres.Musique = AllocateMemory(SizeOf(Musique))
  *Parametres\File = Source+ "Media\Films\"+ MediaMusique
  CreateThread(@LectureMusic(), *Parametres)
  CreateThread(@AffichageTemp(),0)
EndProcedure

Procedure.s LectureFile(Fichier.s)
  Protected Lecture.s
  If ReadFile(#Fichier, Fichier, #PB_UTF8)             
    While Eof(#Fichier) = 0  
      Lecture.s= Lecture+ ReadString(#Fichier, #PB_UTF8) + #CRLF$
    Wend
    CloseFile(#Fichier)
  Else
    MessageRequester("Erreur","Impossible de lire le fichier "+Fichier)
  EndIf
  
  ProcedureReturn Lecture
EndProcedure

Procedure PassageQuestion(*Valeur)
  Decompte = #False
  sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">La bonne réponse était:" + BonRep + "<silence msec="+Chr(34)+"500"+Chr(34)+"/>" + Anecdote + "</pitch>")
  If StartVectorDrawing(ImageVectorOutput(#Image)) 
    VectorFont(FontID(#Police), Hauteur/20)
    MovePathCursor((Largeur-VectorTextWidth(BonRep))/2, Int(Hauteur *0.8)+VectorTextHeight("A"))  
    VectorSourceColor(RGBA(0, 100, 0, 255))
    DrawVectorText(BonRep)
    StopVectorDrawing()
    SetGadgetState(#Font, ImageID(#Image)) ; Affichage
  EndIf 
  Repeat
    Delay(500)   
  Until sapi_IsVoiceRunning() = 0
  FMOD_Channel_GetPosition(Channel,@CurrentPos,1)
  FMOD_Channel_Stop(Channel)
  PageJeuxMusique(0)
EndProcedure

Procedure PassageMusique(*Valeur)
  Repeat
    Delay(500)
  Until FinMediaSon = #True
  Decompte = #False
  sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">La bonne réponse était: " + Titre +" de " + Chanteur +"</pitch>")
  If StartVectorDrawing(ImageVectorOutput(#Image)) 
    VectorFont(FontID(#Police), Hauteur/20)
    MovePathCursor((Largeur-VectorTextWidth(Titre +" de " + Chanteur))/2, Int(Hauteur *0.8)+VectorTextHeight("A"))  
    VectorSourceColor(RGBA(0, 100, 0, 255))
    DrawVectorText(Titre +" de " + Chanteur)
    StopVectorDrawing()
    SetGadgetState(#Font, ImageID(#Image)) ; Affichage
  EndIf 
  Repeat
    Delay(500)   
  Until sapi_IsVoiceRunning() = 0
  PageJeuxFilm(0)
EndProcedure

Procedure PassageVideo(*Valeur)
  Repeat
    Delay(500)
  Until FinMediaSon = #True
  Decompte = #False
  sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">La bonne réponse était: " + BonRep +"</pitch>")
  If StartVectorDrawing(ImageVectorOutput(#Image)) 
    VectorFont(FontID(#Police), Hauteur/20)
    MovePathCursor((Largeur-VectorTextWidth(BonRep))/2, Int(Hauteur *0.8)+VectorTextHeight("A"))  
    VectorSourceColor(RGBA(0, 100, 0, 255))
    DrawVectorText(BonRep)
    StopVectorDrawing()
    SetGadgetState(#Font, ImageID(#Image)) ; Affichage
  EndIf 
  RunProgram(Source+"Video.exe",Source+ "Media\Films\"+ MediaFilm,"", #PB_Program_Wait)
  Score()
EndProcedure

Procedure AffichageTemp(*IDImage)
  Decompte = #True
  For tmp = 30 To 0 Step -1  
    If StartVectorDrawing(ImageVectorOutput(#Image))
      MovePathCursor(0, 0) 
      DrawVectorImage(ImageID(#ImageFont), 255, Int(Largeur *0.3), Int(Hauteur *0.3))
      VectorFont(FontID(#Police), Hauteur/5)  
      MovePathCursor(largeur*0.02, Hauteur*0.02) 
      If nbrBonReponse > JoueurBonneReponse And tmp > 5
        VectorSourceColor(RGBA(0, 220, 0, 255))
      ElseIf tmp < 5 And tmp > 0
        VectorSourceColor(RGBA(255, 0, 0, 255))
      ElseIf tmp = 0
        VectorSourceColor(RGBA(255, 255, 255, 255))
      Else
        VectorSourceColor(RGBA(255, 126, 0, 255))
      EndIf 
      DrawVectorText(Str(tmp))
      
      StopVectorDrawing()
      SetGadgetState(#Font, ImageID(#Image)) ; Affichage
    EndIf 
    Delay(1000)
    If Decompte = #False
      Break
    EndIf 
  Next tmp
  If Decompte = #True
    If Jeux = #QuizQuestion And Not IsThread(Thread)
      Thread = CreateThread(@PassageQuestion(),0) 
    ElseIf Jeux = #QuizMusique And Not IsThread(Thread)
      Thread = CreateThread(@PassageMusique(),0)    
    ElseIf Jeux = #QuizFilm  And Not IsThread(Thread)
      Thread = CreateThread(@PassageVideo(),0)
    EndIf 
  EndIf 
EndProcedure

Procedure Score()
  CopyArray(ParaJoueur(),CopieParaJoueur())
  For Si = 0 To nbrJoueur   
    If ParaJoueur(Si)\Attaqueur_Block <> ""
      Nom_deffenseur.s = ParaJoueur(Si)\Nom
      Point_Block_Question.i = ParaJoueur(Si)\ScoreQuestion
      Point_Block_Musique.i = ParaJoueur(Si)\ScoreMusique
      Point_Block_Video.i = ParaJoueur(Si)\ScoreVideo
      ParaJoueur(Si)\Point = ParaJoueur(Si)\Point - Point_Block_Question - Point_Block_Musique - Point_Block_Video
      CopieParaJoueur(Si)\Point = ParaJoueur(Si)\Point
      ParaJoueur(Si)\ScoreMusique = 0
      ParaJoueur(Si)\ScoreQuestion = 0
      ParaJoueur(Si)\ScoreVideo = 0
      ParaJoueur(Si)\Attaqueur_Block = ""
      ParaJoueur(Si)\TypeAttaque = 1
      ParaJoueur(Si)\Nbr_Block = ParaJoueur(Si)\Nbr_Block +1
      For SiC = 0 To nbrJoueur
        If CopieParaJoueur(SiC)\Nom = Nom_deffenseur
          CopieParaJoueur(SiC)\Point = CopieParaJoueur(SiC)\Point - Point_vole_Question - Point_vole_Musique - Point_vole_Video
          CopieParaJoueur(SiC)\ScoreQuestion = 0
          CopieParaJoueur(SiC)\ScoreMusique = 0
          CopieParaJoueur(SiC)\ScoreVideo = 0  
          Break
        EndIf 
      Next SiC
    EndIf 
    
    Nom_Attaque_Voleur.s = ParaJoueur(Si)\Attaqueur_Voleur
    If Nom_Attaque_Voleur <> ""
      Nom_deffenseur.s = ParaJoueur(Si)\Nom
      Point_vole_Question.i = ParaJoueur(Si)\ScoreQuestion
      Point_vole_Musique.i = ParaJoueur(Si)\ScoreMusique
      Point_vole_Video.i = ParaJoueur(Si)\ScoreVideo
      ParaJoueur(Si)\Point = ParaJoueur(Si)\Point - Point_vole_Question - Point_vole_Musique - Point_vole_Video
      CopieParaJoueur(Si)\Point = ParaJoueur(Si)\Point
      ParaJoueur(Si)\ScoreMusique = 0
      ParaJoueur(Si)\ScoreQuestion = 0
      ParaJoueur(Si)\ScoreVideo = 0
      ParaJoueur(Si)\Attaqueur_Voleur = ""
      ParaJoueur(Si)\TypeAttaque = 1
      ParaJoueur(Si)\Nbr_Vol = ParaJoueur(Si)\Nbr_Vol +1
      For SiC = 0 To nbrJoueur
        If CopieParaJoueur(SiC)\Nom = Nom_Attaque_Voleur ; Récupération des points pour le voleur Voleur
          CopieParaJoueur(SiC)\Point = CopieParaJoueur(SiC)\Point + Point_vole_Question + Point_vole_Musique + Point_vole_Video
          ParaJoueur(SiC)\Point = CopieParaJoueur(SiC)\Point
          CopieParaJoueur(SiC)\ScoreQuestion = CopieParaJoueur(SiC)\ScoreQuestion + Point_vole_Question
          CopieParaJoueur(SiC)\ScoreMusique = CopieParaJoueur(SiC)\ScoreMusique + Point_vole_Musique
          CopieParaJoueur(SiC)\ScoreVideo = CopieParaJoueur(SiC)\ScoreVideo + Point_vole_Video         
        EndIf 
      Next SiC
    EndIf 
    
    ParaJoueur(Si)\ScoreMusique = 0
    ParaJoueur(Si)\ScoreQuestion = 0
    ParaJoueur(Si)\ScoreVideo = 0
    ParaJoueur(Si)\Attaqueur_Block = ""
    ParaJoueur(Si)\Attaqueur_Voleur = ""
    ParaJoueur(Si)\TypeAttaque = 1
    
  Next Si
  
  MeilleurScore.i = 0
  Egalite_Joueur_Point.i = 0
  Nom_Joueur_Point.s = ""
  For SiC = 0 To nbrJoueur
    If CopieParaJoueur(SiC)\Point >= MeilleurScore
      MeilleurScore.i = CopieParaJoueur(SiC)\Point
    EndIf  
  Next SiC
  
  For SiC = 0 To nbrJoueur
    If CopieParaJoueur(SiC)\Point = MeilleurScore
      Nom_Joueur_Point.s = CopieParaJoueur(SiC)\Nom + ", " + Nom_Joueur_Point
      Egalite_Joueur_Point.i = Egalite_Joueur_Point +1
    EndIf  
  Next SiC
  If Egalite_Joueur_Point > 1    
    sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">Egalité du meilleur score avec " + Nom_Joueur_Point +" ont le meilleur score</pitch>")
  Else
    sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">" + Nom_Joueur_Point +" à le meilleur score</pitch>")
  EndIf
  
  Jeux = #QuizScore
  nbrj = 0
  NbrPartieJouer = NbrPartieJouer + 1
  ; Création du stream de lecture 
  FMOD_System_CreateStream(FmodSystem, Ascii(Source+ "Data\Into.mp3"), #FMOD_SOFTWARE, 0, @sound)    
  ;Play a sound on a free channel
  FMOD_System_PlaySound(fmodsystem, #FMOD_CHANNEL_FREE, sound, 0, @channel)
  ;Volume
  FMOD_Channel_SetVolume(Channel, 0.1)
  FMOD_Channel_SetPosition(channel,CurrentPos,1)
  
  If StartVectorDrawing(ImageVectorOutput(#Image))     
    VectorSourceColor(RGBA(255, 255, 255, 255)) ; Couleur de font
    FillVectorOutput()    
    MovePathCursor(Int(Largeur *0.3), 0)
    DrawVectorImage(ImageID(#Score), 255, Int(Largeur *0.4), Int(Hauteur *0.3))  
    VectorFont(FontID(#Police), Hauteur/20)
    VectorSourceColor(RGBA(0, 0, 0, 255))
    MovePathCursor(0, 0)
    DrawVectorText(" Partie "+Str(NbrPartieJouer)+ "/"+Str(NbrPartie))
    MovePathCursor(Int(Largeur*0.5),Int(Hauteur*0.3))
    DrawVectorText(" Questions  Musiques  Videos  Score")
    MovePathCursor(Int(Largeur*0.5),Int(Hauteur*0.3))
    AddPathLine(Int(Largeur*0.5),Hauteur)
    StrokePath(5, #PB_Path_RoundCorner)
    MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Questions "),Int(Hauteur*0.3))
    AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Questions "),Hauteur)
    StrokePath(5, #PB_Path_RoundCorner)
    MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Questions  Musiques "),Int(Hauteur*0.3))
    AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Questions  Musiques "),Hauteur)
    StrokePath(5, #PB_Path_RoundCorner)
    MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Questions  Musiques  Videos "),Int(Hauteur*0.3))
    AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Questions  Musiques  Videos "),Hauteur)
    MovePathCursor(0,Int(Hauteur*0.3)+VectorTextHeight("A"))
    AddPathLine(Largeur,Int(Hauteur*0.3)+VectorTextHeight("A"))
    StrokePath(5, #PB_Path_RoundCorner)
    
    SortStructuredArray(CopieParaJoueur(), #PB_Sort_Descending,  OffsetOf(Joueur\Point), TypeOf(Joueur\Point))  
    nbrj = 0
    For SiC = 0 To nbrJoueur
      nbrj = nbrj +1
      CouleurFond = RGBA(0, 0, 0, 0)
      If CopieParaJoueur(SiC)\TypeAttaque = 2 ;PointX2
        Detail.s = " PointX2" 
      ElseIf CopieParaJoueur(SiC)\TypeAttaque = 3 ;Block
        Detail.s = " Bloqueur" 
      ElseIf CopieParaJoueur(SiC)\TypeAttaque = 4 ;Voleur
        Detail.s = " Voleur" 
      Else
        Detail.s = ""
      EndIf 
      If CopieParaJoueur(Sic)\Attaqueur_Block <> ""
        Detail.s = Detail + " Bloqué par "+CopieParaJoueur(SiC)\Attaqueur_Block
        CouleurFond = RGBA(0, 0, 0, 90)
      EndIf
      If CopieParaJoueur(Sic)\Attaqueur_Voleur <> ""
        Detail.s = Detail + " Volé par "+CopieParaJoueur(SiC)\Attaqueur_Voleur
        CouleurFond = RGBA(0, 0, 0, 90)
      EndIf      
      MovePathCursor(Int(Largeur*0.25)-VectorTextWidth(CopieParaJoueur(SiC)\Nom + " "+Detail)/2, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      VectorSourceColor(CopieParaJoueur(SiC)\Couleur) 
      DrawVectorText(CopieParaJoueur(SiC)\Nom + Detail)
      VectorSourceColor(RGBA(0, 0, 0, 255))
      MovePathCursor(0,Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      AddPathLine(Largeur,Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      StrokePath(5, #PB_Path_RoundCorner)
      If CopieParaJoueur(SiC)\ScoreQuestion = 0
        VectorSourceColor(RGBA(255, 0, 0, 255))
      ElseIf CopieParaJoueur(SiC)\ScoreQuestion = 1
        VectorSourceColor(RGBA(255, 126, 0, 255))
      Else 
        VectorSourceColor(RGBA(0, 255, 0, 255))
      EndIf 
      MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Questions ")/2, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      DrawVectorText(Str(CopieParaJoueur(SiC)\ScoreQuestion))
      If CopieParaJoueur(SiC)\ScoreMusique = 0
        VectorSourceColor(RGBA(255, 0, 0, 255))
      ElseIf CopieParaJoueur(SiC)\ScoreMusique = 1
        VectorSourceColor(RGBA(255, 126, 0, 255))
      Else 
        VectorSourceColor(RGBA(0, 255, 0, 255))
      EndIf 
      MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Questions ")+VectorTextWidth(" Musiques ")/2, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      DrawVectorText(Str(CopieParaJoueur(SiC)\ScoreMusique))
      
      If CopieParaJoueur(SiC)\ScoreVideo = 0
        VectorSourceColor(RGBA(255, 0, 0, 255))
      ElseIf CopieParaJoueur(SiC)\ScoreVideo = 1
        VectorSourceColor(RGBA(255, 126, 0, 255))
      Else 
        VectorSourceColor(RGBA(0, 255, 0, 255))
      EndIf 
      MovePathCursor(Int(Largeur*0.5) +VectorTextWidth(" Questions  Musiques ")+VectorTextWidth(" Videos ")/2, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      
      DrawVectorText(Str(CopieParaJoueur(SiC)\ScoreVideo))
      
      MovePathCursor(Int(Largeur*0.5) +VectorTextWidth(" Questions  Musiques  Videos ")+VectorTextWidth(" Score ")/2, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      VectorSourceColor(RGBA(0, 0, 0, 255))
      DrawVectorText(Str(CopieParaJoueur(SiC)\Point))
      
      VectorSourceColor(CouleurFond)
      AddPathBox(0, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj), Largeur, VectorTextHeight("A"))
      FillPath()
      
      If nbrj <=10
        MovePathCursor(Int(Largeur *0.02), Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      Else    
        StopVectorDrawing()
        SetGadgetState(#Font, ImageID(#Image)) ; Affichage
        Delay(5000)
        StartVectorDrawing(ImageVectorOutput(#Image))  
        VectorSourceColor(RGBA(255, 255, 255, 255)) ; Couleur de font
        FillVectorOutput()    
        MovePathCursor(Int(Largeur *0.3), 0)
        DrawVectorImage(ImageID(#Score), 255, Int(Largeur *0.4), Int(Hauteur *0.3))  
        VectorFont(FontID(#Police), Hauteur/20)
        VectorSourceColor(RGBA(0, 0, 0, 255))
        MovePathCursor(0, 0)
        DrawVectorText(" Partie "+Str(NbrPartieJouer)+ "/"+Str(NbrPartie))
        MovePathCursor(Int(Largeur*0.5),Int(Hauteur*0.3))
        DrawVectorText(" Questions  Musiques  Videos  Score")
        MovePathCursor(Int(Largeur*0.5),Int(Hauteur*0.3))
        AddPathLine(Int(Largeur*0.5),Hauteur)
        StrokePath(5, #PB_Path_RoundCorner)
        MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Questions "),Int(Hauteur*0.3))
        AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Questions "),Hauteur)
        StrokePath(5, #PB_Path_RoundCorner)
        MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Questions  Musiques "),Int(Hauteur*0.3))
        AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Questions  Musiques "),Hauteur)
        StrokePath(5, #PB_Path_RoundCorner)
        MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Questions  Musiques  Videos "),Int(Hauteur*0.3))
        AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Questions  Musiques  Videos "),Hauteur)
        MovePathCursor(0,Int(Hauteur*0.3)+VectorTextHeight("A"))
        AddPathLine(Largeur,Int(Hauteur*0.3)+VectorTextHeight("A"))
        StrokePath(5, #PB_Path_RoundCorner)
        nbrj = 0
      EndIf      
    Next  
    StopVectorDrawing()
    SetGadgetState(#Font, ImageID(#Image)) ; Affichage
  EndIf 
  Repeat
    t = t+1
    Delay(1000)  
  Until t >=15
  
  If NbrPartie = NbrPartieJouer
    FinJeux(0)
  Else
    ;     FMOD_Channel_GetPosition(Channel,@CurrentPos,1)
    ;     FMOD_Channel_Stop(Channel)
    PageJeuxQuestion(0)
    
  EndIf 
EndProcedure

Procedure FinJeux(*Valeur)
  Egalite_Joueur_Block.i = 0
  Egalite_Joueur_Vol.i = 0
  Nbr_Maxi.i = 0 
  Joueur_Nbr_Block.s = ""
  Joueur_Nbr_Vol.s = ""
  For Fi = 0 To nbrJoueur
    If ParaJoueur(Fi)\Nbr_Block >= Nbr_Maxi
      Nbr_Maxi.i = ParaJoueur(Fi)\Nbr_Block
    EndIf  
  Next Fi
  
  For Fi = 0 To nbrJoueur
    If ParaJoueur(Fi)\Nbr_Block = Nbr_Maxi
      Joueur_Nbr_Block.s = ParaJoueur(Fi)\Nom + ", " + Joueur_Nbr_Block
      Egalite_Joueur_Block.i = Egalite_Joueur_Block +1
    EndIf  
  Next Fi
  If Egalite_Joueur_Block > 1 
    TextMaxiBlock.s =  "Autant de bloque avec "+ Joueur_Nbr_Block + " pour " + Str(Nbr_Maxi) + " bloques chancun."
  Else
    TextMaxiBlock.s = "Un maximun de bloque pour " +Joueur_Nbr_Block + " avec " + Str(Nbr_Maxi) + " bloques"
  EndIf
  
  Nbr_Maxi.i = 0
  For Fi = 0 To nbrJoueur
    If ParaJoueur(Fi)\Nbr_Vol >= Nbr_Maxi
      Nbr_Maxi.i = ParaJoueur(Fi)\Nbr_Vol
    EndIf  
  Next Fi
  For Fi = 0 To nbrJoueur
    If ParaJoueur(Fi)\Nbr_Vol = Nbr_Maxi
      Joueur_Nbr_Vol.s = ParaJoueur(Fi)\Nom + ", " + Joueur_Nbr_Vol
      Egalite_Joueur_Vol.i = Egalite_Joueur_Vol +1
    EndIf  
  Next Fi
  If Egalite_Joueur_Vol > 1 
    TextMaxiVole.s = "Autant de vole avec "+ Joueur_Nbr_Vol + " pour "+ Str(Nbr_Maxi) + " Vole chancun."
  Else
    TextMaxiVole.s = "Un Maximun de vole pour "+ Joueur_Nbr_Vol + "avec " + Str(Nbr_Maxi) + " voles"
  EndIf
  
  If StartVectorDrawing(ImageVectorOutput(#Image))     
    VectorSourceColor(RGBA(255, 255, 255, 255)) ; Couleur de font
    FillVectorOutput()    
    MovePathCursor(Int(Largeur *0.3), 0)
    DrawVectorImage(ImageID(#Score), 255, Int(Largeur *0.4), Int(Hauteur *0.3))  
    VectorFont(FontID(#Police), Hauteur/20)
    VectorSourceColor(RGBA(0, 0, 0, 255))
    MovePathCursor(Int(Largeur*0.5),Int(Hauteur*0.3))
    DrawVectorText(" Nbr Bloqués  Nbr Volés ")
    MovePathCursor(Int(Largeur*0.5),Int(Hauteur*0.3))
    AddPathLine(Int(Largeur*0.5),Hauteur)
    StrokePath(5, #PB_Path_RoundCorner)
    MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués "),Int(Hauteur*0.3))
    AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués "),Hauteur)
    StrokePath(5, #PB_Path_RoundCorner)
    MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués  Nbr Volés "),Int(Hauteur*0.3))
    AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués  Nbr Volés "),Hauteur)
    Largeur1 = Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués  Nbr Volés ")
    Largeur2 = ((Largeur - Largeur1)/2)-(VectorTextWidth(" Score ")/2)+ Largeur1
    MovePathCursor(Largeur2,Int(Hauteur*0.3))
    DrawVectorText(" Score ") 
    MovePathCursor(0,Int(Hauteur*0.3)+VectorTextHeight("A"))
    AddPathLine(Largeur,Int(Hauteur*0.3)+VectorTextHeight("A"))
    StrokePath(5, #PB_Path_RoundCorner)
    
    nbrj = 0
    For Fi = 0 To nbrJoueur
      nbrj = nbrj +1
      
      MovePathCursor(Int(Largeur*0.25)-VectorTextWidth(CopieParaJoueur(Fi)\Nom + " ")/2, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      VectorSourceColor(CopieParaJoueur(Fi)\Couleur) 
      DrawVectorText(CopieParaJoueur(Fi)\Nom)
      VectorSourceColor(RGBA(0, 0, 0, 255))
      MovePathCursor(0,Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      AddPathLine(Largeur,Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      StrokePath(5, #PB_Path_RoundCorner)
      If CopieParaJoueur(Fi)\Nbr_Block = 0
        VectorSourceColor(RGBA(0, 0, 0, 255))
      ElseIf CopieParaJoueur(Fi)\Nbr_Block > 0 And CopieParaJoueur(Fi)\Nbr_Block <= 2
        VectorSourceColor(RGBA(255, 126, 0, 255))
      Else 
        VectorSourceColor(RGBA(255, 0, 0, 255))
      EndIf  
      MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués ")/2, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      DrawVectorText(Str(CopieParaJoueur(Fi)\Nbr_Block))
      
      If CopieParaJoueur(Fi)\Nbr_Vol = 0
        VectorSourceColor(RGBA(0, 0, 0, 255))
      ElseIf CopieParaJoueur(Fi)\Nbr_Vol > 0 And CopieParaJoueur(Fi)\Nbr_Vol <= 2
        VectorSourceColor(RGBA(255, 126, 0, 255))
      Else 
        VectorSourceColor(RGBA(255, 0, 0, 255))
      EndIf 
      MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués ")+VectorTextWidth(" Nbr Volés ")/2, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      DrawVectorText(Str(CopieParaJoueur(Fi)\Nbr_Vol))
      
      MovePathCursor(Largeur2+VectorTextWidth(" Score ")/2, Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      VectorSourceColor(RGBA(0, 0, 0, 255))
      DrawVectorText(Str(CopieParaJoueur(Fi)\Point))
      
      If nbrj < 10
        MovePathCursor(Int(Largeur *0.02), Int(Hauteur *0.3)+(VectorTextHeight("A")*nbrj))
      Else    
        StopVectorDrawing()
        SetGadgetState(#Font, ImageID(#Image)) ; Affichage
        Delay(5000)
        StartVectorDrawing(ImageVectorOutput(#Image))   
        VectorSourceColor(RGBA(255, 255, 255, 255)) ; Couleur de font
        FillVectorOutput()    
        MovePathCursor(Int(Largeur *0.3), 0)
        DrawVectorImage(ImageID(#Score), 255, Int(Largeur *0.4), Int(Hauteur *0.3))  
        VectorFont(FontID(#Police), Hauteur/20)
        VectorSourceColor(RGBA(0, 0, 0, 255))
        MovePathCursor(Int(Largeur*0.5),Int(Hauteur*0.3))
        DrawVectorText(" Nbr Bloqués  Nbr Volés ")
        MovePathCursor(Int(Largeur*0.5),Int(Hauteur*0.3))
        AddPathLine(Int(Largeur*0.5),Hauteur)
        StrokePath(5, #PB_Path_RoundCorner)
        MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués "),Int(Hauteur*0.3))
        AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués "),Hauteur)
        StrokePath(5, #PB_Path_RoundCorner)
        MovePathCursor(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués  Nbr Volés "),Int(Hauteur*0.3))
        AddPathLine(Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués  Nbr Volés "),Hauteur)
        Largeur1 = Int(Largeur*0.5)+VectorTextWidth(" Nbr Bloqués  Nbr Volés ")
        Largeur2 = ((Largeur - Largeur1)/2)-(VectorTextWidth(" Score ")/2)+ Largeur1
        MovePathCursor(Largeur2,Int(Hauteur*0.3))
        DrawVectorText(" Score ")
        MovePathCursor(0,Int(Hauteur*0.3)+VectorTextHeight("A"))
        AddPathLine(Largeur,Int(Hauteur*0.3)+VectorTextHeight("A"))
        StrokePath(5, #PB_Path_RoundCorner)
        nbrj = 0
      EndIf      
    Next  
    StopVectorDrawing()
    SetGadgetState(#Font, ImageID(#Image)) ; Affichage
  EndIf 
  
  sapi_Say("<pitch absmiddle="+Chr(34)+ Hauteur_Voix+ Chr(34)+">" +
           TextMaxiBlock + "<silence msec="+Chr(34)+"2000"+Chr(34)+"/>"+
           TextMaxiVole + "<silence msec="+Chr(34)+"2000"+Chr(34)+"/>"+
           "Fin du jeux <silence msec="+Chr(34)+"30000"+Chr(34)+"/></pitch>")
  
  Repeat
    Delay(500)   
  Until sapi_IsVoiceRunning() = 0
  CloseNetworkServer(#Serveur)
  CloseDatabase(#BaseDeDonnees)
  sapi_DeInit()
  ShowWindow_(FindWindow_("Shell_TrayWnd",""),#SW_SHOW); Active barre des taches
  End
EndProcedure

Procedure GestionNetwork(*Valeur)
  BufferSize = 1024
  *Buffer = AllocateMemory(BufferSize)
  Buffer.s
  Repeat
    Delay(1)
    ServerEvent = NetworkServerEvent()
    If ServerEvent
      ClientID = EventClient()
      ID_Utilisateur.i = GetIDClient(GetClientIP(ClientID))
      Buffer = ""
      Select ServerEvent              
        Case #PB_NetworkEvent_Data 
          Repeat
            *Buffer = AllocateMemory(BufferSize)
            Result = ReceiveNetworkData(ClientID, *Buffer, BufferSize)
            Buffer + PeekS(*Buffer, -1, #PB_UTF8)
          Until Result <> BufferSize
          If Left(Buffer, 3) = "GET"
            RequestedFile.s = Trim(Mid(StringField(Buffer, 1, "HTTP"), 6))  
            
            ;- Selection des réponses
            If RequestedFile = "Go" ;Selection des réponses
              If ParaJoueur(ID_Utilisateur)\Reponse = #False
                If Jeux = #QuizQuestion Or #QuizFilm
                  Html.s = Go+                   
                           ~"<div class=\"buttons\">"+ #CRLF$ +
                           ~"<button onclick=\"selectOption('Reponse=A')\">"+Prop1+"</button>"+ #CRLF$ +
                           ~"<button onclick=\"selectOption('Reponse=B')\">"+Prop2+"</button>"+ #CRLF$ +
                           ~"<button onclick=\"selectOption('Reponse=C')\">"+Prop3+"</button>"+ #CRLF$ +
                           ~"<button onclick=\"selectOption('Reponse=D')\">"+Prop4+"</button>"+ #CRLF$ +
                           ~"</div>"+ #CRLF$
                  
                  Html.s = Html + Script5secondes
                EndIf
                
                If Jeux = #QuizMusique
                  Html.s = Go+                   
                           ~"<div class=\"buttons\">"+ #CRLF$ +
                           ~"<button onclick=\"selectOption('Reponse=A')\">"+Chanteur1+"</button>"+ #CRLF$ +
                           ~"<button onclick=\"selectOption('Reponse=B')\">"+Chanteur2+"</button>"+ #CRLF$ +
                           ~"<button onclick=\"selectOption('Reponse=C')\">"+Chanteur3+"</button>"+ #CRLF$ +
                           ~"<button onclick=\"selectOption('Reponse=D')\">"+Chanteur4+"</button>"+ #CRLF$ +
                           ~"</div>"+ #CRLF$
                  
                  Html.s = Html + Script5secondes                        
                  
                EndIf 
                EnvoieData(ClientID, Html.s)
              EndIf 
              
              ;- Reponse tardive   
            ElseIf  RequestedFile = "DelayUp.html"
              EnvoieData(ClientID, DelayUp)
              
              ;Ajout de la validation d"avoir répondu
              
              ParaJoueur(ID_Utilisateur)\Reponse = #True
              
              For Ri = 0 To nbrJoueur
                If ParaJoueur(Ri)\Reponse = #False ;Savoir si tous les joueurs on répondu
                  FinReponse = #False
                  Break
                Else
                  FinReponse = #True
                EndIf 
              Next Ri
              
              If FinReponse = #True  ;Si tous les joueurs on répondu alors on passe à l'étape suivante
                If Jeux = #QuizQuestion And Not IsThread(Thread)
                  Thread = CreateThread(@PassageQuestion(),0) 
                ElseIf Jeux = #QuizMusique And Not IsThread(Thread)
                  Thread = CreateThread(@PassageMusique(),0)    
                ElseIf Jeux = #QuizFilm  And Not IsThread(Thread)
                  Thread = CreateThread(@PassageVideo(),0)
                EndIf 
              EndIf
              
              ;- Reponse A B C D
            ElseIf Left(RequestedFile, 8) = "Reponse=" 
              If Jeux = #QuizQuestion Or Jeux = #QuizFilm  
                ParaJoueur(ID_Utilisateur)\Reponse = #True
              EndIf 
              If  Jeux = #QuizMusique And ParaJoueur(ID_Utilisateur)\Etape = 2
                ParaJoueur(ID_Utilisateur)\Reponse = #True
              EndIf 
              If ParaJoueur(ID_Utilisateur)\Etape = 1
                If BonSelection = Right(RequestedFile,1) ;Vérification de la réponse A,B,C ou D
                  If Jeux = #QuizQuestion Or Jeux = #QuizFilm  
                    EnvoieData(ClientID, Bonne_reponse)  
                  ElseIf Jeux = #QuizMusique  
                    ParaJoueur(ID_Utilisateur)\Etape = 2
                    Html.s = Go2+
                             ~"<div class=\"buttons\">"+ #CRLF$ +
                             ~"<button onclick=\"selectOption('Reponse=A')\">"+Titre1+"</button>"+ #CRLF$ +
                             ~"<button onclick=\"selectOption('Reponse=B')\">"+Titre2+"</button>"+ #CRLF$ +
                             ~"<button onclick=\"selectOption('Reponse=C')\">"+Titre3+"</button>"+ #CRLF$ +
                             ~"<button onclick=\"selectOption('Reponse=D')\">"+Titre4+"</button>"+ #CRLF$ +
                             ~"</div>"+ #CRLF$
                    
                    Html.s = Html + Script5secondes
                    EnvoieData(ClientID, Html) 
                  EndIf   
                  ParaJoueur(ID_Utilisateur)\ReponseOK = #True
                  JoueurBonneReponse = JoueurBonneReponse +1
                  If nbrBonReponse >= JoueurBonneReponse ; bonnus
                    If ParaJoueur(ID_Utilisateur)\TypeAttaque = 2
                      AjoutPoint(ID_Utilisateur, 4)                               
                    Else
                      AjoutPoint(ID_Utilisateur, 2)
                    EndIf  
                  Else                           
                    If ParaJoueur(ID_Utilisateur)\TypeAttaque = 2
                      AjoutPoint(ID_Utilisateur, 2)
                    Else
                      AjoutPoint(ID_Utilisateur, 1)
                    EndIf 
                  EndIf 
                Else
                  EnvoieData(ClientID, Mauvaise_reponse)
                  ParaJoueur(ID_Utilisateur)\Reponse = #True
                EndIf
              ElseIf ParaJoueur(ID_Utilisateur)\Etape = 2
                If BonSelection1 = Right(RequestedFile,1) ;Vérification de la réponse A,B,C ou D
                  EnvoieData(ClientID, Bonne_reponse)
                  JoueurBonneReponse = JoueurBonneReponse +1
                  If nbrBonReponse >= JoueurBonneReponse ; bonnus
                    If ParaJoueur(ID_Utilisateur)\TypeAttaque = 2
                      AjoutPoint(ID_Utilisateur, 4)    
                    Else
                      AjoutPoint(ID_Utilisateur, 2)
                    EndIf  
                  Else
                    If ParaJoueur(ID_Utilisateur)\TypeAttaque = 2
                      AjoutPoint(ID_Utilisateur, 2)
                    Else
                      AjoutPoint(ID_Utilisateur, 1)
                    EndIf 
                  EndIf 
                Else
                  EnvoieData(ClientID, Mauvaise_reponse)
                EndIf 
              EndIf 
              
              For Ri = 0 To nbrJoueur
                If ParaJoueur(Ri)\Reponse = #False ;Savoir si tous les joueurs on répondu
                  FinReponse = #False
                  Break
                Else
                  FinReponse = #True
                EndIf 
              Next Ri
              
              If FinReponse = #True  ;Si tous les joueurs on répondu alors on passe à l'étape suivante 
                If Jeux = #QuizQuestion And Not IsThread(Thread)
                  Thread = CreateThread(@PassageQuestion(),0)
                ElseIf Jeux = #QuizMusique And Not IsThread(Thread)
                  Thread = CreateThread(@PassageMusique(),0)    
                ElseIf Jeux = #QuizFilm  And Not IsThread(Thread)
                  Thread = CreateThread(@PassageVideo(),0) 
                EndIf 
              EndIf 
              
              ;- Stratégies
            ElseIf Left(RequestedFile, 7) = "Pieges=" 
              If Right(RequestedFile,1) = "2" ; Point X2              
                ParaJoueur(ID_Utilisateur)\NbrPointX2 = ParaJoueur(ID_Utilisateur)\NbrPointX2 -1
                ParaJoueur(ID_Utilisateur)\TypeAttaque = 2
                EnvoieData(ClientID, Index)
                
              ElseIf Right(RequestedFile,1) = "3" ; Block
                ParaJoueur(ID_Utilisateur)\NbrBlock = ParaJoueur(ID_Utilisateur)\NbrBlock -1
                ParaJoueur(ID_Utilisateur)\TypeAttaque = 3
                Html.s = ListeJoueurs 
                For Bi = 0 To nbrJoueur
                  If GetClientIP(ClientID) <> ParaJoueur(Bi)\ID 
                    Html.s = Html + ~"<button onclick=\"window.location.href = 'IDJoueurB=" +ParaJoueur(Bi)\ID+ "';"+Chr(34)+">"+ParaJoueur(Bi)\Nom+"</button>"
                  EndIf 
                Next Bi
                html.s = html+  ~"</div>"+
                         ~"</body></html>"
                EnvoieData(ClientID, Html)
                
              ElseIf Right(RequestedFile,1) = "4" ; Voleur
                ParaJoueur(ID_Utilisateur)\TypeAttaque = 4
                ParaJoueur(ID_Utilisateur)\NbrVoleur = ParaJoueur(ID_Utilisateur)\NbrVoleur -1
                Html.s = ListeJoueurs
                For Vi = 0 To nbrJoueur
                  If GetClientIP(ClientID) <> ParaJoueur(Vi)\ID
                    Html.s = Html + ~"<button onclick=\"window.location.href = 'IDJoueurV="+ParaJoueur(Vi)\ID+"';"+Chr(34)+">"+ParaJoueur(Vi)\Nom+"</button>"
                  EndIf 
                Next Vi
                html.s = html+  ~"</div>"+
                         ~"</body></html>"  
                EnvoieData(ClientID, Html)
                
              Else ;Rien
                ParaJoueur(ID_Utilisateur)\TypeAttaque = 1
                EnvoieData(ClientID, Index)
              EndIf 
              
              ;- Joueur piègé  
            ElseIf Left(RequestedFile, 10) = "IDJoueurB="
              Nom_Attaquant.s = ParaJoueur(ID_Utilisateur)\Nom
              ID_Joueur_Attaque.i = GetIDClient(Val(URLDecoder(StringField(StringField(Buffer, 2, "IDJoueurB="),1," "))))
              If ParaJoueur(ID_Joueur_Attaque)\Attaqueur_Voleur = "" And ParaJoueur(ID_Joueur_Attaque)\Attaqueur_Block = ""
                ParaJoueur(ID_Joueur_Attaque)\Attaqueur_Block = Nom_Attaquant  
              Else
                ParaJoueur(ID_Utilisateur)\NbrBlock = ParaJoueur(ID_Utilisateur)\NbrBlock +1
                ParaJoueur(ID_Utilisateur)\TypeAttaque = 1
              EndIf 
              EnvoieData(ClientID, Index)
              
              
            ElseIf Left(RequestedFile, 10) = "IDJoueurV="    
              Nom_Attaquant.s = ParaJoueur(ID_Utilisateur)\Nom
              ID_Joueur_Attaque.i = GetIDClient(Val(URLDecoder(StringField(StringField(Buffer, 2, "IDJoueurV="),1," "))))
              
              If ParaJoueur(ID_Joueur_Attaque)\Attaqueur_Voleur = "" And ParaJoueur(ID_Joueur_Attaque)\Attaqueur_Block = ""
                ParaJoueur(ID_Joueur_Attaque)\Attaqueur_Voleur = Nom_Attaquant  
              Else
                ParaJoueur(ID_Utilisateur)\NbrVoleur = ParaJoueur(ID_Utilisateur)\NbrVoleur +1
                ParaJoueur(ID_Utilisateur)\TypeAttaque = 1
              EndIf 
              EnvoieData(ClientID, Index)
              
              ;-Rechercher de nouveau joueur
            Else
              If Not FindString(Donnee_Joueur, Str(GetClientIP(ClientID)))                
                EnvoieData(ClientID, Nouveau_Joueur)
                
              Else ;Index.html
                If Jeux = #QuizFilm And ParaJoueur(ID_Utilisateur)\Reponse = #True
                  Html.s = Patiente2
                ElseIf Jeux = #QuizQuestion Or Jeux = #QuizMusique Or Jeux = #QuizFilm
                  Html.s = Index             
                ElseIf Jeux = #QuizScore And nbrJoueur >= 1
                  If NbrPartie >= NbrPartieJouer + 1
                    PagePiege = #False
                    Html.s = Pieges
                    If ParaJoueur(ID_Utilisateur)\NbrPointX2 > 0
                      html.s = html+ ~"<button onclick=\"window.location.href = 'Pieges=2';\">Point X2 (x"+Str(ParaJoueur(ID_Utilisateur)\NbrPointX2)+")</button>"
                      PagePiege = #True
                    EndIf
                    If ParaJoueur(ID_Utilisateur)\NbrBlock > 0
                      html.s = html+ ~"<button onclick=\"window.location.href = 'Pieges=3';\">Block (x"+Str(ParaJoueur(ID_Utilisateur)\NbrBlock)+")</button>"
                      PagePiege = #True
                    EndIf 
                    If ParaJoueur(ID_Utilisateur)\NbrVoleur > 0
                      html.s = html+ ~"<button onclick=\"window.location.href = 'Pieges=4';\">Voleur (x"+Str(ParaJoueur(ID_Utilisateur)\NbrVoleur)+")</button>"
                      PagePiege = #True
                    EndIf 
                    html.s = html+  ~"</div>"+
                             ~"</body></html>"    
                    If PagePiege = #False
                      html.s = Index
                    EndIf
                  Else 
                    Html.s = Fin
                  EndIf 
                Else
                  Html.s = Patiente
                EndIf 
                EnvoieData(ClientID, Html)
              EndIf 
            EndIf 
            
            ;- Enregistrement Joueur   
          ElseIf Left(Buffer, 4) = "POST"
            nbrJoueur +1
            ReDim ParaJoueur.Joueur(nbrJoueur)
            Nom.s = URLDecoder(StringField(Buffer, 2, "nom="))
            ParaJoueur(nbrJoueur)\Id = GetClientIP(ClientID)
            ParaJoueur(nbrJoueur)\Nom = ReplaceString(Nom, "+", " ")
            ParaJoueur(nbrJoueur)\Reponse = #False
            ParaJoueur(nbrJoueur)\Couleur = RGBA(Random(255,10),Random(255,10),Random(255,10),255)
            ParaJoueur(nbrJoueur)\NbrPointX2 = NbrPointX2
            ParaJoueur(nbrJoueur)\NbrBlock = NbrBlock
            ParaJoueur(nbrJoueur)\NbrVoleur = NbrVoleur
            ParaJoueur(nbrJoueur)\TypeAttaque = 1
            ParaJoueur(nbrJoueur)\Point = 0
            Donnee_Joueur.s = Donnee_Joueur.s + Str(nbrJoueur)+ "="+ Str(ParaJoueur(nbrJoueur)\ID) +";"        
            EnvoieData(ClientID, Patiente)        
            PageAccueil(#True,img) ;Mise a jour de la page d'accueil
          EndIf 
          
      EndSelect
    EndIf
    
  ForEver
EndProcedure
Avatar de l’utilisateur
Noos88260
Messages : 8
Inscription : dim. 04/janv./2026 9:02
Localisation : FRANCE

Re: Quiz

Message par Noos88260 »

Global.pbi

Code : Tout sélectionner


Global Title.s = "Quiz"
Global Hauteur_Voix.s
Global File.s, FmodSystem.i, Channel.i, Sound.i, lenght.i
Global Theme.s,  Question.s, BonRep.s, Wiki.s,  Media.s, Prop1.s, Prop2.s, Prop3.s, Prop4.s, BonSelection.s ,Anecdote.s
Global Genre.s, Annee.s, Titre.s, Titre1.s, Titre2.s, Titre3.s, Titre4.s, Chanteur.s, Chanteur1.s, Chanteur2.s, Chanteur3.s, Chanteur4.s, BonSelection1.s
Global FinMediaSon = #False
Global Largeur.i, Hauteur.i
Global AdresseIPJeux.s
Global Source.s = GetCurrentDirectory()
Global nbrJoueur.i = -1, FinReponse.i, JoueurBonneReponse.i, nbrBonReponse.i
Global Jeux.i, NbrPartieJouer.i, NbrPartie.i
Global NbrPartie.i, NivQuestion.i, MTous_type.i, VTous_type.i, NbrPointX2.i, NbrBlock.i, NbrVoleur.i
Global MediaFilm.s
Global CurrentPos
Global Index.s, Go.s, Go2.s, DelayUp.s, Script5secondes.s, Bonne_reponse.s, Mauvaise_reponse.s, Nouveau_Joueur.s, Patiente.s, Patiente2.s, ListeJoueurs.s, Pieges.s, Fin.s ,img
Global Donnee_Joueur.s
Global Decompte.i = #True

Global Dim NumQuestion(0)
Global Dim NumMusique(0)
Global Dim NumVideo(0)
Enumeration.pbi

Code : Tout sélectionner

Enumeration
  #Titre
  #Window
  #Image
  #ImageFont
  #Gadget
  #Font
  #Police
  #Serveur
  #Fichier
  #BaseDeDonnees
  #Entree
  #Espace
  #Echap
  #Video
  #Media
  #MediaMusique
  #MediaVideo
  #Score
  #Movie
EndEnumeration

Enumeration Jeux
  #Enregistrement
  #Explication
  #QuizQuestion
  #QuizMusique
  #QuizFilm
  #QuizScore
EndEnumeration
Structure.pbi

Code : Tout sélectionner

Structure Musique
  File.s
EndStructure

Structure Joueur
  ID.i            ;Identifiant réseau
  Nom.s           ;Nom du joueur
  Point.i         ;Nombre de point accumulé
  Reponse.i       ;Réponse répondu? oui = True non = False
  Couleur.q       ;Couleur attribué pour le joueur
  Etape.i         ;Etape des questions
  ReponseOK.i     ;Bonne réponse? oui = True non = False
  ScoreQuestion.i ;Score Question
  ScoreMusique.i  ;Scrore Musique
  ScoreVideo.i    ;Scrore Video
  NbrPointX2.i    ;Nombre d'aide point x2
  NbrBlock.i      ;Nombre d'aide Block
  NbrVoleur.i     ;Nombre d'aide voleur
  TypeAttaque.i   ;1=Rien 2=PointX2 3=Block 4=Voleur
  Attaqueur_Block.s
  Attaqueur_Voleur.s ;Attaque joueur
  Nbr_Block.i
  Nbr_Vol.i
EndStructure

Global Dim ParaJoueur.Joueur(0)
Global Dim CopieParaJoueur.Joueur(0)

Global NewList Proposition.s()
Global NewList Proposition2.s()
Avatar de l’utilisateur
Noos88260
Messages : 8
Inscription : dim. 04/janv./2026 9:02
Localisation : FRANCE

Re: Quiz

Message par Noos88260 »

Sapi-all.pbi

Code : Tout sélectionner


;sapi-all.pbi
;see here: https://www.purebasic.fr/english/viewtopic.php?t=71402

;{ ;Version history
;}
;V1.00: first distribution version [12.01.2025]
;V1.01: voice procedures added [12.01.2025]
;V1.02: own usermessage number added [12.01.2025]
;V1.03: sapi_SetSpeed & sapi_SetVolume added [12.01.2025]
;V1.04: sapi_IsVoiceRunning & sapi_IsVoicePaused added [13.01.2025]
;V1.05: errorhandling for sapi_SetVoice implemented [18.01.2025]
;V1.06: UserMessages for speech start & stop implemented [18.01.2025]
;V1.07: switched to alternative voice source [18.01.2025]
;V1.08: Windows XP voices added (Sam, Mike, Mary) [18.01.2025]
;V1.09: processing of bookmarks added [19.01.2025]
;V1.10: #SPEI_WORD_BOUNDARY event added [19.01.2025]

;{ ;sapi.pbi
#SPCAT_VOICES1 = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices"
#SPCAT_VOICES2 = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech_OneCore\Voices"

;- enum SPCFGRULEATTRIBUTES
#SPRAF_TopLevel	= 1 << 0
#SPRAF_Active	= 1 << 1
#SPRAF_Export	= 1 << 2
#SPRAF_Import	= 1 << 3
#SPRAF_Interpreter	= 1 << 4
#SPRAF_Dynamic	= 1 << 5
#SPRAF_AutoPause	= 1 << 16

;- enum SPGRAMMARWORDTYPE
#SPWT_DISPLAY	= 0
#SPWT_LEXICAL	= #SPWT_DISPLAY + 1
#SPWT_PRONUNCIATION	= #SPWT_LEXICAL + 1

;- enum SPEVENTENUM
#SPEI_UNDEFINED	= 0
#SPEI_START_INPUT_STREAM	= 1
#SPEI_END_INPUT_STREAM	= 2
#SPEI_VOICE_CHANGE	= 3
#SPEI_TTS_BOOKMARK	= 4
#SPEI_WORD_BOUNDARY	= 5
#SPEI_PHONEME	= 6
#SPEI_SENTENCE_BOUNDARY	= 7
#SPEI_VISEME	= 8
#SPEI_TTS_AUDIO_LEVEL	= 9
#SPEI_TTS_PRIVATE	= 15
#SPEI_MIN_TTS	= 1
#SPEI_MAX_TTS	= 15
#SPEI_END_SR_STREAM	= 34
#SPEI_SOUND_START	= 35
#SPEI_SOUND_END	= 36
#SPEI_PHRASE_START	= 37
#SPEI_RECOGNITION	= 38
#SPEI_HYPOTHESIS	= 39
#SPEI_SR_BOOKMARK	= 40
#SPEI_PROPERTY_NUM_CHANGE	= 41
#SPEI_PROPERTY_STRING_CHANGE	= 42
#SPEI_FALSE_RECOGNITION	= 43
#SPEI_INTERFERENCE	= 44
#SPEI_REQUEST_UI	= 45
#SPEI_RECO_STATE_CHANGE	= 46
#SPEI_ADAPTATION	= 47
#SPEI_START_SR_STREAM	= 48
#SPEI_RECO_OTHER_CONTEXT	= 49
#SPEI_SR_AUDIO_LEVEL	= 50
#SPEI_SR_PRIVATE	= 52
#SPEI_MIN_SR	= 34
#SPEI_MAX_SR	= 52
#SPEI_RESERVED1	= 30
#SPEI_RESERVED2	= 33
#SPEI_RESERVED3	= 63

#SPFEI_FLAGCHECK = ((1 << #SPEI_RESERVED1) | (1 << #SPEI_RESERVED2) )
#SPFEI_ALL_TTS_EVENTS = ($000000000000FFFE | #SPFEI_FLAGCHECK) 
#SPFEI_ALL_SR_EVENTS = ($001FFFFC00000000 | #SPFEI_FLAGCHECK)
#SPFEI_ALL_EVENTS = $EFFFFFFFFFFFFFFF
Macro SPFEI(SPEI_ord) : ((1 << SPEI_ord) | #SPFEI_FLAGCHECK) : EndMacro 

;- enum SPRULESTATE
#SPRS_INACTIVE	= 0
#SPRS_ACTIVE	= 1
#SPRS_ACTIVE_WITH_AUTO_PAUSE	= 3

;enum SPRUNSTATE
#SPRS_DONE = 1 << 0
#SPRS_IS_SPEAKING = 1 << 1

;- enum SPPHRASERNG
#SPPR_ALL_ELEMENTS	= -1

#SP_GETWHOLEPHRASE = #SPPR_ALL_ELEMENTS
#SPRR_ALL_ELEMENTS = #SPPR_ALL_ELEMENTS

;- enum SPGRAMMARSTATE
#SPGS_ENABLED = 0
#SPGS_DISABLED = 1
#SPGS_EXCLUSIVE = 3

;- enum SPLOADOPTIONS
#SPLO_STATIC	= 0
#SPLO_DYNAMIC	= 1

;- enum SPEAKFLAGS
#SPF_DEFAULT	= 0
#SPF_ASYNC	= 1 << 0
#SPF_PURGEBEFORESPEAK	= 1 << 1
#SPF_IS_FILENAME	= 1 << 2
#SPF_IS_XML	= 1 << 3
#SPF_IS_NOT_XML	= 1 << 4
#SPF_PERSIST_XML	= 1 << 5
#SPF_NLP_SPEAK_PUNC	= 1 << 6
#SPF_NLP_MASK	= #SPF_NLP_SPEAK_PUNC
#SPF_VOICE_MASK	= #SPF_ASYNC | #SPF_PURGEBEFORESPEAK | #SPF_IS_FILENAME | #SPF_IS_XML | #SPF_IS_NOT_XML | #SPF_NLP_MASK | #SPF_PERSIST_XML
#SPF_UNUSED_FLAGS	= ~#SPF_VOICE_MASK

;- enum SPEVENTLPARAMTYPE
#SPET_LPARAM_IS_UNDEFINED	= 0
#SPET_LPARAM_IS_TOKEN	= #SPET_LPARAM_IS_UNDEFINED + 1
#SPET_LPARAM_IS_OBJECT	= #SPET_LPARAM_IS_TOKEN + 1
#SPET_LPARAM_IS_POINTER	= #SPET_LPARAM_IS_OBJECT + 1
#SPET_LPARAM_IS_STRING	= #SPET_LPARAM_IS_POINTER + 1

;- SPEVENT
Structure SPEVENT Align #PB_Structure_AlignC
  eEventId.w
  elParamType.w
  ulStreamNum.l
  ullAudioStreamOffset.q
  wParam.i
  lParam.i
EndStructure

;- SPVOICESTATUS
Structure SPVOICESTATUS Align #PB_Structure_AlignC
  ulCurrentStream.l
  ulLastStreamQueued.l
  hrLastResult.l
  dwRunningState.l
  ulInputWordPos.l
  ulInputWordLen.l
  ulInputSentPos.l
  ulInputSentLen.l
  lBookmarkId.l
  PhonemeId.a
  VisemeId.l
  dwReserved1.l
  dwReserved2.l
EndStructure

;- ISpProperties
Interface ISpProperties Extends IUnknown
  SetPropertyNum(name.s, value.l)
  GetPropertyNum(name.s, value.l)
  SetPropertyString(name.s, value.s)
  GetPropertyString(name.s, value.i)
EndInterface

;- ISpRecognizer
Interface ISpRecognizer Extends ISpProperties
  SetRecognizer(recognizer.i)
  GetRecognizer(recognizer.i)
  SetInput(input.i, AllowFormatChanges.l)
  GetInputObjectToken(token.i)
  GetInputStream(stream.i)
  CreateRecoContext(NewCtxt.i)
  GetRecoProfile(token.i)
  SetRecoProfile(token.i)
  IsSharedInstance()
  GetRecoState(state.i)
  SetRecoState(state.i)
  GetStatus(status.i)
  GetFormat(WaveFormatType.i, FormatId.i, CoMemWFEX.i)
  IsUISupported(TypeOfUI.s, ExtraData.i, ExtraData.l, Supported.l)
  DisplayUI(hwndParent.i, Title.s, TypeOfUI.s, ExtraData.i, ExtraData.l)
  EmulateRecognition(Phrase.i)
EndInterface

;- ISpNotifySource
Interface ISpNotifySource Extends IUnknown
  SetNotifySink(NotifySink.i)
  SetNotifyWindowMessage(hWnd.i, mdsg.l, wparam.i, lparam.i)
  SetNotifyCallbackFunction(Callback.i, wparam.i, lparam.i)
  SetNotifyCallbackInterface(SpCallback.i, wparam.i, lparam.i)
  SetNotifyWin32Event()
  WaitForNotifyEvent(Milliseconds.l)
  GetNotifyEventHandle()
EndInterface

;- ISpEventSource
Interface ISpEventSource Extends ISpNotifySource
  SetInterest(EventInterest.q, QueuedInterest.q)
  GetEvents(Count.l, EventArray.i, Fetched.i)
  GetInfo(info.i)
EndInterface

;- ISpRecoContext
Interface ISpRecoContext Extends ISpEventSource
  GetRecognizer(Recognizer.i)
  CreateGrammar(GrammarId.q, Grammar.i)
  GetStatus(Status.i)
  GetMaxAlternates(Alternates.i)
  SetMaxAlternates(Alternates.l)
  SetAudioOptions(options.l, AudioFormatId.i, WaveFormatEx.i)
  GetAudioOptions(Options.i, AudioFormatId.i, CoMemWFEX.i)
  DeserializeResult(SerializedResult.i, Result.i)
  Bookmark(Options.l, StreamPosition.q, lparamEvent.i)
  SetAdaptationData(AdaptationData.s, cch.l)
  Pause(Reserved.l)
  Resume(Reserved.l)
  SetVoice(pVoice.i, fAllowFormatChanges.l)
  GetVoice(ppVoice.i)
  SetVoicePurgeEvent(ullEventInterest.q)
  GetVoicePurgeEvent(pullEventInterest.i)
  SetContextState(eContextState.l)
  GetContextState(peContextState.i)
EndInterface

;- ISpGrammarBuilder
Interface ISpGrammarBuilder Extends IUnknown
  ResetGrammar(NewLanguage.w)
  GetRule(pszRuleName.s, dwRuleId.l, dwAttributes.l, fCreateIfNotExist.l, phInitialState.i)
  ClearRule(hState.i)
  CreateNewState(hState.i, phState.i)
  AddWordTransition(hFromState.i, hToState.i, psz.s, pszSeparators.s, eWordType.l, Weight.f, pPropInfo.i)
  AddRuleTransition(hFromState.i, hToState.i, hRule.i, Weight.f, pPropInfo.i)
  AddResource(hRuleState.i, pszResourceName.s, pszResourceValue.s)
  Commit(dwReserved.l)
EndInterface

;- ISpRecoGrammar
Interface ISpRecoGrammar Extends ISpGrammarBuilder
  GetGrammarId(pullGrammarId.i)
  GetRecoContext(ppRecoCtxt.i)
  LoadCmdFromFile(pszFileName, Options.l)
  LoadCmdFromObject(rcid.i, pszGrammarName.s, Options.l)
  LoadCmdFromResource(hModule.i, pszResourceName.s, pszResourceType.s, wLanguage.w, Options.l)
  LoadCmdFromMemory(pGrammar.i, Options.l)
  LoadCmdFromProprietaryGrammar(rguidParam.i, pszStringParam.s, pvDataPrarm.i, cbDataSize.l, Options.l)
  SetRuleState(pszName.s, pReserved.i, NewState.l)
  SetRuleIdState(ulRuleId.l, NewState.l)
  LoadDictation(pszTopicName.s, Options.l)
  UnloadDictation()
  SetDictationState(NewState.l)
  SetWordSequenceData(pText.s, cchText.l, pInfo.i)
  SetTextSelection(pInfo.i)
  IsPronounceable(pszWord.s, pWordPronounceable.i)
  SetGrammarState(eGrammarState.l)
  SaveCmd(pStream.i, ppszCoMemErrorText.i)
  GetGrammarState(peGrammarState.i)
EndInterface

;- ISpPhrase
Interface ISpPhrase Extends IUnknown
  GetPhrase(ppCoMemPhrase.i)
  GetSerializedPhrase(ppCoMemPhrase.i)
  GetText(ulStart.l, ulCount.l, fUseTextReplacements.l, ppszCoMemText.i, pbDisplayAttributes.i)
  Discard(dwValueTypes.l)
EndInterface

;- ISpRecoResult
Interface ISpRecoResult Extends ISpPhrase
  GetResultTimes(pTimes.i)
  GetAlternates(ulStartElement.l, cElements.l, ulRequestCount.l, ppPhrases.i, pcPhrasesReturned.i)
  GetAudio(ulStartElement.l, cElements.l, ppStream.i)
  SpeakAudio(ulStartElement.l, cElements.l, dwFlags.l, pulStreamNumber.i)
  Serialize(ppCoMemSerializedResult.i)
  ScaleAudio(pAudioFormatId.i, pWaveFormatEx.i)
  GetRecoContext(ppRecoContext.i)
EndInterface

;- enum SPVPRIORITY
#SPVPRI_NORMAL	= 0
#SPVPRI_ALERT	= 1 << 0
#SPVPRI_OVER	= 1 << 1

#CLSID_SpVoice$ = "{96749377-3391-11D2-9EE3-00C04F797396}"
#IID_ISpVoice$ = "{6C44DF74-72B9-4992-A1EC-EF996E0422D4}"

;- ISpVoice
Interface ISpVoice Extends ISpEventSource
  SetOutput(pUnkOutput.i, fAllowFormatChanges.l)
  GetOutputObjectToken(ppObjectToken.i)
  GetOutputStream(ppStream.i)
  Pause()
  Resume()
  SetVoice(pToken.i)
  GetVoice(ppToken.i)
  Speak(pwcs.s, dwFlags.l, pulStreamNumber.i)
  SpeakStream(pStream.i, dwFlags.l, pulStreamNumber.i)
  GetStatus(pStatus.i, ppszLastBookmark.i)
  Skip(pItemType.s, lNumItems.l, pulNumSkipped.i)
  SetPriority(ePriority.l)
  GetPriority(pePriority.i)
  SetAlertBoundary(eBoundary.l)
  GetAlertBoundary(peBoundary.i)
  SetRate(RateAdjust.l)
  GetRate(pRateAdjust.i)
  SetVolume(usVolume.w)
  GetVolume(pusVolume.i)
  WaitUntilDone(msTimeout.l)
  SetSyncSpeakTimeout(msTimeout.l)
  GetSyncSpeakTimeout(pmsTimeout.i)
  SpeakCompleteEvent()
  IsUISupported(pszTypeOfUI.s, pvExtraData.i, cbExtraData.l, pfSupported.i)
  DisplayUI(hwndParent.i, pszTitle.s, pszTypeOfUI.s, pvExtraData.i, cbExtraData.l)                                                   
EndInterface

;- IEnumSpObjectTokens
Interface IEnumSpObjectTokens Extends IUnknown
Next(celt.l, pelt.i, pceltFetched.i)
Skip(celt.l)
Reset()
Clone(ppEnum.i)
Item(Index.l, ppToken.i)
GetCount(pCount.i)           
EndInterface

;- ISpDataKey
Interface ISpDataKey Extends IUnknown
  SetData(pszValueName.s, cbData.l, pData.i)
  GetData(pszValueName.s, pcbData.i, pData.i)
  SetStringValue(pszValueName.s, pszValue.s)
  GetStringValue(pszValueName.s, ppszValue.i)
  SetDWORD(pszValueName.s, dwValue.l)
  GetDWORD(pszValueName.s, pdwValue.i)
  OpenKey(pszSubKeyName.s, ppSubKey.i)
  CreateKey(pszSubKey.s, ppSubKey.i)
  DeleteKey(pszSubKey.s)
  DeleteValue(pszValueName.s)
  EnumKeys(Index.l, ppszSubKeyName.i)
  EnumValues(Index.l, ppszValueName.i)                                 
EndInterface

;- enum SPDATAKEYLOCATION
#SPDKL_DefaultLocation	= 0
#SPDKL_CurrentUser	= 1
#SPDKL_LocalMachine	= 2
#SPDKL_CurrentConfig	= 5

#CLSID_SpObjectTokenCategory$ = "{A910187F-0C7A-45AC-92CC-59EDAFB77B53}"
#IID_ISpObjectTokenCategory$ = "{2D3D3845-39AF-4850-BBF9-40B49780011D}"

;- ISpObjectTokenCategory
Interface ISpObjectTokenCategory Extends ISpDataKey
  SetId(pszCategoryId.s, fCreateIfNotExist.l)
  GetId(ppszCoMemCategoryId.i)
  GetDataKey(spdkl.l, ppDataKey.i)
  EnumTokens(pzsReqAttribs.s, pszOptAttribs.s, ppEnum.i)
  SetDefaultTokenId(pszTokenId.s)
  GetDefaultTokenId(ppszCoMemTokenId.i)          
EndInterface

;- ISpObjectToken
Interface ISpObjectToken Extends ISpDataKey
  SetId(pszCategoryId.s, pszTokenId.s, fCreateIfNotExist.l)
  GetId(ppszCoMemTokenId.i)
  GetCategory(ppTokenCategory.i)
  CreateInstance(pUnkOuter.i, dwClsContext.l, riid.i, ppvObject.i)
  GetStorageFileName(clsidCaller.i, pszValueName.s, pszFileNameSpecifier.s, nFolder.l, ppszFilePath.i)
  RemoveStorageFileName(clsidCaller.i, pszKeyName.s, fDeleteFile.l)
  Remove(pclsidCaller.i)
  IsUISupported(pszTypeOfUI.s, pvExtraData.i, cbExtraData.l, punkObject.i, pfSupported.i)
  DisplayUI(hwndParent.i, pszTitle.s, pszTypeOfUI.s, pvExtraData.i, cbExtraData.l, punkObject.i)
  MatchesAttributes(pszAttributes.s, pfMatches.i)
EndInterface
;}
;{ ;sapihelper.pbi
Declare SpEnumTokens(pszCategoryId.s, pszReqAttribs.s, pszOptAttribs.s, ppEnum.i)
Declare SpGetCategoryFromId(pszCategoryId.s, ppCategory.ISpObjectTokenCategory, fCreateIfNotExist.l = #False)

Procedure SpEnumTokens(pszCategoryId.s, pszReqAttribs.s, pszOptAttribs.s, *ppEnum.INTEGER)
  Define.l hr
  Define.ISpObjectTokenCategory tokenCategory
  
  hr = SpGetCategoryFromId(pszCategoryId, @tokenCategory)
  If hr = #S_OK
    hr = tokenCategory\EnumTokens(pszReqAttribs, pszOptAttribs, *ppEnum)
  EndIf
  
  ProcedureReturn hr
EndProcedure

Procedure SpGetCategoryFromId(pszCategoryId.s, *ppCategory.INTEGER, fCreateIfNotExist.l = #False)
  Define.IID CLSID_SpObjectTokenCategory
  Define.IID IID_ISpObjectTokenCategory
  Define.ISpObjectTokenCategory tokenCategory
  Define.l hr
  Define.i test
  
  IIDFromString_(#CLSID_SpObjectTokenCategory$, @CLSID_SpObjectTokenCategory)
  IIDFromString_(#IID_ISpObjectTokenCategory$, @IID_ISpObjectTokenCategory)
  
  hr = CoCreateInstance_(@CLSID_SpObjectTokenCategory, #Null, #CLSCTX_INPROC_SERVER, @IID_ISpObjectTokenCategory, @tokenCategory)
  If hr = #S_OK
    hr = tokenCategory\SetId(pszCategoryId, fCreateIfNotExist)
    If hr = #S_OK
      *ppCategory\i = tokenCategory
      
    Else
      tokenCategory\Release()
    EndIf 
  EndIf 
  
  ProcedureReturn hr
EndProcedure

Procedure SpClearEvent(*pe.SPEVENT)
  Protected.IUnknown pUnk
  
  If *pe\elParamType <> #SPEI_UNDEFINED
    If *pe\elParamType = #SPET_LPARAM_IS_POINTER Or *pe\elParamType = #SPET_LPARAM_IS_STRING
      CoTaskMemFree_(*pe\lParam)
      
    ElseIf *pe\elParamType = #SPET_LPARAM_IS_TOKEN Or *pe\elParamType = #SPET_LPARAM_IS_OBJECT
      pUnk = *pe\lParam
      pUnk\Release()
    EndIf 
  EndIf 
  
  FillMemory(*pe, 0, SizeOf(SPEVENT))
EndProcedure
;}

Declare sapi_Stop()

Global _sapi_cbVoices.i,_sapi_iVoice.i,_sapi_cpEnum.IEnumSpObjectTokens,_sapi_voiceToken.ISpObjectToken
Global _sapi_CLSID_SpVoice.IID,_sapi_IID_ISpVoice.IID,_sapi_pVoice.ISpVoice,_sapi_hr.l,_sapi_voiceId.i
Global _sapi_isVoiceRunning.b,_sapi_isVoicePaused.b,_sapi_BookmarkReached$
Global _sapi_addr_DefSubclassProc.i,_sapi_addr_SetWindowSubclass.i,_sapi_addr_RemoveWindowSubclass.i,_Comctl32.i
Global _sapi_initialized.b=0,_sapi_hMainWnd.i,_sapi_InternalUserMess.i,_sapi_UserMessStart.i,_sapi_UserMessStop.i,_sapi_UserMessBookmarkReached.i,_sapi_UserMessWordBoundary.i
Global _sapi_CurrentWordLen.l,_sapi_CurrentWordPos.l,_sapi_CurrentText$

Procedure sapi_SubclassProc(hWnd.i,uMsg.i,wParam.i,lParam.i,uIdSubclass.i,dwRefData.i)
  Protected erg,ret
  Protected eventItem.SPEVENT
  erg=999 ;if kept =999 the original window procedure will be called at the end, otherwise not
  If uMsg=_sapi_InternalUserMess
    While _sapi_pVoice\GetEvents(1, @eventItem, #Null) = #S_OK
      Select eventItem\eEventId 
        Case #SPEI_START_INPUT_STREAM
          _sapi_isVoiceRunning = #True
          _sapi_BookmarkReached$=""
          If _sapi_UserMessStart<>0
            SendMessage_(_sapi_hMainWnd,_sapi_UserMessStart,0,0)
          EndIf
          Break
        Case #SPEI_END_INPUT_STREAM
          _sapi_isVoiceRunning = #False
          _sapi_BookmarkReached$=""
          If _sapi_isVoicePaused
            _sapi_pVoice\Resume()
            _sapi_isVoicePaused = #False
          EndIf
          If _sapi_UserMessStop<>0
            SendMessage_(_sapi_hMainWnd,_sapi_UserMessStop,0,0)
          EndIf
          Break
        Case #SPEI_TTS_BOOKMARK ;e.g. »<bookmark mark="bookmark_one"/>« in the text
          If eventItem\elParamType=#SPET_LPARAM_IS_STRING
            _sapi_BookmarkReached$=PeekS(eventItem\lParam) ;PeekS(PeekI(lParam),-1)
          Else
            _sapi_BookmarkReached$=Str(PeekL(eventItem\wParam))
          EndIf
          If _sapi_UserMessBookmarkReached<>0
            SendMessage_(_sapi_hMainWnd,_sapi_UserMessBookmarkReached,0,0)
          EndIf
          Break
        Case #SPEI_WORD_BOUNDARY
          _sapi_CurrentWordLen=eventItem\wParam
          _sapi_CurrentWordPos=eventItem\lParam
          If _sapi_UserMessWordBoundary<>0
            SendMessage_(_sapi_hMainWnd,_sapi_UserMessWordBoundary,_sapi_CurrentWordPos,_sapi_CurrentWordLen)
          EndIf
      EndSelect
    Wend 
    SpClearEvent(@eventItem)
  EndIf
  ;{ ;return value, call original window procedure if appropriate
  If erg=999 ;call original window procedure
    ProcedureReturn CallFunctionFast(_sapi_addr_DefSubclassProc,hWnd,uMsg,wParam,lParam)
  Else ;return special value and *do not* call original window procedure
    ProcedureReturn erg
  EndIf
  ;}
EndProcedure ;sapi_SubClassProc

Procedure sapi_Init(hMainWnd.i,UserMessStart.i=0,UserMessStop.i=0,UserMessBookmarkReached.i=0,UserMessWordBoundary.i=0,InternalUserMess.i=#WM_USER) ;call once at the beginning, supply ID (MS-Windows handle) of main program window
  Protected ret.l,err.l
  ret=1
  err=0
  If _sapi_initialized=0
    _sapi_hMainWnd=hMainWnd
    _sapi_InternalUserMess=InternalUserMess
    _sapi_UserMessStart=UserMessStart
    _sapi_UserMessStop=UserMessStop
    _sapi_UserMessBookmarkReached=UserMessBookmarkReached
    _sapi_UserMessWordBoundary=UserMessWordBoundary
    _sapi_isVoiceRunning = #False
    _sapi_isVoicePaused = #False
    _sapi_BookmarkReached$=""
    ;{ ;COM-Init
    CoInitialize_(0)
    IIDFromString_(#CLSID_SpVoice$, @_sapi_CLSID_SpVoice)
    IIDFromString_(#IID_ISpVoice$, @_sapi_IID_ISpVoice)
    _sapi_hr = CoCreateInstance_(@_sapi_CLSID_SpVoice, #Null, #CLSCTX_INPROC_SERVER, @_sapi_IID_ISpVoice, @_sapi_pVoice)
    If _sapi_hr <> #S_OK
      ;Debug "Failed to create voice object"
      ;End
      ret=0
    Else
      _Comctl32=OpenLibrary(#PB_Any,"Comctl32.dll") ;neccessary because the subclassing functions aren't included in PB with an underscore at their end
      _sapi_addr_DefSubclassProc=GetFunction(_Comctl32,"DefSubclassProc")
      _sapi_addr_SetWindowSubclass=GetFunction(_Comctl32,"SetWindowSubclass")
      _sapi_addr_RemoveWindowSubclass=GetFunction(_Comctl32,"RemoveWindowSubclass")
      _sapi_cbVoices=ComboBoxGadget(#PB_Any,-10,0,0,0)
      ;{ ;get voices
      If SpEnumTokens(#SPCAT_VOICES2, "", "", @_sapi_cpEnum) = #S_OK ;VOICES2 first, because normally they contain more entries than VOICES 1
        _sapi_iVoice = 0
        While _sapi_cpEnum\Next(1, @_sapi_voiceToken, #Null) = #S_OK
          If _sapi_voiceToken\GetId(@_sapi_voiceId) = #S_OK
            AddGadgetItem(_sapi_cbVoices, _sapi_iVoice, GetFilePart(PeekS(_sapi_voiceId)))
            SetGadgetItemData(_sapi_cbVoices, _sapi_iVoice, _sapi_voiceToken)
            ;messagebox_(0,str(_sapi_iVoice)+"   "+str(_sapi_voiceToken)+"   "+PeekS(_sapi_voiceId),"",0)
          EndIf 
          _sapi_iVoice + 1
        Wend 
        _sapi_cpEnum\Release()
        SetGadgetState(_sapi_cbVoices, 0)
      Else
        ;Debug "Failed to enumerate voices"
        ;End 
        ;err=err+1
      EndIf
      If CountGadgetItems(_sapi_cbVoices)=0
        ;err=err+1
        If SpEnumTokens(#SPCAT_VOICES1, "", "", @_sapi_cpEnum) = #S_OK	
          _sapi_iVoice = 0
          While _sapi_cpEnum\Next(1, @_sapi_voiceToken, #Null) = #S_OK
            If _sapi_voiceToken\GetId(@_sapi_voiceId) = #S_OK
              AddGadgetItem(_sapi_cbVoices, _sapi_iVoice, GetFilePart(PeekS(_sapi_voiceId)))
              SetGadgetItemData(_sapi_cbVoices, _sapi_iVoice, _sapi_voiceToken)
            EndIf 
            _sapi_iVoice + 1
          Wend 
          _sapi_cpEnum\Release()
          SetGadgetState(_sapi_cbVoices, 0)
        Else
          ;Debug "Failed to enumerate voices"
          ;End 
          ;err=err+1
        EndIf 
        If CountGadgetItems(_sapi_cbVoices)=0
          ret=-2
        EndIf
      Else ;add Windows XP voices if available (MSMike, MSSam, MSMary) --> see here (2nd reply!): https://answers.microsoft.com/en-us/windows/forum/all/how-to-get-microsoft-sam-on-windows-7/20b2beb4-e927-4be5-90d3-45c3af1bf2ce
        If SpEnumTokens(#SPCAT_VOICES1, "", "", @_sapi_cpEnum) = #S_OK
          _sapi_iVoice = 0
          While _sapi_cpEnum\Next(1, @_sapi_voiceToken, #Null) = #S_OK
            If _sapi_voiceToken\GetId(@_sapi_voiceId) = #S_OK
              If (UCase(GetFilePart(PeekS(_sapi_voiceId)))="MSMIKE") Or (UCase(GetFilePart(PeekS(_sapi_voiceId)))="MSSAM") Or (UCase(GetFilePart(PeekS(_sapi_voiceId)))="MSMARY")
                AddGadgetItem(_sapi_cbVoices, _sapi_iVoice, GetFilePart(PeekS(_sapi_voiceId)))
                SetGadgetItemData(_sapi_cbVoices, _sapi_iVoice, _sapi_voiceToken)
              EndIf
            EndIf 
            _sapi_iVoice + 1
          Wend 
          _sapi_cpEnum\Release()
          SetGadgetState(_sapi_cbVoices, 0)
        Else
          ;Debug "Failed to enumerate voices"
          ;End 
          ;err=err+1
        EndIf
      EndIf
      ;}
    EndIf
    ;}
  Else
    ret=-1 ;already initialized
  EndIf
  If (ret=1) Or (ret=-2)
    CallFunctionFast(_sapi_addr_SetWindowSubclass,hMainWnd,@sapi_SubclassProc(),1,0)
    _sapi_pVoice\SetInterest(#SPFEI_ALL_EVENTS, #SPFEI_ALL_EVENTS)
    _sapi_pVoice\SetNotifyWindowMessage(hMainWnd, _sapi_InternalUsermess, 0, 0 )
    _sapi_initialized=1
  EndIf
  ProcedureReturn ret
EndProcedure ;sapi_Init

Procedure sapi_DeInit() ;call once at the end
  Protected iVoice.l,erg.l
  erg=1
  If _sapi_initialized
    If _sapi_isVoiceRunning
      sapi_Stop()
    EndIf
    ;{ ;release voices
    For iVoice = 0 To CountGadgetItems(_sapi_cbVoices) - 1
      _sapi_voiceToken = GetGadgetItemData(_sapi_cbVoices, iVoice)
      If _sapi_voiceToken
        _sapi_voiceToken\Release()
      EndIf 
    Next 
    If _sapi_pVoice : _sapi_pVoice\Release() : EndIf 
    ;}
    CallFunctionFast(_sapi_addr_RemoveWindowSubclass,_sapi_hMainWnd,@sapi_SubclassProc(),1)
    CloseLibrary(_Comctl32)
    If _sapi_cbVoices
      FreeGadget(_sapi_cbVoices)
      _sapi_cbVoices=0
    EndIf
    _sapi_initialized=0
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_DeInit

Procedure sapi_Say(Text$)
  Protected erg.i
  erg=0
  If _sapi_initialized
    _sapi_CurrentText$=Text$
    _sapi_CurrentWordPos=0
    _sapi_CurrentWordLen=0
    If _sapi_isVoiceRunning = #False
      erg=_sapi_pVoice\Speak(Text$, #SPF_IS_XML | #SPF_ASYNC, #Null)
      If erg=0
        erg=1
      Else
        erg=0
      EndIf
      _sapi_BookmarkReached$=""
      _sapi_isVoiceRunning=#True
    Else ;If _sapi_isVoicePaused = #True
         ;{ ;original logic (resume)
         ;erg=_sapi_pVoice\Resume()
         ;_sapi_isVoicePaused = #False
         ;}
      sapi_Stop()
      erg=_sapi_pVoice\Speak(Text$, #SPF_IS_XML | #SPF_ASYNC, #Null)
      If erg=0
        erg=1
      Else
        erg=0
      EndIf
      _sapi_BookmarkReached$=""
      _sapi_isVoiceRunning=#True
      _sapi_isVoicePaused=#False
    EndIf
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_Say

Procedure sapi_Pause()
  Protected erg.i
  erg=0
  If _sapi_initialized
    If (_sapi_isVoiceRunning = #True) And (_sapi_isVoicePaused = #False)
      erg=_sapi_pVoice\Pause()
      If erg=0
        erg=1
      Else
        erg=0
      EndIf
      _sapi_isVoicePaused = #True
    EndIf 
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_Pause

Procedure sapi_Resume()
  Protected erg.i
  erg=0
  If _sapi_initialized
    If (_sapi_isVoiceRunning = #True) And (_sapi_isVoicePaused = #True)
      erg=_sapi_pVoice\Resume()
      If erg=0
        erg=1
      Else
        erg=0
      EndIf
      _sapi_isVoicePaused = #False
    EndIf 
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_Resume

Procedure sapi_Stop()
  Protected erg.i
  Protected eventItem.SPEVENT
  erg=0
  If _sapi_initialized
    If _sapi_isVoiceRunning
      If _sapi_isVoicePaused
        sapi_Resume()
      EndIf
      erg=_sapi_pVoice\Speak("", #SPF_PURGEBEFORESPEAK, #Null)
      ;erg=_sapi_pVoice\Skip("Sentence", Len(_CurrentText$), #Null)
      If erg=0
        erg=1
      Else
        erg=0
      EndIf
      ;Alt method to stop
      ;app\pVoice\Skip("Sentence", Len(GetGadgetText(app\edText)), #Null)
      _sapi_isVoiceRunning=#False
      _sapi_isVoicePaused=#False
      _sapi_BookmarkReached$=""
      _sapi_CurrentWordPos=0
      _sapi_CurrentWordLen=0
      While _sapi_pVoice\GetEvents(1, @eventItem, #Null)=#S_OK ;purge all events that would otherwise be stuck in the loop until the next readout commences
      Wend
    EndIf 
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_Stop

Procedure.s sapi_GetVoiceNames() ;returns the names of all installed voices separated by "|"
  Protected erg$,i.l
  erg$=""
  If _sapi_initialized
    For i=0 To CountGadgetItems(_sapi_cbVoices)-1
      If erg$<>""
        erg$=erg$+"|"
      EndIf
      erg$=erg$+GetGadgetItemText(_sapi_cbVoices,i)
    Next i
  Else
    erg$="-1"
  EndIf
  ProcedureReturn erg$
EndProcedure ;sapi_GetVoiceNames

Procedure sapi_SetVoice(VoiceName$) ;VoiceName$=one of the names returned by sapi_GetVoiceNames()
  Protected erg.i,voiceToken.ISpObjectToken
  erg=0
  If _sapi_initialized
    If VoiceName$<>""
      SetGadgetText(_sapi_cbVoices,VoiceName$)
      voiceToken = GetGadgetItemData(_sapi_cbVoices, GetGadgetState(_sapi_cbVoices))
      If voiceToken
        _sapi_pVoice\SetVoice(voiceToken)
        erg=1
      EndIf 
    EndIf
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_SetVoice

Procedure sapi_SetSpeed(Speed.b=0) ;-10 to +10; default=0
  Protected erg.i
  erg=0
  If _sapi_initialized
    If (Speed>=-10) And (Speed<=10)
      erg=_sapi_pVoice\SetRate(Speed)
      erg=1-erg
    EndIf
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_SetSpeed

Procedure sapi_SetVolume(Volume.b=100) ;0 to 100; default=100
  Protected erg.i
  erg=0
  If _sapi_initialized
    If (Volume>=0) And (Volume<=100)
      erg=_sapi_pVoice\SetVolume(Volume)
      erg=1-erg
    EndIf
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_SetVolume

Procedure sapi_IsVoiceRunning() ;returns 1 if text is being read out (even if paused), 0 otherwise
  Protected erg.i
  erg=0
  If _sapi_initialized
    erg=_sapi_isVoiceRunning
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_IsVoiceRunning

Procedure sapi_IsVoicePaused() ;returns 1 if readout is paused, 0 otherwise
  Protected erg.i
  erg=0
  If _sapi_initialized
    erg=_sapi_isVoicePaused
  Else
    erg=-1
  EndIf
  ProcedureReturn erg
EndProcedure ;sapi_IsVoicePaused

Procedure.s sapi_GetLastBookmark() ;e.g. »<bookmark mark="bookmark_one"/>« in the text
  Protected erg$
  erg$=""
  If _sapi_initialized
    erg$=_sapi_BookmarkReached$
  Else
    erg$="-1"
  EndIf
  ProcedureReturn erg$
EndProcedure ;sapi_GetLastBookmark

Procedure sapi_GetCurrentWordPos(TakeChr13IntoAccount.i=0)
  Protected s$
  If TakeChr13IntoAccount
    s$=Left(_sapi_CurrentText$,_sapi_CurrentWordPos)
    ProcedureReturn _sapi_CurrentWordPos-CountString(s$,Chr(13))
  Else
    ProcedureReturn _sapi_CurrentWordPos
  EndIf
EndProcedure ;sapi_GetCurrentWordPos

Procedure sapi_GetCurrentWordLen()
  ProcedureReturn _sapi_CurrentWordLen
EndProcedure ;sapi_GetCurrentWordLen


; _s$=sapi_GetVoiceNames()
; For _i=1 To CountString(_s$,"|")+1
;  Debug StringField(_s$,_i,"|")
; Next _i
; 

Avatar de l’utilisateur
Noos88260
Messages : 8
Inscription : dim. 04/janv./2026 9:02
Localisation : FRANCE

Re: Quiz

Message par Noos88260 »

Bonne Journée et bonne fin de Week-end
Répondre