Run multi-thread SHA1 according to List file

Run multi-thread SHA1 according to List file
mail@pastecode.io avatar
unknown
c_cpp
9 days ago
11 kB
9
Indexable
Never
CompilerIf #PB_Compiler_Thread = 0
  CompilerWarning "Enable thread safe option!"
CompilerEndIf

EnableExplicit

Enumeration Window
  #WORKING_wind
EndEnumeration

Enumeration #PB_Event_FirstCustomValue
  #Event_SHA1
  #SHA1_Log
  #SHA1_Progress
  #SHA1_Validate
EndEnumeration

Enumeration Gadgets
  #Btn_get_SHA1
  #Btn_pause_resume
  #Btn_stop
  #Txt_Select
  #checkbox_file1
  #checkbox_file2
  #checkbox_file3
  #Txt_Clock
  #WORKING_WIND_ListView
  #WORKING_WIND_ProgressBar
EndEnumeration

#file1_path = "D:\my clip\clip1.mp4"
#file2_path = "D:\my clip\clip2.mp4"
#file3_path = "D:\my clip\clip3.mp4"

; TODO need change
#file1_sha1 = "sha1-sha1-sha1-sha1" ; need change
#file2_sha1 = "sha1-sha1-sha1-sha1" ; need change
#file3_sha1 = "sha1-sha1-sha1-sha1" ; need change

Structure udtThreadControl
  ThreadID.i
  UserID.i
  Signal.i
  Pause.i
  Exit.i
EndStructure

Procedure StartThread(*Data.udtThreadControl, *Procedure) ; ThreadID
  If Not IsThread(*Data\ThreadID)
    *Data\Exit = #False
    *Data\Pause = #False
    *Data\ThreadID = CreateThread(*Procedure, *Data)
  EndIf
  ProcedureReturn *Data\ThreadID
EndProcedure

Procedure StopThread(*Data.udtThreadControl, Wait = 1000) ; Void
  If IsThread(*Data\ThreadID)
    *Data\Exit = #True
    If *Data\Pause
      *Data\Pause = #False
      SignalSemaphore(*Data\Signal)
    EndIf
    If Wait
      If WaitThread(*Data\ThreadID, Wait) = 0
        KillThread(*Data\ThreadID)
      EndIf
      *Data\ThreadID = 0
      *Data\Pause = #False
      *Data\Exit = #False
      If *Data\Signal
        FreeSemaphore(*Data\Signal)
        *Data\Signal = 0
      EndIf
    EndIf
  EndIf
EndProcedure

Procedure FreeThread(*Data.udtThreadControl, Stop = #True, Wait = 1000) ; True or False
  If IsThread(*Data\ThreadID)
    If Stop
      StopThread(*Data, Wait)
      FreeStructure(*Data)
      ProcedureReturn #True
    Else
      ProcedureReturn #False
    EndIf
  Else
    If *Data\Signal
      FreeSemaphore(*Data\Signal)
    EndIf
    FreeStructure(*Data)
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ThreadPause(*Data.udtThreadControl) ; Void
  If IsThread(*Data\ThreadID)
    If Not *Data\Signal
      *Data\Signal = CreateSemaphore()
    EndIf
    If Not *Data\Pause
      *Data\Pause = #True
    EndIf
  EndIf
EndProcedure

Procedure ThreadResume(*Data.udtThreadControl) ; Void
  If IsThread(*Data\ThreadID)
    If *Data\Pause
      *Data\Pause = #False
      SignalSemaphore(*Data\Signal)
    EndIf
  EndIf
EndProcedure

Procedure AllocateString(String.s) ; Result = Pointer
  Protected *mem.string = AllocateStructure(String)
  If *mem
    *mem\s = String
  EndIf
  ProcedureReturn *mem
EndProcedure

Procedure.s FreeString(*mem.string) ; Result String
  Protected r1.s
  If *mem
    r1 = *mem\s
    FreeStructure(*mem)
  EndIf
  ProcedureReturn r1
EndProcedure

Structure struc_SHA1 Extends udtThreadControl
  Window.i
  Event.i
  List FilePath$()
  Sha1Out$
EndStructure

Procedure update_clock(ii)
  Repeat
    If IsWindow(#WORKING_wind)
      SetGadgetText(#Txt_Clock, FormatDate("%hh:%ii:%ss", Date()))
      Delay(500)
    Else
      Break
    EndIf
  ForEver
EndProcedure

Procedure Resize_mainWindow()
  Protected Window_0_WidthIni = 500, Window_0_HeightIni = 200
  Protected ScaleX.f, ScaleY.f
  ScaleX = WindowWidth(#WORKING_wind) / Window_0_WidthIni : ScaleY = WindowHeight(#WORKING_wind) / Window_0_HeightIni
  ResizeGadget(#Btn_get_SHA1, ScaleX * 10, ScaleY * 10, ScaleX * 80, ScaleY * 25)
  ResizeGadget(#Btn_pause_resume, ScaleX * 100, ScaleY * 10, ScaleX * 80, ScaleY * 25)
  ResizeGadget(#Btn_stop, ScaleX * 190, ScaleY * 10, ScaleX * 80, ScaleY * 25)
  ResizeGadget(#Txt_CLOCK, ScaleX * 280, ScaleY * 10, ScaleX * 60, ScaleY * 25)
  ResizeGadget(#WORKING_WIND_ListView, ScaleX * 10, ScaleY * 40, ScaleX * 480, ScaleY * 110)
EndProcedure

Procedure Open_mainWindow()
  OpenWindow(#WORKING_wind, 0, 0, 500, 200, "get SHA1", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
  
  TextGadget(#Txt_Select, 5, 5, 130, 25, "Select files to get SHA1:", #SS_CENTERIMAGE)
  CheckBoxGadget(#checkbox_file1, 140, 5, 60, 25, "File 1")
  CheckBoxGadget(#checkbox_file2, 205, 5, 60, 25, "File 2")
  CheckBoxGadget(#checkbox_file3, 270, 5, 60, 25, "File 3")
  
  ButtonGadget(#Btn_get_SHA1, 10, 35, 80, 25, "get SHA1")
  ButtonGadget(#Btn_pause_resume, 100, 35, 80, 25, "P/R")
  ButtonGadget(#Btn_stop, 190, 35, 80, 25, "Stop")
  TextGadget(#Txt_CLOCK, 440, 35, 60, 25, "8:18:18", #PB_Text_Center | #SS_CENTERIMAGE)
  
  ListViewGadget(#WORKING_WIND_ListView, 10, 65, 480, 110)  ; #LBS_NOSEL == 0x4000
  AddGadgetItem(#WORKING_WIND_ListView, -1, "Action Log...")
  
  CreateStatusBar(#WORKING_WIND_ProgressBar, WindowID(#WORKING_wind))
  AddStatusBarField(495)
  StatusBarProgress(#WORKING_WIND_ProgressBar, 0, 0, #PB_StatusBar_BorderLess, 0, 100)
  
  CreateThread(@update_clock(), 0)
  
  ;BindEvent(#PB_Event_SizeWindow, @Resize_mainWindow(), #WORKING_wind)
  ;PostEvent(#PB_Event_SizeWindow, #WORKING_wind, 0)
EndProcedure

Global *threadSHA1.struc_SHA1 = AllocateStructure(struc_SHA1)

Procedure Thread_GetSHA1(*dd.struc_SHA1)
  Protected t2, t1 = ElapsedMilliseconds()
  Protected nTotalBytes.q, chunksize.i, *chunkholder, nCurBytes.q, nBytesRead.d, nCurPr.d
  ; FIXME I need to run at least 2 threads for 2 or more checkboxes
  With *dd
    MessageRequester("Information", "There are " + Str(ListSize(\FilePath$())) + " files in the list.", #PB_MessageRequester_Ok)
    \Sha1Out$ = "0"
    ForEach \FilePath$()
      If ReadFile(0, \FilePath$()) = 0
        \Sha1Out$ = "-1"
        PostEvent(#SHA1_Log, \Window, 0, 0, AllocateString(#CR$ + "File not found: " + GetFilePart(\FilePath$())))
        PostEvent(#SHA1_Validate, \Window, 0, 0, 0)
      EndIf
      If ReadFile(0, \FilePath$()) > 0
        PostEvent(#SHA1_Log, \Window, 0, 0, AllocateString("Cal SHA1: " + GetFilePart(\FilePath$())))
        nTotalBytes = FileSize(\FilePath$())
        chunksize = nTotalBytes/100
        *chunkholder = AllocateMemory(chunksize)
        nCurBytes = nTotalBytes
        UseSHA1Fingerprint()
        StartFingerprint(0, #PB_Cipher_SHA1)
        While Eof(0) = 0
          If \Pause
            PostEvent(#SHA1_Log, \Window, 0, 0, AllocateString("Paused cal SHA1."))
            WaitSemaphore(\Signal)
          EndIf
          If \Exit
            CloseFile(0)
            FreeMemory(*chunkholder)
            PostEvent(#SHA1_Log, \Window, 0, 0, AllocateString("Stopped cal SHA1."))
            PostEvent(#SHA1_Progress, \Window, 0, 0, 0)
            Break
          EndIf
          nBytesRead = ReadData(0, *chunkholder, chunksize)
          nCurBytes - nBytesRead
          nCurPr = ((nTotalBytes - nCurBytes) / nTotalBytes) * 100
          PostEvent(#SHA1_Progress, \Window, 0, 0, nCurPr)
          AddFingerprintBuffer(0, *chunkholder, nBytesRead)
        Wend
        If Not \Exit
          CloseFile(0)
          FreeMemory(*chunkholder)
          \Sha1Out$ = FinishFingerprint(0)
          PostEvent(#SHA1_Progress, \Window, 0, 0, 0)
          t2     = ElapsedMilliseconds()
          PostEvent(#SHA1_Log, \Window, 0, 0, AllocateString("SHA1: " + \Sha1Out$ + Chr(10) + "Elapsed " + StrF((t2 - t1) / 1000) + " seconds."))
          PostEvent(#SHA1_Validate, \Window, 0, 0, 0)
        EndIf
      EndIf
      \ThreadID = 0
    Next
  EndWith
EndProcedure

Macro GetSHA1()
  ClearGadgetItems(#WORKING_WIND_ListView)  
  SetGadgetText(#Btn_pause_resume, "Pause")
  *threadSHA1\Window = #WORKING_wind
  If GetGadgetState(#checkbox_file1) = 1
    AddElement(*threadSHA1\FilePath$())
    *threadSHA1\FilePath$() = #file1_path
  EndIf
  If GetGadgetState(#checkbox_file2) = 1
    AddElement(*threadSHA1\FilePath$())
    *threadSHA1\FilePath$() = #file2_path
  EndIf
  If GetGadgetState(#checkbox_file3) = 1
    AddElement(*threadSHA1\FilePath$())
    *threadSHA1\FilePath$() = #file3_path
  EndIf
  ;GetSHA1(OpenFileRequester("BigFile", "", "", 0))
  If Not IsThread(*threadSHA1\ThreadID)
    StartThread(*threadSHA1, @Thread_GetSHA1())
  EndIf
EndMacro

Macro Set_Log(MessageText)
  AddGadgetItem(#WORKING_WIND_ListView, -1, MessageText) 
  SetGadgetState(#WORKING_WIND_ListView, CountGadgetItems(#WORKING_WIND_ListView) -1) 
EndMacro 

Open_mainWindow()

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      FreeThread(*threadSHA1)
      Break
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #Btn_get_SHA1
          GetSHA1()
        Case #Btn_pause_resume
          If IsThread(*threadSHA1\ThreadID)
            If Not *threadSHA1\Pause
              ThreadPause(*threadSHA1)
              SetGadgetText(#Btn_pause_resume, "Resume")
            Else
              ThreadResume(*threadSHA1)
              SetGadgetText(#Btn_pause_resume, "Pause")
            EndIf
          EndIf
        Case #Btn_stop
          StopThread(*threadSHA1)
          SetGadgetText(#Btn_pause_resume, "P/R")
      EndSelect
    Case #SHA1_Log
      Set_Log(FreeString(EventData()))
    Case #SHA1_Progress
      StatusBarProgress(#WORKING_WIND_ProgressBar, 0, EventData())
    Case #SHA1_Validate
      If GetGadgetState(#checkbox_file1) = 1
        MessageRequester("SHA1 of file1", *threadSHA1\Sha1Out$, #PB_MessageRequester_Info)
        ;         If CompareMemoryString(#file1_sha1, *threadSHA1\Sha1Out$) ! #PB_String_Equal
        ;           MessageRequester("Error", "File1: SHA1 not match")
        ;         EndIf
      EndIf
      If GetGadgetState(#checkbox_file2) = 1
        MessageRequester("SHA1 of file2", *threadSHA1\Sha1Out$, #PB_MessageRequester_Info)
        ;         If CompareMemoryString(#file1_sha3, *threadSHA1\Sha1Out$) ! #PB_String_Equal
        ;           MessageRequester("Error", "File2: SHA1 not match")
        ;         EndIf
      EndIf
      If GetGadgetState(#checkbox_file3) = 1
        MessageRequester("SHA1 of file3", *threadSHA1\Sha1Out$, #PB_MessageRequester_Info)
        ;         If CompareMemoryString(#file1_sha3, *threadSHA1\Sha1Out$) ! #PB_String_Equal
        ;           MessageRequester("Error", "File3: SHA1 not match")
        ;         EndIf
      EndIf
  EndSelect
ForEver
Leave a Comment