EnableExplicit Procedure.b Torrent_GetArray_MapPiece(Array MapPiece.a(1), NumberPiece) Protected Result.b, Temp.a, SizeArray, Index SizeArray = ArraySize(MapPiece()) Result = #False If SizeArray>=0 ;And SizeArray*8 => NumberPiece Index = Int(NumberPiece/8) If Index>=0 And Index < SizeArray Temp = MapPiece(Index) Index = NumberPiece % 8 If Index>0 And Index<8 Temp >> Index EndIf Result = Temp & 1 EndIf EndIf ProcedureReturn Result EndProcedure Procedure.b Torrent_SetArray_MapPiece(Array MapPiece.a(1), NumberPiece, Value.b) Protected Result.b, Temp.a, SizeArray, Index, Var.a, Shift.a SizeArray = ArraySize(MapPiece()) Result = #False If SizeArray>=0 ;And SizeArray*8 => NumberPiece Index = Round(NumberPiece/8, #PB_Round_Down) If Index>=0 And Index < SizeArray Temp = MapPiece(Index) Shift = NumberPiece % 8 Var = 1 If Shift>0 And Shift<8 Var << Shift EndIf If Value Temp | Var Else Var = ~Var Temp & Var EndIf MapPiece(Index) = Temp Result = #True EndIf EndIf ProcedureReturn Result EndProcedure Procedure Torrent_CheckFilesHash_ProgressCB(INFO_Hash.s, *OldPercent.Word, *OldTime.Long, All_FileSize.q, PosFiles.q) Protected x, y, z.b, Pos Protected Temp.f, Percent.w, Time.l, Result;rc.RECT Result=#True Time = ElapsedMilliseconds() If Time>*OldTime\l Or *OldTime\l>Time+1000 Or *OldTime\l=0 If PosFiles>0 Temp = 1000 / (All_FileSize / PosFiles) Else Temp = 0 EndIf Percent = Round(Temp, #PB_Round_Nearest) ;Debug Percent If Percent > *OldPercent\w Or Percent>=1000 Or *OldTime\l=0 *OldPercent\w = Percent x = 0 If Percent>=1000 y=80 Else y=4 EndIf Repeat If TryLockMutex(G_TorrentList\Mutex_Table) Pos = 0 z = 0 ForEach G_TorrentList\Table() If LCase(G_TorrentList\Table()\INFO_Hash) = INFO_Hash G_TorrentList\Table()\Percent = Percent z = 1 Break EndIf Pos + 1 Next UnlockMutex(G_TorrentList\Mutex_Table) If z = 1 PostMessage_(G_ProgramMiscInfo\hTorrentListIcon, #LVM_UPDATE, Pos, 0) Else ; Не найден элемент списка стребуемым хешем. Наверное торрент удалили. Result=#False EndIf Break EndIf x+1 If y>0 Delay(10) EndIf Until x>=y EndIf *OldTime\l = Time + 100 EndIf ProcedureReturn Result EndProcedure Procedure.b Torrent_CheckFilesHash(Path.s, T_CountPiece, Torrent_FileSize.q, *FileMap.Sub_TorrentInfo_TorrentList_MapFile, *Torrent.TorrentFiles_TorrentInfo, *CurrentFileSize.QUAD) ; Проверка файлов торрента на соответсвие SHA1 хеш-суммам. Protected Result.b, *PieceMem, FileID, i Protected SizeArray_Files, Address.q, CurrentPiece_Index, Len Protected CountPiece, CountBytes, Shift, Temp, x Protected CB_Piece_Pos.q, INFO_Hash.s, OldPercent.w, OldTime.l Result = #False Address = 0 If *Torrent\piece_length>0 *PieceMem = AllocateMemory(*Torrent\piece_length+10) If *PieceMem CurrentPiece_Index = 0 : Address = 0 CountPiece = *Torrent\piece_length-1 SizeArray_Files = ArraySize(*FileMap\MapFiles())-1 Shift = 0 INFO_Hash = LCase(*Torrent\INFO_Hash) OldPercent = 0 For i=0 To SizeArray_Files If *FileMap\MapFiles(i)\TestFile ; Файл есть. If *FileMap\MapFiles(i)\SizeFile > 0 ; Файл не пустой. FileID = ReadFile(#PB_Any, Path+*FileMap\MapFiles(i)\FileName) If FileID If *FileMap\MapFiles(i)\PieceStart = *FileMap\MapFiles(i)\PieceEnd ; Файл расположен в пределах одной части. Len = *FileMap\MapFiles(i)\SizeFile If Shift+Len > *Torrent\piece_length Len = *Torrent\piece_length-Shift EndIf CountBytes = ReadData(FileID, *PieceMem+Shift, Len) Shift + CountBytes ElseIf *FileMap\MapFiles(i)\PieceStart < *FileMap\MapFiles(i)\PieceEnd ; Часть файла находится в одной части, а другая часть, в другой части торрента. If *FileMap\MapFiles(i)\ShiftStart>0 Len = *Torrent\piece_length-*FileMap\MapFiles(i)\ShiftStart If Shift+Len > *Torrent\piece_length Len = *Torrent\piece_length-Shift EndIf CountBytes = ReadData(FileID, *PieceMem+Shift, Len) Shift + CountBytes If Shift = *Torrent\piece_length ; Есть вся часть и она считана в *PieceMem If LCase(SHA1Fingerprint(*PieceMem, Shift)) = LCase(*Torrent\pieces(*FileMap\MapFiles(i)\PieceStart)\SHA1_string) CB_Piece_Pos + Shift If Torrent_CheckFilesHash_ProgressCB(INFO_Hash, @OldPercent, @OldTime, Torrent_FileSize, CB_Piece_Pos)<>#True Break ; Наверное удалили торент во время проверки EndIf Torrent_SetArray_MapPiece(*FileMap\MapPiece(), *FileMap\MapFiles(i)\PieceStart, 1) ; Отмечаем что кусок есть на диске. Else Torrent_SetArray_MapPiece(*FileMap\MapPiece(), *FileMap\MapFiles(i)\PieceStart, 0) ; Отмечаем что куска нет на диске. EndIf Else ; Нет всей части. Torrent_SetArray_MapPiece(*FileMap\MapPiece(), *FileMap\MapFiles(i)\PieceStart, 0) ; Отмечаем что куска нет на диске. EndIf EndIf If *FileMap\MapFiles(i)\PieceStart < *FileMap\MapFiles(i)\PieceEnd ; Файл занимает больше чем одну часть. Address = Loc(FileID) If *FileMap\MapFiles(i)\ShiftStart>0 Temp = 1 Else Temp = 0 EndIf For x = *FileMap\MapFiles(i)\PieceStart+Temp To *FileMap\MapFiles(i)\PieceEnd ; -1 If x = *FileMap\MapFiles(i)\PieceEnd And *FileMap\MapFiles(i)\ShiftEnd < *Torrent\piece_length Break EndIf FillMemory(*PieceMem, *Torrent\piece_length+8, 0) If x < *FileMap\MapFiles(i)\PieceEnd Len = *Torrent\piece_length Else Len = *FileMap\MapFiles(i)\ShiftEnd + 1 EndIf If Len > *Torrent\piece_length Len = *Torrent\piece_length EndIf If Address+Len>*FileMap\MapFiles(i)\SizeFile Len = *FileMap\MapFiles(i)\SizeFile - Address EndIf CountBytes = ReadData(FileID, *PieceMem, Len) Address + CountBytes If CountBytes>0 And LCase(SHA1Fingerprint(*PieceMem, CountBytes)) = LCase(*Torrent\pieces(x)\SHA1_string) CB_Piece_Pos + CountBytes If Torrent_CheckFilesHash_ProgressCB(INFO_Hash, @OldPercent, @OldTime, Torrent_FileSize, CB_Piece_Pos)<>#True Break 2 ; Наверное удалили торент во время проверки EndIf Torrent_SetArray_MapPiece(*FileMap\MapPiece(), x, 1) ; Отмечаем что кусок есть на диске. Else Torrent_SetArray_MapPiece(*FileMap\MapPiece(), x, 0) ; Отмечаем что куска нет на диске. EndIf Next x EndIf FillMemory(*PieceMem, *Torrent\piece_length+8, 0) Shift = 0 If *FileMap\MapFiles(i)\ShiftEnd>=0 Address = Loc(FileID) Len = *FileMap\MapFiles(i)\ShiftEnd+1 If Len > *Torrent\piece_length Len = *Torrent\piece_length ; -Shift EndIf If Address+Len>*FileMap\MapFiles(i)\SizeFile Len = *FileMap\MapFiles(i)\SizeFile - Address EndIf CountBytes = ReadData(FileID, *PieceMem, Len) Shift = CountBytes EndIf EndIf If i = SizeArray_Files And *FileMap\MapFiles(i)\PieceEnd = T_CountPiece ; Это самая последняя часть и она имеет размер меньший чем остальные. If LCase(SHA1Fingerprint(*PieceMem, Shift)) = LCase(*Torrent\pieces(*FileMap\MapFiles(i)\PieceEnd)\SHA1_string) CB_Piece_Pos + Shift If Torrent_CheckFilesHash_ProgressCB(INFO_Hash, @OldPercent, @OldTime, Torrent_FileSize, CB_Piece_Pos)<>#True Break ; Наверное удалили торент во время проверки EndIf Torrent_SetArray_MapPiece(*FileMap\MapPiece(), *FileMap\MapFiles(i)\PieceEnd, 1) ; Отмечаем что кусок есть на диске. Else Torrent_SetArray_MapPiece(*FileMap\MapPiece(), *FileMap\MapFiles(i)\PieceEnd, 0) ; Отмечаем что куска нет на диске. EndIf EndIf Result = #True Else ; Нет доступа к файлу. For x = *FileMap\MapFiles(i)\PieceStart To *FileMap\MapFiles(i)\PieceEnd Torrent_SetArray_MapPiece(*FileMap\MapPiece(), x, 0) ; Отмечаем что куска нет на диске. Next x FillMemory(*PieceMem, *Torrent\piece_length+8, 0) Shift = 0 EndIf If FileID And IsFile(FileID) : CloseFile(FileID) : FileID=0 : EndIf ; Если ранее был открыт файл - закрываем его. EndIf Else For x = *FileMap\MapFiles(i)\PieceStart To *FileMap\MapFiles(i)\PieceEnd Torrent_SetArray_MapPiece(*FileMap\MapPiece(), x, 0) ; Отмечаем что куска нет на диске. Next x FillMemory(*PieceMem, *Torrent\piece_length+8, 0) Shift = 0 EndIf Next i FreeMemory(*PieceMem) EndIf EndIf OldTime = 0 Torrent_CheckFilesHash_ProgressCB(INFO_Hash, @OldPercent, @OldTime, Torrent_FileSize, CB_Piece_Pos) *CurrentFileSize\q = CB_Piece_Pos ProcedureReturn Result EndProcedure Procedure.b Torrent_CreateMap(Path.s, *FileMap.Sub_TorrentInfo_TorrentList_MapFile, *Torrent.TorrentFiles_TorrentInfo);, *CurrentFileSize.QUAD) ; Заполнение структуры Sub_TorrentInfo_TorrentList_MapFile. Protected Result.b, CountFiles, String.s, x Protected Size.q, Address.q, Temp, i, TempQ.q Result = #False Address = 0 CountFiles = ListSize(*Torrent\files()) If CountFiles>0 ReDim *FileMap\MapFiles(CountFiles) If ArraySize(*FileMap\MapFiles()) = CountFiles i = 0 ForEach *Torrent\files() Size = *Torrent\files()\length *FileMap\MapFiles(i)\SizeFile = Size String = "" x=0 Temp = ListSize(*Torrent\files()\path()) If Temp>0 ForEach *Torrent\files()\path() x + 1 String + *Torrent\files()\path() If x"" *FileMap\MapFiles(i)\FileName = String Else ProcedureReturn #False EndIf Else ProcedureReturn #False EndIf TempQ = FileSize(Path+String) If TempQ>=0 And TempQ = Size ; Файл есть на диске. *FileMap\MapFiles(i)\TestFile = 1 Else ; Файла нет на диске. *FileMap\MapFiles(i)\TestFile = 0 EndIf ;If Size<0 : Size = 0 : EndIf If Temp<0 : Temp = 0 : EndIf *FileMap\MapFiles(i)\RealFileSize = TempQ;Size *FileMap\MapFiles(i)\AddressStart = Address *FileMap\MapFiles(i)\AddressEnd = Address + Size - 1 *FileMap\MapFiles(i)\PieceStart = Address / *Torrent\piece_length *FileMap\MapFiles(i)\PieceEnd = *FileMap\MapFiles(i)\AddressEnd / *Torrent\piece_length *FileMap\MapFiles(i)\ShiftStart = Address % *Torrent\piece_length *FileMap\MapFiles(i)\ShiftEnd = (*FileMap\MapFiles(i)\AddressEnd % *Torrent\piece_length) + 1 Address + Size i + 1 Next Result = #True EndIf EndIf ProcedureReturn Result EndProcedure Procedure.a Torrent_SetRealSizeFile(*FileMap.Sub_TorrentInfo_TorrentList_MapFile, piece_length.l, TorrentName.s) ; Определение размера полезных данных в файле по числу имеющихся частей. Protected SizeArray_Files, SizeArray_Piece Protected PieceStart.l, PieceEnd.l, x, Temp Protected i, Piece, FileSize.q, RealFileSize.q, FileTorrentSize.q Protected Byte.a, Result.a, CurrentPiece SizeArray_Files = ArraySize(*FileMap\MapFiles())-1 ; Массив файлов. SizeArray_Piece = ArraySize(*FileMap\MapPiece())-1 ; Массив частей. RealFileSize = 0 Result=#True For i=0 To SizeArray_Files RealFileSize=0 FileSize = *FileMap\MapFiles(i)\RealFileSize ; Текущий реальный размер файла (сколько байт файла присудствует на диске на данный момент). FileTorrentSize = *FileMap\MapFiles(i)\SizeFile ; Размер файла в байтах (из торрент файла). PieceStart = *FileMap\MapFiles(i)\PieceStart PieceEnd = *FileMap\MapFiles(i)\PieceEnd x = *FileMap\MapFiles(i)\ShiftStart CurrentPiece = 0 If PieceEnd = PieceStart ; Файл расположен в пределах одной части. If Torrent_GetArray_MapPiece(*FileMap\MapPiece(), PieceStart) ; Есть часть. RealFileSize + (*FileMap\MapFiles(i)\ShiftEnd - x) CurrentPiece + 1 EndIf ElseIf PieceEnd > PieceStart ; Файл занимает болше чем одну часть. If x>0 Byte=1 If Torrent_GetArray_MapPiece(*FileMap\MapPiece(), PieceStart) ; Есть часть. RealFileSize + (piece_length-x) CurrentPiece + 1 EndIf Else Byte=0 EndIf For x=PieceStart+Byte To PieceEnd-1 If Torrent_GetArray_MapPiece(*FileMap\MapPiece(), x) ; Есть часть. RealFileSize + piece_length CurrentPiece + 1 EndIf Next x x = *FileMap\MapFiles(i)\ShiftEnd If x>0 If Torrent_GetArray_MapPiece(*FileMap\MapPiece(), PieceEnd) ; Есть часть. RealFileSize + x CurrentPiece + 1 EndIf EndIf EndIf If FileSize < RealFileSize And (FileSize<>-1 And RealFileSize<>0) Goto Torrent_SetRealSizeFile_M1 ElseIf FileTorrentSize<>FileSize And CurrentPiece>0 Torrent_SetRealSizeFile_M1: Result=#False ; Ошибка. AddGadgetItem(#MainWin_Panel_Info_ListIcon_Log, -1, TimeLog()+"Ошибка торрента '"+TorrentName+"'. Файл '"+*FileMap\MapFiles(i)\FileName+"' имеет некорректный размер и скорее всего поврежден.", ImageID(#MainWin_TorrentIcon_bag)) Else *FileMap\MapFiles(i)\RealFileSize = RealFileSize EndIf Next i ProcedureReturn Result EndProcedure ; Проверка наличия файлов торрента на диске компа в указанной папке. Procedure.b Torrent_TestFiles(Path.s, FileName.s, *FileMap.Sub_TorrentInfo_TorrentList_MapFile, *Torrent.TorrentFiles_TorrentInfo, *CurrentFileSize.QUAD) Protected Result.b, CountFiles, String.s, x Protected Size.q, Address.q, Temp, i Protected Temp_2, CurrentFileSize.q Result = #False CountFiles = ListSize(*Torrent\files()) If CountFiles>0 If *Torrent\TypeDir = #True ; Торрент в виде папки файлов. Temp_2 = CountFiles -1 ; Число файлов. Temp = ArraySize(*FileMap\MapPiece())-1 ; Число частей. Size = 0 x = 0 For i = 0 To Temp *FileMap\MapPiece(i) = 0 ; Отмечаем что всех кусков нет на диске - обнуление. Next For i=0 To Temp_2 If *FileMap\MapFiles(i)\TestFile = 1 ; Файл есть на диске. If *FileMap\MapFiles(i)\PieceStart = *FileMap\MapFiles(i)\PieceEnd ;And i=0 And (SizeArray*8<=CountPiece And (SizeArray+1)*8>=CountPiece) For i=0 To SizeArray Byte = Piece(i) For x=1 To 8 If Byte & 1 > 0 Count+1 EndIf Byte>>1 z+1 If z>CountPiece Break 2 EndIf Next x Next i EndIf ProcedureReturn Count EndProcedure Procedure Torrent_Compare_PieceArray(Array MyPiece.a(1), Array PeerPiece.a(1), CountPiece) ; Сравнения двух массивов частей для определения их различия. Находит части, которые есть у пира, но нет у нас. Protected Count, SizeArray, i, x Protected MyByte.a, PeerByte.a, z Count=0 SizeArray=ArraySize(MyPiece()) If SizeArray>=0 And ((SizeArray-1)*8<=CountPiece And SizeArray*8>=CountPiece) And SizeArray=ArraySize(PeerPiece()) For i=0 To SizeArray MyByte = MyPiece(i) PeerByte=PeerPiece(i) For x=1 To 8 If MyByte&1=0 And PeerByte&1 <> 0 ; У нас части нет, а у пира она есть. Count+1 EndIf MyByte>>1 PeerByte>>1 z+1 If z>CountPiece ; Проверили все части. Break 2 EndIf Next x Next i EndIf ProcedureReturn Count EndProcedure Procedure.b CreateSysFile_Torrent(FileName.s, *DataTorrentFile, DataTorrent_Size.l) ; Создание торрент-фавйла в системной папке программы. Protected FileID, Result.b Result = #False If *DataTorrentFile And DataTorrent_Size>0 FileID = CreateFile(#PB_Any, FileName) If FileID WriteData(FileID, *DataTorrentFile, DataTorrent_Size) CloseFile(FileID) Result = #True EndIf EndIf ProcedureReturn Result EndProcedure Procedure.a Torrent_SetDataList(*NewTorrent.Sub_TorrentInfo_TorrentList) ; Запись данных для нового торрента - заполение структур. Protected Result.a, Error.a, x.a ; При вызове этой процежуры, захвачен мьютекс G_TorrentList\Mutex. Result = #False : Error = #False ForEach *NewTorrent\TorrentFile\announce_list() x=0 ForEach *NewTorrent\Network\Tracker() ; Чтобы трекеры не дублировались. If *NewTorrent\TorrentFile\announce_list() = *NewTorrent\Network\Tracker()\Address x=1 : Break EndIf Next If x=0 LastElement(*NewTorrent\Network\Tracker()) If AddElement(*NewTorrent\Network\Tracker()) *NewTorrent\Network\Error_Tracker = 0 *NewTorrent\Network\Tracker()\Address = *NewTorrent\TorrentFile\announce_list() *NewTorrent\Network\Tracker()\Command = #Tracker_Started *NewTorrent\Network\Tracker()\Old_Command = #Tracker_Empty *NewTorrent\Network\Tracker()\CountNoConnect = 0 *NewTorrent\Network\Tracker()\Downloaded = 0 *NewTorrent\Network\Tracker()\ErrorString = "" *NewTorrent\Network\Tracker()\Left = *NewTorrent\Torrent\Torrent_FileSize - *NewTorrent\Torrent\CurrentFileSize *NewTorrent\Network\Tracker()\TrackerID = "" *NewTorrent\Network\Tracker()\UpdateTime = 2 *NewTorrent\Network\Tracker()\Interval = 30*60 *NewTorrent\Network\Tracker()\Min_Interval = 60 *NewTorrent\Network\Tracker()\Uploaded = 0 *NewTorrent\Network\Tracker()\Error = 0 *NewTorrent\Network\Tracker()\Warning_Message_Err = 0 *NewTorrent\Network\Tracker()\NumTracker = *NewTorrent\Network\EnumTracker ; Номер трекера (уникален для торрента). *NewTorrent\Network\EnumTracker + 1 Else Error = #True : Break EndIf EndIf Next If Error = #False : Result = #True : EndIf ProcedureReturn Result EndProcedure Procedure Torrent_AddTorrent(Full_PathFile.s, Label.s, CheckHash_State.b, StartTorrentState.b, Torrent_FileSize.q, *Torrent.TorrentFiles_TorrentInfo, Message.s, *DataTorrentFile, DataTorrent_Size.l, *ErrMutex.Ascii) ; Добавление нового торрента в список. Protected TempS.s, TempF.f, TempL.l, i, x.a Protected FileMap.Sub_TorrentInfo_TorrentList_MapFile, CountPiece, CountMapPiece, Path.s Protected FileName.s, INFO_Hash.s, AddDate.l, CurrentFileSize.q Protected TempQ.q, TempW.w, TorrentName.s, CurrentCountPiece.l *ErrMutex\a = #False ; На всякий случай проверяем есть ли торрент в списке, хотя этого не может быть! LockMutex(G_TorrentList\Mutex) ; Блокируем обращения к списку торрентов. INFO_Hash = LCase(*Torrent\INFO_Hash) ForEach G_TorrentList\TorrentList() If LCase(G_TorrentList\TorrentList()\TorrentFile\INFO_Hash) = INFO_Hash UnlockMutex(G_TorrentList\Mutex) ProcedureReturn #False ; Чудеса да и только. Ну не может быть такого чтобы торрент был в списке, значит глюк или недоработка программы. EndIf Next UnlockMutex(G_TorrentList\Mutex) Path="" : FileName ="" If *Torrent\TypeDir = #True Path = Full_PathFile TorrentName = *Torrent\CurrentDir_Name Else ; Однофайловый торрент. Path = GetPathPart(Full_PathFile) FileName = GetFilePart(Full_PathFile) SelectElement(*Torrent\files(),0) If FileName<>"" And CheckFilename(FileName) ; Имя файла корректно. *Torrent\files()\path() = FileName Else ; Имя файла некорректно. FileName = *Torrent\files()\path() EndIf TorrentName = FileName EndIf If Path<>"" If Right(Path,1)<>"\" : Path+"\" : EndIf EndIf If TorrentName="" TorrentName = "Новый торрент" EndIf CountPiece = Round(*Torrent\All_Size / *Torrent\piece_length, #PB_Round_Up) ; Число частей торрента. CountMapPiece = Round(CountPiece/8, #PB_Round_Up) ; Число элементов массива-карты присутсвия или отсутсвия части. ReDim FileMap\MapPiece(CountMapPiece) ; For i=0 To CountMapPiece FileMap\MapPiece(i) = 0 Next i If Torrent_CreateMap(Path, @FileMap, *Torrent) = #False ProcedureReturn #False ; Ошибка при создании карты торрента. EndIf If Torrent_TestFiles(Path.s, FileName.s, @FileMap, *Torrent, @CurrentFileSize) = #False ProcedureReturn #False ; Ошибка при проверке файлов торрента. EndIf CurrentCountPiece = Torrent_CountPiece(FileMap\MapPiece(), CountPiece) AddDate = Date() LockMutex(G_TorrentList\Mutex) ; Блокируем обращения к списку торрентов. ; Добавление информации о торренте в список LastElement(G_TorrentList\TorrentList()) ; Переход на последний элемент списка. If AddElement(G_TorrentList\TorrentList()) ; Добавляем запись о новом торренте. G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Add ; Состояние торрента. CopyStructure(*Torrent, @G_TorrentList\TorrentList()\TorrentFile, TorrentFiles_TorrentInfo) CopyStructure(@FileMap, @G_TorrentList\TorrentList()\Torrent\MapFile, Sub_TorrentInfo_TorrentList_MapFile) If CountMapPiece>=0 ReDim G_TorrentList\TorrentList()\Network\AccessiblyPiece(CountMapPiece) EndIf G_TorrentList\TorrentList()\Torrent\CountPiece = CountPiece G_TorrentList\TorrentList()\Torrent\CurrentCountPiece = CurrentCountPiece G_TorrentList\TorrentList()\Torrent\Path = Path G_TorrentList\TorrentList()\AddDate = AddDate G_TorrentList\TorrentList()\Torrent\CurrentFileSize = CurrentFileSize G_TorrentList\TorrentList()\TorrentName = TorrentName G_TorrentList\TorrentList()\Label = Label G_TorrentList\TorrentList()\ActiveTimeSec = 0; Время активности торреена (в секундах). G_TorrentList\TorrentList()\Network_IO\Limit_In = -1 ; Лимит приёма. G_TorrentList\TorrentList()\Network_IO\Limit_Out = -1 ; Лимит отдачи. G_TorrentList\TorrentList()\Network_IO\RemainsTime=-1 G_TorrentList\TorrentList()\Torrent\Torrent_FileSize = Torrent_FileSize ; Размер файлов, которые нужно скачать. Может быть меньше реального размера торрента. G_TorrentList\TorrentList()\DelStatus = #False Torrent_SetDataList(@G_TorrentList\TorrentList()) Else UnlockMutex(G_TorrentList\Mutex) ProcedureReturn #False EndIf UnlockMutex(G_TorrentList\Mutex) If Test_LockMutex(G_TorrentList\Mutex_Table, 800)=#True LastElement(G_TorrentList\Table()) ; Переход на последний элемент списка. If AddElement(G_TorrentList\Table()) ; Добавляем запись о новом торренте. G_TorrentList\Table()\INFO_Hash = INFO_Hash G_TorrentList\Table()\Percent = 0 UnlockMutex(G_TorrentList\Mutex_Table) Else UnlockMutex(G_TorrentList\Mutex_Table) LockMutex(G_TorrentList\Mutex) ; Блокируем обращения к списку торрентов. ForEach G_TorrentList\TorrentList() If G_TorrentList\TorrentList()\TorrentFile\INFO_Hash = INFO_Hash DeleteElement(G_TorrentList\TorrentList()) Break EndIf Next UnlockMutex(G_TorrentList\Mutex) ProcedureReturn #False EndIf Else *ErrMutex\a = #True LockMutex(G_TorrentList\Mutex) ; Блокируем обращения к списку торрентов. ForEach G_TorrentList\TorrentList() If G_TorrentList\TorrentList()\TorrentFile\INFO_Hash = INFO_Hash DeleteElement(G_TorrentList\TorrentList()) Break EndIf Next UnlockMutex(G_TorrentList\Mutex) ProcedureReturn #False EndIf x = Test_LockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex, 800) TempL = CountGadgetItems(#MainWin_ListIcon_Torrent) AddGadgetItem(#MainWin_ListIcon_Torrent, TempL, TorrentName+Chr(10)+"Добавление") SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, TempL, #MainWin_TorrentIcon_New) SetGadgetItemText(#MainWin_ListIcon_Torrent, TempL, ConvertByte_ToString(*Torrent\All_Size, 2), #MainWin_ListIcon_Torrent_Size) SetGadgetItemText(#MainWin_ListIcon_Torrent, TempL, FormatDate("%dd.%mm.%yyyy %hh:%ii", AddDate), #MainWin_ListIcon_Torrent_Date) If x=#True UnlockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex) EndIf If CheckHash_State = 0 ; Нужно проверить SHA1 хеш-суммы файлов. TempQ = CurrentFileSize Torrent_CheckFilesHash(Path, CountPiece-1, Torrent_FileSize, @FileMap, *Torrent, @CurrentFileSize) Torrent_SetRealSizeFile(@FileMap, *Torrent\piece_length, TorrentName) ; Определение размера полезных данных в файле по числу имеющихся частей. If TempQ <> CurrentFileSize LockMutex(G_TorrentList\Mutex) ; Блокируем обращения к списку торрентов. ForEach G_TorrentList\TorrentList() If G_TorrentList\TorrentList()\TorrentFile\INFO_Hash = INFO_Hash G_TorrentList\TorrentList()\Torrent\CurrentFileSize = CurrentFileSize CopyStructure(@FileMap, @G_TorrentList\TorrentList()\Torrent\MapFile, Sub_TorrentInfo_TorrentList_MapFile) Break EndIf Next UnlockMutex(G_TorrentList\Mutex) EndIf Else TempW=0 : TempL=0 Torrent_CheckFilesHash_ProgressCB(INFO_Hash, @TempW, @TempL, Torrent_FileSize, CurrentFileSize) EndIf FileName = "" TempL = 0 FileName = TorrentName+".torrent" TempS = G_ProgramMiscInfo\Dir_SysFiles+FileName If FileSize(TempS)>=0 Repeat FileName = TorrentName+"_"+Str(TempL)+".torrent" TempS = G_ProgramMiscInfo\Dir_SysFiles+FileName If FileSize(TempS) = -1 Break EndIf TempL+1 Until TempL>10000 EndIf If TempL>10000 Or CreateSysFile_Torrent(TempS, *DataTorrentFile, DataTorrent_Size) = #False ;TorrentFiles_CreateSysFile_Torrent(TempS, *Torrent) = #False MessageRequester(Message, "Ошибка копирования торрент-файла!", #MB_OK|#MB_ICONWARNING) TempL = 0 Else TempL = 1 EndIf i = 0 : TempW=0 LockMutex(G_TorrentList\Mutex) ; Блокируем обращения к списку торрентов. ForEach G_TorrentList\TorrentList() If G_TorrentList\TorrentList()\TorrentFile\INFO_Hash = INFO_Hash If TempL = 1 G_TorrentList\TorrentList()\Torrent\SysFileName = FileName EndIf TempW=1 If StartTorrentState If G_TorrentList\TorrentList()\Torrent\CurrentFileSize < G_TorrentList\TorrentList()\Torrent\Torrent_FileSize G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Load ; Состояние торрента. TempL = 1 Else G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Seed ; Состояние торрента. TempL = 0 EndIf Else G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Stop ; Состояние торрента. EndIf Break EndIf i+1 Next UnlockMutex(G_TorrentList\Mutex) If TempW=1 If Test_LockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex, 400)=#True If StartTorrentState If TempL = 1 SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_down) ; Загрузка. Else SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_up) ; Раздача (сидитирование). EndIf Else SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_stop) EndIf Update_TableTorrent("", i, 0) UnlockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex) Else *ErrMutex\a = #True EndIf EndIf SaveTorrentData() ProcedureReturn #True EndProcedure Procedure Torrent_AddTrackerList(INFO_Hash.s, *Torrent.TorrentFiles_TorrentInfo) ; Добавление трекеров в выбранный торрент. Protected UpdateFile.b, String.s, x, FileName.s UpdateFile = #False If Test_LockMutex(G_TorrentList\Mutex, 800) ; Блокируем обращения к списку торрентов. ForEach G_TorrentList\TorrentList() If G_TorrentList\TorrentList()\TorrentFile\INFO_Hash = INFO_Hash FileName = G_TorrentList\TorrentList()\Torrent\SysFileName ForEach *Torrent\announce_list() String = *Torrent\announce_list() x = 0 ForEach G_TorrentList\TorrentList()\TorrentFile\announce_list() If G_TorrentList\TorrentList()\TorrentFile\announce_list() = String ; В списке есть уже этот адрес трекера. x = 1 Break EndIf Next If x=0 ; Если в списке небыло адреса, трекера, то добавляем его. UpdateFile = #True LastElement(G_TorrentList\TorrentList()\TorrentFile\announce_list()) If AddElement(G_TorrentList\TorrentList()\TorrentFile\announce_list()) G_TorrentList\TorrentList()\TorrentFile\announce_list() = String EndIf EndIf Next Torrent_SetDataList(@G_TorrentList\TorrentList()) Break EndIf Next If UpdateFile = #True ClearStructure(*Torrent, TorrentFiles_TorrentInfo) CopyStructure(G_TorrentList\TorrentList()\TorrentFile, *Torrent, TorrentFiles_TorrentInfo) EndIf UnlockMutex(G_TorrentList\Mutex) If UpdateFile = #True ; Нужно преписать торрент файл. TorrentFiles_CreateSysFile_Torrent(G_ProgramMiscInfo\Dir_SysFiles+FileName, *Torrent) EndIf Else If G_ProgramSetting\Misc\BalloonTray=#True ; Произошла ошибка и разрешены всплывающие подстазки над треем. SysTray_IconBalloon(#SysTrayID, WindowID(#MainWin), "Добавление трекера.", "Произошла ошибка при захвате мьютекса.", 20000, 3) EndIf EndIf EndProcedure Procedure Torrent_ProgStart_Thread(*x) ; В этом потоке считываются все данные из торрент файлов и копируются в структуру. Protected NewList ListTorrentFiles.String_2(), Torrent.TorrentFiles_TorrentInfo Protected x, y, *Mem, Temp, hImageList, i LockMutex(G_TorrentList\Mutex) ; Блокируем обращения к списку торрентов. ForEach G_TorrentList\TorrentList() If AddElement(ListTorrentFiles()) ListTorrentFiles()\String_1 = G_TorrentList\TorrentList()\Torrent\SysFileName ListTorrentFiles()\String_2 = G_TorrentList\TorrentList()\TorrentName EndIf Next UnlockMutex(G_TorrentList\Mutex) y = 0 ForEach ListTorrentFiles() x = 0 If TorrentFiles_LoadTorrentFile(G_ProgramMiscInfo\Dir_SysFiles+ListTorrentFiles()\String_1, @Torrent, 0, 0) = #True LockMutex(G_TorrentList\Mutex) ; Блокируем обращения к списку торрентов. ForEach G_TorrentList\TorrentList() If Torrent\INFO_Hash = G_TorrentList\TorrentList()\TorrentFile\INFO_Hash And ListTorrentFiles()\String_1 = G_TorrentList\TorrentList()\Torrent\SysFileName If Torrent_CreateMap(G_TorrentList\TorrentList()\Torrent\Path, @G_TorrentList\TorrentList()\Torrent\MapFile, @Torrent) If Torrent_SetRealSizeFile(@G_TorrentList\TorrentList()\Torrent\MapFile, Torrent\piece_length, G_TorrentList\TorrentList()\TorrentName)=#False ; Определение размера полезных данных в файле по числу имеющихся частей. G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Error ; Поврежедны файлы. SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, y, #MainWin_TorrentIcon_bag) EndIf ClearStructure(@G_TorrentList\TorrentList()\TorrentFile, TorrentFiles_TorrentInfo) CopyStructure(@Torrent, G_TorrentList\TorrentList()\TorrentFile, TorrentFiles_TorrentInfo) G_TorrentList\TorrentList()\Torrent\CurrentCountPiece = Torrent_CountPiece(G_TorrentList\TorrentList()\Torrent\MapFile\MapPiece(), G_TorrentList\TorrentList()\Torrent\CountPiece) CopyArray(G_TorrentList\TorrentList()\Torrent\MapFile\MapPiece(), G_TorrentList\TorrentList()\Network\AccessiblyPiece() ) If G_TorrentList\TorrentList()\Torrent\CountPiece>0 G_TorrentList\TorrentList()\Network_IO\Available = G_TorrentList\TorrentList()\Torrent\CurrentCountPiece / G_TorrentList\TorrentList()\Torrent\CountPiece Else G_TorrentList\TorrentList()\Network_IO\Available=0 EndIf x = 1 EndIf Break EndIf Next Torrent_SetDataList(@G_TorrentList\TorrentList()) UnlockMutex(G_TorrentList\Mutex) Update_TableTorrent("", y, 0) Else Debug ListTorrentFiles()\String_1+" ошбка торрент файла." EndIf If x = 0 MessageRequester("", "Ошибка при инициализации торрента"+Chr(10)+ListTorrentFiles()\String_2, #MB_OK|#MB_ICONWARNING) EndIf y+1 Next Out_StatusBar() If G_ProgramMiscInfo\Setting\MainWinVisible = #True HideWindow(#MainWin, 0) EndIf ; Флаги для таблоицы трекеров. hImageList = SendMessage_(GadgetID(#MainWin_Panel_Info_ListIcon_Peer), #LVM_GETIMAGELIST, #LVSIL_SMALL, 0) If hImageList Temp = 0 : y = 0 CompilerIf #PB_Compiler_Version>=510 *Mem=UnPak(?FlagPac, ?FlagPac_End-?FlagPac, @Temp) CompilerElse *Mem=UnPak(?FlagPac, @Temp) CompilerEndIf If *Mem<>0 And Temp>0 For i=#MainWin_Flag_Pmr To #MainWin_Flag_South_africa x=PeekL(*Mem+y) ; Сколько байт занимает файл. If x<=0 Or x+y>Temp Or CatchImage(#MainWin_Image_UnPacFlagTemp, *Mem+y+4, x) = 0 MessageRequester(#MessageName+" - инициализация программы", "Ошибка при распаковке ресурсов программы!", #MB_OK|#MB_ICONERROR) Break EndIf y+x+4 G_ProgramMiscInfo\Torrent_Flags_ImageList[i-#MainWin_Flag_Pmr] = ImageList_ReplaceIcon_(hImageList, -1, ImageID(#MainWin_Image_UnPacFlagTemp)) Next i FreeMemory(*Mem) Else MessageRequester(#MessageName+" - инициализация программы", "Ошибка при распаковке ресурсов программы!", #MB_OK|#MB_ICONERROR) EndIf EndIf If IsImage(#MainWin_Image_UnPacFlagTemp) FreeImage(#MainWin_Image_UnPacFlagTemp) EndIf G_ProgramMiscInfo\Thread\Network_ThreadID = CreateThread(@Core_NetworkEvent_Thread(), 0) If G_ProgramMiscInfo\Thread\Network_ThreadID = 0 MessageRequester(#MessageName, "Ошибка запуска потока"+Chr(10)+"поддержки работы сети!", #MB_ICONERROR) End EndIf EndProcedure Procedure Torrent_ProgStartAddTorrent() ; Вызывается при старте программы и добавляет тореенты в таблицу. Protected ThreadID, y, i Protected NewList T_List.GetIcon_Extension() PanelInfo_DrawImage(0, 1, 0) LockMutex(G_TorrentList\Mutex) ; Блокируем обращения к списку торрентов. ForEach G_TorrentList\TorrentList() G_TorrentList\TorrentList()\Network_IO\RemainsTime=-1 G_TorrentList\TorrentList()\DelStatus = #False If AddElement(T_List()) T_List()\Part = G_TorrentList\TorrentList()\TorrentName T_List()\IconID = G_TorrentList\TorrentList()\TorrentStatus EndIf Next UnlockMutex(G_TorrentList\Mutex) y = 0 For i=1 To 100 If TryLockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex) y=1 Break EndIf Delay(10) Next i If y=1 y = 0 ForEach T_List() AddGadgetItem(#MainWin_ListIcon_Torrent, y, "") ;T_List()\Part Select T_List()\IconID Case #TorrentStatus_Load SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, y, #MainWin_TorrentIcon_down) Case #TorrentStatus_Seed SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, y, #MainWin_TorrentIcon_up) Case #TorrentStatus_Pause SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, y, #MainWin_TorrentIcon_Pause) Case #TorrentStatus_Stop SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, y, #MainWin_TorrentIcon_stop) Case #TorrentStatus_Error SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, y, #MainWin_TorrentIcon_bag) EndSelect Update_TableTorrent("", y, 0) y+1 Next UnlockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex) EndIf ClearList(T_List()) ThreadID = CreateThread(@Torrent_ProgStart_Thread(), 0) If ThreadID = 0 MessageRequester(#MessageName, "Ошибка запуска потока, "+Chr(10)+"чтения данных из торрент файла!", #MB_OK|#MB_ICONERROR) End Else ThreadPriority(ThreadID, 8) EndIf G_ProgramMiscInfo\Thread\OutText_ThreadID = CreateThread(@Core_Times_Thread(),0) If G_ProgramMiscInfo\Thread\OutText_ThreadID = 0 MessageRequester(#MessageName, "Ошибка запуска потока, "+Chr(10)+"обслуживания GUI!", #MB_OK|#MB_ICONERROR) End Else ThreadPriority(G_ProgramMiscInfo\Thread\OutText_ThreadID, 8) EndIf EndProcedure Procedure Torrent_SetStatus(Status.b) ; Смена статуса торрента - запущен, на паузе или остановлен. Protected i, x, Count, SizeList Protected NewList Torrent_Info.GetIcon_Extension() Protected NewList ActiveItem.l() Protected NewList Torrent_Status.POINT() Protected NewList TableTorrent.OutTextTableTorrent() Protected ErrStatus.a If Status = #TorrentStatus_M_Start Or Status = #TorrentStatus_Pause Or Status = #TorrentStatus_Stop ErrStatus = #True If Test_LockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex, 800)=#True ; Определяем какие пункте выделены в таблице. Count = CountGadgetItems(#MainWin_ListIcon_Torrent)-1 For i=0 To Count If GetGadgetItemState(#MainWin_ListIcon_Torrent, i) & #PB_ListIcon_Selected ; Пункт выделен. If AddElement(ActiveItem()) ActiveItem() = i EndIf EndIf Next i UnlockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex) If ListSize(ActiveItem())>0 ; В списке есть элементы. If Test_LockMutex(G_TorrentList\Mutex, 800)=#True SizeList = ListSize(G_TorrentList\TorrentList()) ForEach ActiveItem() i=ActiveItem() If i<=SizeList SelectElement(G_TorrentList\TorrentList(), i) If G_TorrentList\TorrentList()\TorrentStatus<>#TorrentStatus_Add If Status = #TorrentStatus_M_Start If G_TorrentList\TorrentList()\Torrent\CurrentFileSize < G_TorrentList\TorrentList()\Torrent\Torrent_FileSize G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Load Else G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Seed EndIf If AddElement(Torrent_Info()) Torrent_Info()\Part = G_TorrentList\TorrentList()\TorrentFile\INFO_Hash Torrent_Info()\IconID = #Tracker_Started EndIf Else If Status<>#TorrentStatus_Pause Or (Status=#TorrentStatus_Pause And (G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Load Or G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Seed)) G_TorrentList\TorrentList()\TorrentStatus = Status If Status = #TorrentStatus_Stop If AddElement(Torrent_Info()) Torrent_Info()\Part = G_TorrentList\TorrentList()\TorrentFile\INFO_Hash Torrent_Info()\IconID = #Tracker_Stopped EndIf EndIf Else Status = G_TorrentList\TorrentList()\TorrentStatus EndIf EndIf EndIf If AddElement(Torrent_Status()) Torrent_Status()\x = G_TorrentList\TorrentList()\TorrentStatus Torrent_Status()\y = G_TorrentList\TorrentList()\Network\Error_Tracker EndIf EndIf Next UnlockMutex(G_TorrentList\Mutex) If Test_LockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex, 800)=#True x=0 SizeList = ListSize(Torrent_Status()) ForEach ActiveItem() i=ActiveItem() If x<=SizeList SelectElement(Torrent_Status(), x) If Torrent_Status()\x<>#TorrentStatus_Add Select Torrent_Status()\x Case #TorrentStatus_Load If G_ProgramMiscInfo\Torrent_All_Pause<>#True If Torrent_Status()\y=1 SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_red_down) Else SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_down) EndIf Else SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_Pause) ; Установлена пауза для всех торентов. EndIf Case #TorrentStatus_Seed If G_ProgramMiscInfo\Torrent_All_Pause<>#True If Torrent_Status()\y=1 SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_red_up) Else SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_up) EndIf Else SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_Pause) ; Установлена пауза для всех торентов. EndIf Case #TorrentStatus_Pause SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_Pause) Case #TorrentStatus_Stop SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_stop) Case #TorrentStatus_Error SetIcon_TorrentListIcon(#MainWin_ListIcon_Torrent, i, #MainWin_TorrentIcon_bag) EndSelect EndIf EndIf x+1 Next ErrStatus = #False UnlockMutex(G_ProgramMiscInfo\TorrentListIcon_Mutex) If Test_LockMutex(G_TorrentList\Mutex, 80)=#True Out_CopyData_TableTorrent(TableTorrent()) UnlockMutex(G_TorrentList\Mutex) Out_Update_TableTorrent_All(TableTorrent()) EndIf EndIf EndIf Else ; В списке нет элементов, наверное не один торрент не выбран в таблице. ErrStatus = #False EndIf EndIf If Status = #TorrentStatus_M_Start Or Status = #TorrentStatus_Stop ; Сообщает трекерам торрента что торрент запущен, либо остановлен. If ListSize(Torrent_Info())>0 ForEach Torrent_Info() Tracker_StartStop(Torrent_Info()\Part, Torrent_Info()\IconID) Next EndIf EndIf If ErrStatus=#True And G_ProgramSetting\Misc\BalloonTray=#True ; Произошла ошибка и разрешены всплывающие подсказки над треем. SysTray_IconBalloon(#SysTrayID, WindowID(#MainWin), "Изменение статуса торрента.", "Сброс по таймауту при захвате мьютекса."+Chr(10)+"Повторите операцию.", 20000, 2) EndIf EndIf EndProcedure Procedure Torrent_DeleteTorrent_DeleteFile(State) ; Удаление фйайлов торрента. Protected String.s If State = #TorrentPopupMemu_DeleteTorrent_And_Files If G_TorrentList\TorrentList()\TorrentFile\TypeDir = #True ; Торренте в папке. If FileSize(G_TorrentList\TorrentList()\Torrent\Path)=-2 DeleteDirectory(G_TorrentList\TorrentList()\Torrent\Path, "*.*", #PB_FileSystem_Recursive|#PB_FileSystem_Force) EndIf Else ; Торрент в виде одного файла. If ArraySize(G_TorrentList\TorrentList()\Torrent\MapFile\MapFiles())>=0 String = G_TorrentList\TorrentList()\Torrent\Path If Right(String,1)<>"\" : String+"\" : EndIf String+G_TorrentList\TorrentList()\Torrent\MapFile\MapFiles(0)\FileName If FileSize(String)>=0 DeleteFile(String) EndIf EndIf EndIf EndIf String = G_ProgramMiscInfo\Dir_SysFiles + G_TorrentList\TorrentList()\Torrent\SysFileName If FileSize(String)>=0 DeleteFile(String) EndIf EndProcedure Procedure Torrent_DeleteTorrent(State) ; Удаление торрента. Protected x, CountSelectItem Protected CountItem, i Protected String.s, Result Result = #False CountSelectItem = 0 CountItem = CountGadgetItems(#MainWin_ListIcon_Torrent)-1 If CountItem>=0 For i=0 To CountItem If GetGadgetItemState(#MainWin_ListIcon_Torrent, i) & #PB_ListIcon_Selected CountSelectItem+1 EndIf Next i Else ProcedureReturn 0 EndIf If CountSelectItem>0 String="Вы действительно хотите удалить торрент" If CountSelectItem = 1 And State <> #TorrentPopupMemu_DeleteTorrent_And_Files String+"?" Else String+"ы ("+Str(CountSelectItem)+")" If State <> #TorrentPopupMemu_DeleteTorrent_And_Files String+"?" EndIf EndIf If State = #TorrentPopupMemu_DeleteTorrent_And_Files ; Удаление из списка и всех файлов. String+Chr(10)+"и все их файлы?" EndIf If MessageRequester(#MessageName, String, #MB_YESNO|#MB_ICONQUESTION|#MB_DEFBUTTON2) = #IDYES ; Удаляем файлы. ; В первую очередь, нужно сообщить процедуре обмена данными с пирами что торрент остановлен, чтобы корректно удалить данные. If Test_LockMutex(G_TorrentList\Mutex, 800) x=0 CountItem = CountGadgetItems(#MainWin_ListIcon_Torrent)-1 For i=0 To CountItem If GetGadgetItemState(#MainWin_ListIcon_Torrent, i) & #PB_ListIcon_Selected If i < ListSize(G_TorrentList\TorrentList()) SelectElement(G_TorrentList\TorrentList(), i) If G_TorrentList\TorrentList()\TorrentStatus=#TorrentStatus_Load Or G_TorrentList\TorrentList()\TorrentStatus=#TorrentStatus_Seed x=1 ; Нужно создать задержку для корректного удаления торрента. EndIf G_TorrentList\TorrentList()\TorrentStatus = #TorrentStatus_Stop G_TorrentList\TorrentList()\DelStatus = #True EndIf EndIf Next i UnlockMutex(G_TorrentList\Mutex) If x=1 ; А теперь ждем две секунды чтобы гарантировано процедуре обмена с писами получила статус торрента. For i=0 To 20 For x=0 To 10 WindowEvent() Next Delay(100) Next i EndIf x = 0 ; Захватываем Mutex листа торрентов. For i=1 To 40 If TryLockMutex(G_TorrentList\Mutex) x=1 Break EndIf Delay(2) Next i If x = 1 x = 0 ; Захватываем Mutex листа процентов загрузки. For i=1 To 40 If TryLockMutex(G_TorrentList\Mutex_Table) x=1 Break EndIf Delay(2) Next i If x=1 CountItem = CountGadgetItems(#MainWin_ListIcon_Torrent)-1 For i=0 To CountItem If GetGadgetItemState(#MainWin_ListIcon_Torrent, i) & #PB_ListIcon_Selected If i < ListSize(G_TorrentList\TorrentList()) SelectElement(G_TorrentList\TorrentList(), i) Torrent_DeleteTorrent_DeleteFile(State) ClearStructure(@G_TorrentList\TorrentList(), Sub_TorrentInfo_TorrentList) DeleteElement(G_TorrentList\TorrentList()) EndIf If i < ListSize(G_TorrentList\Table()) SelectElement(G_TorrentList\Table(), i) DeleteElement(G_TorrentList\Table()) EndIf RemoveGadgetItem(#MainWin_ListIcon_Torrent, i) i-1 EndIf Next i Result = #True UnlockMutex(G_TorrentList\Mutex_Table) EndIf UnlockMutex(G_TorrentList\Mutex) ; Сохранение данных всех торрентов в файле. If SaveTorrentData()=#False And G_ProgramSetting\Misc\BalloonTray=#True ; Произошла ошибка и разрешены всплывающие подсказки над треем. SysTray_IconBalloon(#SysTrayID, WindowID(#MainWin), "Удаление торрента.", "Произошла ошибка при сохранении конфигурации торрентов.", 20000, 3) EndIf SignalSemaphore(G_ProgramMiscInfo\Panel_Info_Semaphore) EndIf EndIf If Result = #False MessageRequester(#MessageName, "Произошла ошибка при удалении торрента!", #MB_OK|#MB_ICONWARNING) EndIf EndIf EndIf EndProcedure Procedure Torrent_CountTimes(Sec) ; Подсчет времени в торрентах. Protected Status.b, Size Static Plus If Test_LockMutex(G_TorrentList\Mutex, 100) = #True Size = ListSize(G_TorrentList\TorrentList()) If Size>0 If G_ProgramMiscInfo\Torrent_All_Pause<>#True ForEach G_TorrentList\TorrentList() Status = G_TorrentList\TorrentList()\TorrentStatus If Status = #TorrentStatus_Load Or Status = #TorrentStatus_Seed G_TorrentList\TorrentList()\ActiveTimeSec + Sec+Plus EndIf Next EndIf EndIf Plus = 0 UnlockMutex(G_TorrentList\Mutex) Else Plus + Sec EndIf EndProcedure DisableExplicit ; IDE Options = PureBasic 5.11 (Windows - x86) ; Folding = ---- ; EnableXP