Background Transfert

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Background Transfert

Message par Droopy »

Ces procédures servent à transférer un fichier en arrière plan.

Afin de limiter le débit réseau / charge cpu
+ Auto Reprise où la copie en était si elle est stoppée.

Code : Tout sélectionner

; Droopy 07/05/05
; PureBasic 3.93


ProcedureDLL GetDiskFreeSpaceEx(Drive.s) ; Included in Droopy's Lib
  ; GetDiskFreeSpaceEx() Author = Freak
  
  Structure union
    LowPart.l
    HighPart.l
  EndStructure
  
  lpFreeBytesAvailable.union
  lpTotalNumberOfBytes.union
  lpTotalNumberOfFreeBytes.union
  
  GetDiskFreeSpaceEx_(@Drive,@lpFreeBytesAvailable,@lpTotalNumberOfBytes,@lpTotalNumberOfFreeBytes)
  
  ; LowPart contient 32 Bits 
  ; On décale à droite de 20 bits ( il reste 12 bits significatifs )
  ; Attention le décalage recopie le bit de signe !
  ; 20 bits --> /1024/1024 --> Résultat en Mo !!!
  
  lpTotalNumberOfFreeBytes\LowPart>>20 
  
  ; On nettoie le bit de signe recopié avec un masque ( de 12 bits bien sur )
  lpTotalNumberOfFreeBytes\LowPart & $FFF
  
  ; On décale HighPart de 12 à gauche
  lpTotalNumberOfFreeBytes\HighPart <<12
  
  ; Et on fusionne le tout avec un OU 
  ; La taille est en Mo
  ProcedureReturn lpTotalNumberOfFreeBytes\LowPart | lpTotalNumberOfFreeBytes\HighPart
  
EndProcedure

ProcedureDLL Timer(ProcedurePointer) ; Included in Droopy's Lib
  
  Static FlagTimer
  
  ; Create the LinkedList the first time !
  If FlagTimer=0
    NewList IdThreads() ; Store the ThreadId
    FlagTimer=1
  EndIf
  
  AddElement(IdThreads())
  LastElement(IdThreads())
  IdThreads()=CreateThread(ProcedurePointer,0)
  ProcedureReturn ListIndex(IdThreads())
EndProcedure

ProcedureDLL TimerKill(Id) ; Included in Droopy's Lib
  SelectElement(IdThreads(),Id)
  KillThread(IdThreads())
EndProcedure

;/ BackgroundTransfertInit(SourceFile.s,DestinationFile.s,PacketSize,Frequency)
; Initialise the Lib
; Return 1 if SourceFile Exist / Enought free space avalaible @ Target Destination

;/ BackgroundTransfertState()
; Return 0 if transfert not finished ; 1 when finished

;/ BackGroundTransfertStart()
; Start the Background Transfert

;/ BackGroundTransfertStop()
; Stop the Background Transfert

;/ BackGroundTransfertPercentage()
; Get the transfert state in percentage

;/ BackGroundTransfertVerify()
; When transfert finished, this function test if source = destination : 1 = true

Global BGTSource.s,BGTDestination.s,BGTTaillePaquets,BGTTempo,BGTFlag,BGTTimerId,BGTTailleDestination,BGTTailleSource

ProcedureDLL BackGroundTransfertStop()
  TimerKill(BGTTimerId)
EndProcedure

ProcedureDLL BackgroundTransfertInit(SourceFile.s,DestinationFile.s,PacketSize,Frequency)
  BGTSource=SourceFile
  BGTDestination=DestinationFile
  BGTTaillePaquets=PacketSize
  BGTTempo=Frequency
  BGTFlag=0
  retour=1
  
  
  If FileSize(BGTSource)=-1 
    retour=0 ; File does not exist
  Else
    ; Source file exist
    ; Test if there is enought space for file copy
    ResteACopier=FileSize(BGTSource)
    If FileSize(BGTDestination)>0 : ResteACopier-FileSize(BGTDestination):EndIf
    ResteACopier/1024/1024
    
    Drive.s=Left(BGTDestination,2)
    SpaceNeeded=GetDiskFreeSpaceEx(Drive)
    SpaceNeeded-ResteACopier
    
    If SpaceNeeded<=0 : retour=0 : EndIf 
  EndIf
  
  ProcedureReturn retour
EndProcedure

ProcedureDLL BackgroundTransfertState()
  ProcedureReturn BGTFlag
EndProcedure

Procedure BackgroundTransfertOnePacket()
  
  OpenFile(0,BGTSource)
  BGTTailleSource=Lof()
  OpenFile(1,BGTDestination.s)
  BGTTailleDestination=Lof()
  
  DebutCopie=BGTTailleDestination
  If DebutCopie=BGTTailleSource 
    BGTFlag=1 ; On a déjà tout copié on quitte
    CloseFile(1)
    CloseFile(0)
    BackGroundTransfertStop() ; Kill thread when finished
  Else
    
    FinCopie=DebutCopie+BGTTaillePaquets
    If FinCopie>BGTTailleSource : FinCopie=BGTTailleSource : EndIf
    
    OctetsALire=FinCopie-DebutCopie
    *Tampon=AllocateMemory(OctetsALire)
    
    UseFile(0)
    FileSeek(DebutCopie)
    ReadData(*Tampon,OctetsALire)
    
    UseFile(1)
    FileSeek(Lof())
    WriteData(*Tampon,OctetsALire)
    
    CloseFile(1)
    CloseFile(0)
    
  EndIf
  
  ProcedureReturn BGTFlag
  
EndProcedure

Procedure BackGroundTransfertTimer() ; Transfert en boucle des paquets = Timer
  Repeat
    Delay(BGTTempo)
    BackgroundTransfertOnePacket()
  ForEver
EndProcedure

ProcedureDLL BackGroundTransfertStart() ; Lance le transfert ( Lance le Timer )
  BGTTimerId=Timer(@BackGroundTransfertTimer())
EndProcedure

ProcedureDLL BackGroundTransfertPercentage()
  retour.f=(BGTTailleDestination/BGTTailleSource)*100
  If BGTFlag=1 : retour=100 : EndIf
  ProcedureReturn retour
EndProcedure

Procedure BackGroundTransfertVerify()
  If MD5FileFingerprint(BGTSource) = MD5FileFingerprint(BGTDestination) : retour=1 : EndIf
  ProcedureReturn retour
EndProcedure

;/ Test the Lib

; DeleteFile("c:\copie.msi") ; Restart the copy

retour=BackgroundTransfertInit("c:\Test.msi","c:\Copie.msi",16192,1)
If retour=0 : Beep_(400,500):End:EndIf

BackGroundTransfertStart()

OpenWindow(0,0,0,320,160,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Background Transfert") And CreateGadgetList(WindowID(0))
TextGadget       (0, 10, 10,250, 20, "0 %",#PB_Text_Center)
ProgressBarGadget(1, 10, 30,250, 30, 0,100,#PB_ProgressBar_Smooth )

Repeat
  Delay(10)
  SetGadgetState   (1, BackGroundTransfertPercentage())   ; set 1st progressbar (ID = 0) to 50 of 100
  SetGadgetText(0,Str(BackGroundTransfertPercentage())+"%")
Until WindowEvent()=#PB_Event_CloseWindow Or BackgroundTransfertState()

BackGroundTransfertStop()

If BackGroundTransfertVerify()
  MessageRequester("Background Transfert","Success")
Else
  MessageRequester("Background Transfert","Fail")
EndIf
[/code]