parent
b362a35ac1
commit
554eae5185
|
|
@ -0,0 +1,94 @@
|
|||
package m3u8d
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var gMergeStatus SpeedStatus
|
||||
var gMergeCancel context.CancelFunc
|
||||
var gMergeCancelLocker sync.Mutex
|
||||
|
||||
type MergeTsDir_Resp struct {
|
||||
ErrMsg string
|
||||
IsCancel bool
|
||||
}
|
||||
|
||||
var gMergeIsRunning atomic.Bool
|
||||
|
||||
func MergeTsDir(InputTsDir string, OutputMp4Name string) (resp MergeTsDir_Resp) {
|
||||
if !gMergeIsRunning.CompareAndSwap(false, true) {
|
||||
return resp
|
||||
}
|
||||
defer gMergeIsRunning.Store(false)
|
||||
|
||||
fList, err := ioutil.ReadDir(InputTsDir)
|
||||
if err != nil {
|
||||
resp.ErrMsg = "读取目录失败 " + err.Error()
|
||||
return
|
||||
}
|
||||
var tsFileList []string
|
||||
for _, f := range fList {
|
||||
if f.Mode().IsRegular() && strings.HasSuffix(strings.ToLower(f.Name()), ".ts") {
|
||||
tsFileList = append(tsFileList, filepath.Join(InputTsDir, f.Name()))
|
||||
}
|
||||
}
|
||||
if len(tsFileList) == 0 {
|
||||
resp.ErrMsg = "目录下不存在ts文件: " + InputTsDir
|
||||
return
|
||||
}
|
||||
sort.Strings(tsFileList) // 按照字典顺序排序
|
||||
if OutputMp4Name == "" {
|
||||
OutputMp4Name = filepath.Join(InputTsDir, "all.mp4")
|
||||
}
|
||||
ctx, cancelFn := context.WithCancel(context.Background())
|
||||
defer cancelFn()
|
||||
|
||||
gMergeCancelLocker.Lock()
|
||||
if gMergeCancel != nil {
|
||||
gMergeCancel()
|
||||
}
|
||||
gMergeCancel = cancelFn
|
||||
gMergeCancelLocker.Unlock()
|
||||
|
||||
err = MergeTsFileListToSingleMp4(MergeTsFileListToSingleMp4_Req{
|
||||
TsFileList: tsFileList,
|
||||
OutputMp4: OutputMp4Name,
|
||||
Ctx: ctx,
|
||||
Status: &gMergeStatus,
|
||||
})
|
||||
if err != nil {
|
||||
resp.ErrMsg = "合并错误: " + err.Error()
|
||||
resp.IsCancel = isContextCancel(ctx)
|
||||
return resp
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
type MergeGetProgressPercent_Resp struct {
|
||||
Percent int
|
||||
SpeedText string
|
||||
IsRunning bool
|
||||
}
|
||||
|
||||
func MergeGetProgressPercent() (resp MergeGetProgressPercent_Resp) {
|
||||
resp.IsRunning = gMergeIsRunning.Load()
|
||||
if resp.IsRunning {
|
||||
resp.Percent = gMergeStatus.GetPercent()
|
||||
resp.SpeedText = gMergeStatus.SpeedRecent5sGetAndUpdate()
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func MergeStop() {
|
||||
gMergeCancelLocker.Lock()
|
||||
if gMergeCancel != nil {
|
||||
gMergeCancel()
|
||||
}
|
||||
gMergeCancelLocker.Unlock()
|
||||
}
|
||||
|
|
@ -96,6 +96,7 @@ var mergeCmd = &cobra.Command{
|
|||
TsFileList: tsFileList,
|
||||
OutputMp4: gMergeReq.OutputMp4Name,
|
||||
Ctx: context.Background(),
|
||||
Status: nil,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalln("合并失败", err)
|
||||
|
|
|
|||
93
download.go
93
download.go
|
|
@ -50,14 +50,14 @@ func GetProgress() (resp GetProgress_Resp) {
|
|||
gOldEnvLocker.Lock()
|
||||
if gOldEnv != nil {
|
||||
sleepTh = atomic.LoadInt32(&gOldEnv.sleepTh)
|
||||
gOldEnv.progressLocker.Lock()
|
||||
resp.Percent = gOldEnv.progressPercent
|
||||
resp.Title = gOldEnv.progressBarTitle
|
||||
gOldEnv.progressLocker.Unlock()
|
||||
resp.Percent = gOldEnv.status.GetPercent()
|
||||
resp.Title = gOldEnv.status.GetTitle()
|
||||
if resp.Title == "" {
|
||||
resp.Title = "正在下载"
|
||||
}
|
||||
speedV = gOldEnv.speedRecent5sGetAndUpdate()
|
||||
if !gOldEnv.GetIsCancel() {
|
||||
speedV = gOldEnv.status.SpeedRecent5sGetAndUpdate()
|
||||
}
|
||||
}
|
||||
gOldEnvLocker.Unlock()
|
||||
resp.StatusBar = speedV
|
||||
|
|
@ -70,12 +70,6 @@ func GetProgress() (resp GetProgress_Resp) {
|
|||
return resp
|
||||
}
|
||||
|
||||
func (this *downloadEnv) SetProgressBarTitle(title string) {
|
||||
this.progressLocker.Lock()
|
||||
this.progressBarTitle = title
|
||||
this.progressLocker.Unlock()
|
||||
}
|
||||
|
||||
type RunDownload_Resp struct {
|
||||
ErrMsg string
|
||||
IsSkipped bool
|
||||
|
|
@ -97,18 +91,12 @@ type RunDownload_Req struct {
|
|||
}
|
||||
|
||||
type downloadEnv struct {
|
||||
cancelFn func()
|
||||
ctx context.Context
|
||||
nowClient *http.Client
|
||||
header http.Header
|
||||
sleepTh int32
|
||||
progressLocker sync.Mutex
|
||||
progressBarTitle string
|
||||
progressPercent int
|
||||
progressBarShow bool
|
||||
speedBytesLocker sync.Mutex
|
||||
speedBeginTime time.Time
|
||||
speedBytesMap map[time.Time]int64
|
||||
cancelFn func()
|
||||
ctx context.Context
|
||||
nowClient *http.Client
|
||||
header http.Header
|
||||
sleepTh int32
|
||||
status SpeedStatus
|
||||
}
|
||||
|
||||
func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp) {
|
||||
|
|
@ -142,7 +130,7 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp
|
|||
for key, valueList := range req.HeaderMap {
|
||||
this.header[key] = valueList
|
||||
}
|
||||
this.SetProgressBarTitle("[1/6]嗅探m3u8")
|
||||
this.status.SetProgressBarTitle("[1/6]嗅探m3u8")
|
||||
var m3u8Body []byte
|
||||
var errMsg string
|
||||
req.M3u8Url, m3u8Body, errMsg = this.sniffM3u8(req.M3u8Url)
|
||||
|
|
@ -162,7 +150,7 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp
|
|||
return resp
|
||||
}
|
||||
if info != nil {
|
||||
this.SetProgressBarTitle("[2/6]检查是否已下载")
|
||||
this.status.SetProgressBarTitle("[2/6]检查是否已下载")
|
||||
latestNameFullPath, found := info.SearchVideoInDir(req.SaveDir)
|
||||
if found {
|
||||
resp.IsSkipped = true
|
||||
|
|
@ -200,7 +188,7 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp
|
|||
resp.IsCancel = this.GetIsCancel()
|
||||
return resp
|
||||
}
|
||||
this.SetProgressBarTitle("[3/6]获取ts列表")
|
||||
this.status.SetProgressBarTitle("[3/6]获取ts列表")
|
||||
tsList, errMsg := getTsList(beginSeq, req.M3u8Url, string(m3u8Body))
|
||||
if errMsg != "" {
|
||||
resp.ErrMsg = "获取ts列表错误: " + errMsg
|
||||
|
|
@ -212,16 +200,16 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp
|
|||
}
|
||||
tsList = tsList[req.SkipTsCountFromHead:]
|
||||
// 下载ts
|
||||
this.SetProgressBarTitle("[4/6]下载ts")
|
||||
this.speedSetBegin()
|
||||
this.status.SetProgressBarTitle("[4/6]下载ts")
|
||||
this.status.SpeedResetBytes()
|
||||
err = this.downloader(tsList, downloadDir, encInfo, req.ThreadCount)
|
||||
this.speedClearBytes()
|
||||
this.status.SpeedResetBytes()
|
||||
if err != nil {
|
||||
resp.ErrMsg = "下载ts文件错误: " + err.Error()
|
||||
resp.IsCancel = this.GetIsCancel()
|
||||
return resp
|
||||
}
|
||||
this.DrawProgressBar(1, 1)
|
||||
this.status.DrawProgressBar(1, 1)
|
||||
var tsFileList []string
|
||||
for _, one := range tsList {
|
||||
tsFileList = append(tsFileList, filepath.Join(downloadDir, one.Name))
|
||||
|
|
@ -230,19 +218,19 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp
|
|||
var contentHash string
|
||||
tmpOutputName = filepath.Join(downloadDir, "all.merge.mp4")
|
||||
|
||||
this.SetProgressBarTitle("[5/6]合并ts为mp4")
|
||||
this.speedSetBegin()
|
||||
this.status.SetProgressBarTitle("[5/6]合并ts为mp4")
|
||||
err = MergeTsFileListToSingleMp4(MergeTsFileListToSingleMp4_Req{
|
||||
TsFileList: tsFileList,
|
||||
OutputMp4: tmpOutputName,
|
||||
Ctx: this.ctx,
|
||||
Status: &this.status,
|
||||
})
|
||||
this.speedClearBytes()
|
||||
this.status.SpeedResetBytes()
|
||||
if err != nil {
|
||||
resp.ErrMsg = "合并错误: " + err.Error()
|
||||
return resp
|
||||
}
|
||||
this.SetProgressBarTitle("[6/6]计算文件hash")
|
||||
this.status.SetProgressBarTitle("[6/6]计算文件hash")
|
||||
contentHash = getFileSha256(tmpOutputName)
|
||||
if contentHash == "" {
|
||||
resp.ErrMsg = "无法计算摘要信息: " + tmpOutputName
|
||||
|
|
@ -320,8 +308,9 @@ func RunDownload(req RunDownload_Req) (resp RunDownload_Resp) {
|
|||
Proxy: http.ProxyURL(proxyUrlObj),
|
||||
},
|
||||
},
|
||||
speedBytesMap: map[time.Time]int64{},
|
||||
progressBarShow: req.ProgressBarShow,
|
||||
status: SpeedStatus{
|
||||
progressBarShow: req.ProgressBarShow,
|
||||
},
|
||||
}
|
||||
env.ctx, env.cancelFn = context.WithCancel(context.Background())
|
||||
|
||||
|
|
@ -332,8 +321,8 @@ func RunDownload(req RunDownload_Req) (resp RunDownload_Resp) {
|
|||
gOldEnv = env
|
||||
gOldEnvLocker.Unlock()
|
||||
resp = env.RunDownload(req)
|
||||
env.SetProgressBarTitle("下载进度")
|
||||
env.DrawProgressBar(1, 0)
|
||||
env.status.SetProgressBarTitle("下载进度")
|
||||
env.status.DrawProgressBar(1, 0)
|
||||
return resp
|
||||
}
|
||||
|
||||
|
|
@ -483,7 +472,7 @@ func (this *downloadEnv) downloadTsFile(ts TsInfo, download_dir string, encInfo
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
this.speedAddBytes(len(origData))
|
||||
this.status.SpeedAddBytes(len(origData))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -536,7 +525,7 @@ func (this *downloadEnv) downloader(tsList []TsInfo, downloadDir string, encInfo
|
|||
}
|
||||
locker.Lock()
|
||||
downloadCount++
|
||||
this.DrawProgressBar(tsLen, downloadCount)
|
||||
this.status.DrawProgressBar(tsLen, downloadCount)
|
||||
locker.Unlock()
|
||||
})
|
||||
}
|
||||
|
|
@ -545,24 +534,6 @@ func (this *downloadEnv) downloader(tsList []TsInfo, downloadDir string, encInfo
|
|||
return err
|
||||
}
|
||||
|
||||
// 进度条
|
||||
func (this *downloadEnv) DrawProgressBar(total int, current int) {
|
||||
if total == 0 {
|
||||
return
|
||||
}
|
||||
proportion := float32(current) / float32(total)
|
||||
|
||||
this.progressLocker.Lock()
|
||||
this.progressPercent = int(proportion * 100)
|
||||
title := this.progressBarTitle
|
||||
if this.progressBarShow {
|
||||
width := 50
|
||||
pos := int(proportion * float32(width))
|
||||
fmt.Printf(title+" %s%*s %6.2f%%\r", strings.Repeat("■", pos), width-pos, "", proportion*100)
|
||||
}
|
||||
this.progressLocker.Unlock()
|
||||
}
|
||||
|
||||
func isFileExists(path string) bool {
|
||||
stat, err := os.Stat(path)
|
||||
return err == nil && stat.Mode().IsRegular()
|
||||
|
|
@ -710,8 +681,12 @@ func (this *downloadEnv) doGetRequest(urlS string) (data []byte, err error) {
|
|||
}
|
||||
|
||||
func (this *downloadEnv) GetIsCancel() bool {
|
||||
return isContextCancel(this.ctx)
|
||||
}
|
||||
|
||||
func isContextCancel(ctx context.Context) bool {
|
||||
select {
|
||||
case <-this.ctx.Done():
|
||||
case <-ctx.Done():
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ func CreateLibForQtUi(mode string) {
|
|||
ctx.Generate1(m3u8d.ParseCurlStr)
|
||||
ctx.Generate1(m3u8d.RunDownload_Req_ToCurlStr)
|
||||
ctx.Generate1(m3u8d.GetFileNameFromUrl)
|
||||
ctx.Generate1(m3u8d.MergeTsDir)
|
||||
ctx.Generate1(m3u8d.MergeStop)
|
||||
ctx.Generate1(m3u8d.MergeGetProgressPercent)
|
||||
if mode == "amd64-static" {
|
||||
ctx.MustCreateAmd64LibraryInDir("m3u8d-qt")
|
||||
} else if mode == "386-static" {
|
||||
|
|
|
|||
25
go.mod
25
go.mod
|
|
@ -6,12 +6,33 @@ require (
|
|||
github.com/orestonce/cdb v0.0.0-20220528005855-d187c22240e2
|
||||
github.com/orestonce/go2cpp v0.0.0-20220802140809-b2a921a62a07
|
||||
github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171
|
||||
github.com/spf13/cobra v1.4.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/yapingcat/gomedia v0.0.0-20221023155149-c5f2f0f45ca5
|
||||
golang.org/x/text v0.3.3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/cilium/ebpf v0.12.3 // indirect
|
||||
github.com/cosiner/argv v0.1.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d // indirect
|
||||
github.com/go-delve/delve v1.21.2 // indirect
|
||||
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d // indirect
|
||||
github.com/google/go-dap v0.11.0 // indirect
|
||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
go.starlark.net v0.0.0-20231101134539-556fd59b42f6 // indirect
|
||||
golang.org/x/arch v0.6.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
||||
golang.org/x/sys v0.14.1-0.20231108175955-e4099bfacb8c // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
|||
64
go.sum
64
go.sum
|
|
@ -1,21 +1,85 @@
|
|||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4=
|
||||
github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM=
|
||||
github.com/cosiner/argv v0.1.0 h1:BVDiEL32lwHukgJKP87btEPenzrrHUjajs/8yzaqcXg=
|
||||
github.com/cosiner/argv v0.1.0/go.mod h1:EusR6TucWKX+zFgtdUsKT2Cvg45K5rtpCcWz4hK06d8=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d h1:hUWoLdw5kvo2xCsqlsIBMvWUc1QCSsCYD2J2+Fg6YoU=
|
||||
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d/go.mod h1:C7Es+DLenIpPc9J6IYw4jrK0h7S9bKj4DNl8+KxGEXU=
|
||||
github.com/go-delve/delve v1.21.2 h1:eaS+ziJo+660mi3D2q/VP8RxW5GcF4Y1zyKSi82alsU=
|
||||
github.com/go-delve/delve v1.21.2/go.mod h1:FgTAiRUe43RS5EexL06RPyMtP8AMZVL/t9Qqgy3qUe4=
|
||||
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d h1:pxjSLshkZJGLVm0wv20f/H0oTWiq/egkoJQ2ja6LEvo=
|
||||
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d/go.mod h1:biJCRbqp51wS+I92HMqn5H8/A0PAhxn2vyOT+JqhiGI=
|
||||
github.com/google/go-dap v0.11.0 h1:SpAZJL41rOOvd85PuLCCLE1dteTQOyKNnn0H3DBHywo=
|
||||
github.com/google/go-dap v0.11.0/go.mod h1:HAeyoSd2WIfTfg+0GRXcFrb+RnojAtGNh+k+XTIxJDE=
|
||||
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/orestonce/cdb v0.0.0-20220528005855-d187c22240e2 h1:AmGkuxSIOW0gA/jetY8d1DVV0cyQ08FMCxa1arkI6HQ=
|
||||
github.com/orestonce/cdb v0.0.0-20220528005855-d187c22240e2/go.mod h1:HMNNdA1LMQFJRwobtCzVevWcInFSo9rfs1fYeVYwU+c=
|
||||
github.com/orestonce/go2cpp v0.0.0-20220802140809-b2a921a62a07 h1:nyt0GDiskod5Y9uNVrXgK7PZHeL7Ab1uVc3LhLg7/gk=
|
||||
github.com/orestonce/go2cpp v0.0.0-20220802140809-b2a921a62a07/go.mod h1:1fsOAZftk08/dOTRqlp6f/MVwaEKOhrnPUg0RtWiSdY=
|
||||
github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171 h1:NnOl6HTrhrlTT7aaAybVOtq+fEztGFMoQtegckgwLdk=
|
||||
github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171/go.mod h1:MCQUrAPiG9/PTjHJuGqWLasKbIaG6z62KO6kfp90byM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
|
||||
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yapingcat/gomedia v0.0.0-20221023155149-c5f2f0f45ca5 h1:dswmlgf8sSrjaQJCGDpmI14sIkHqyIZdP6Jwzl7gVDY=
|
||||
github.com/yapingcat/gomedia v0.0.0-20221023155149-c5f2f0f45ca5/go.mod h1:WSZ59bidJOO40JSJmLqlkBJrjZCtjbKKkygEMfzY/kc=
|
||||
go.starlark.net v0.0.0-20231101134539-556fd59b42f6 h1:+eC0F/k4aBLC4szgOcjd7bDTEnpxADJyWJE0yowgM3E=
|
||||
go.starlark.net v0.0.0-20231101134539-556fd59b42f6/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM=
|
||||
golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
|
||||
golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.1-0.20231108175955-e4099bfacb8c h1:3kC/TjQ+xzIblQv39bCOyRk8fbEeJcDHwbyxPUU2BpA=
|
||||
golang.org/x/sys v0.14.1-0.20231108175955-e4099bfacb8c/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ extern __declspec(dllexport) void Go2cppFn_GetWd(char* in, int inLen, char** out
|
|||
extern __declspec(dllexport) void Go2cppFn_ParseCurlStr(char* in, int inLen, char** out, int* outLen);
|
||||
extern __declspec(dllexport) void Go2cppFn_RunDownload_Req_ToCurlStr(char* in, int inLen, char** out, int* outLen);
|
||||
extern __declspec(dllexport) void Go2cppFn_GetFileNameFromUrl(char* in, int inLen, char** out, int* outLen);
|
||||
extern __declspec(dllexport) void Go2cppFn_MergeTsDir(char* in, int inLen, char** out, int* outLen);
|
||||
extern __declspec(dllexport) void Go2cppFn_MergeStop(char* in, int inLen, char** out, int* outLen);
|
||||
extern __declspec(dllexport) void Go2cppFn_MergeGetProgressPercent(char* in, int inLen, char** out, int* outLen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
@ -625,6 +628,100 @@ std::string GetFileNameFromUrl(std::string in0){
|
|||
return retValue;
|
||||
}
|
||||
|
||||
MergeTsDir_Resp MergeTsDir(std::string in0, std::string in1){
|
||||
std::string in;
|
||||
{
|
||||
uint32_t tmp9 = in0.length();
|
||||
char tmp10[4];
|
||||
tmp10[0] = (uint32_t(tmp9) >> 24) & 0xFF;
|
||||
tmp10[1] = (uint32_t(tmp9) >> 16) & 0xFF;
|
||||
tmp10[2] = (uint32_t(tmp9) >> 8) & 0xFF;
|
||||
tmp10[3] = (uint32_t(tmp9) >> 0) & 0xFF;
|
||||
in.append(tmp10, 4);
|
||||
in.append(in0);
|
||||
}
|
||||
{
|
||||
uint32_t tmp11 = in1.length();
|
||||
char tmp12[4];
|
||||
tmp12[0] = (uint32_t(tmp11) >> 24) & 0xFF;
|
||||
tmp12[1] = (uint32_t(tmp11) >> 16) & 0xFF;
|
||||
tmp12[2] = (uint32_t(tmp11) >> 8) & 0xFF;
|
||||
tmp12[3] = (uint32_t(tmp11) >> 0) & 0xFF;
|
||||
in.append(tmp12, 4);
|
||||
in.append(in1);
|
||||
}
|
||||
char *out = NULL;
|
||||
int outLen = 0;
|
||||
Go2cppFn_MergeTsDir((char *)in.data(), in.length(), &out, &outLen);
|
||||
MergeTsDir_Resp retValue;
|
||||
int outIdx = 0;
|
||||
{
|
||||
{
|
||||
uint32_t tmp13 = 0;
|
||||
uint32_t tmp14 = uint32_t(uint8_t(out[outIdx+0]) << 24);
|
||||
uint32_t tmp15 = uint32_t(uint8_t(out[outIdx+1]) << 16);
|
||||
uint32_t tmp16 = uint32_t(uint8_t(out[outIdx+2]) << 8);
|
||||
uint32_t tmp17 = uint32_t(uint8_t(out[outIdx+3]) << 0);
|
||||
tmp13 = tmp14 | tmp15 | tmp16 | tmp17;
|
||||
outIdx+=4;
|
||||
retValue.ErrMsg = std::string(out+outIdx, out+outIdx+tmp13);
|
||||
outIdx+=tmp13;
|
||||
}
|
||||
retValue.IsCancel = (bool) out[outIdx];
|
||||
outIdx++;
|
||||
}
|
||||
if (out != NULL) {
|
||||
free(out);
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
void MergeStop(){
|
||||
std::string in;
|
||||
char *out = NULL;
|
||||
int outLen = 0;
|
||||
Go2cppFn_MergeStop((char *)in.data(), in.length(), &out, &outLen);
|
||||
if (out != NULL) {
|
||||
free(out);
|
||||
}
|
||||
}
|
||||
|
||||
MergeGetProgressPercent_Resp MergeGetProgressPercent(){
|
||||
std::string in;
|
||||
char *out = NULL;
|
||||
int outLen = 0;
|
||||
Go2cppFn_MergeGetProgressPercent((char *)in.data(), in.length(), &out, &outLen);
|
||||
MergeGetProgressPercent_Resp retValue;
|
||||
int outIdx = 0;
|
||||
{
|
||||
{
|
||||
uint32_t tmp4 = uint32_t(uint8_t(out[outIdx+0]) << 24);
|
||||
uint32_t tmp5 = uint32_t(uint8_t(out[outIdx+1]) << 16);
|
||||
uint32_t tmp6 = uint32_t(uint8_t(out[outIdx+2]) << 8);
|
||||
uint32_t tmp7 = uint32_t(uint8_t(out[outIdx+3]) << 0);
|
||||
retValue.Percent = tmp4 | tmp5 | tmp6 | tmp7;
|
||||
outIdx+=4;
|
||||
}
|
||||
{
|
||||
uint32_t tmp8 = 0;
|
||||
uint32_t tmp9 = uint32_t(uint8_t(out[outIdx+0]) << 24);
|
||||
uint32_t tmp10 = uint32_t(uint8_t(out[outIdx+1]) << 16);
|
||||
uint32_t tmp11 = uint32_t(uint8_t(out[outIdx+2]) << 8);
|
||||
uint32_t tmp12 = uint32_t(uint8_t(out[outIdx+3]) << 0);
|
||||
tmp8 = tmp9 | tmp10 | tmp11 | tmp12;
|
||||
outIdx+=4;
|
||||
retValue.SpeedText = std::string(out+outIdx, out+outIdx+tmp8);
|
||||
outIdx+=tmp8;
|
||||
}
|
||||
retValue.IsRunning = (bool) out[outIdx];
|
||||
outIdx++;
|
||||
}
|
||||
if (out != NULL) {
|
||||
free(out);
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Qt:
|
||||
|
|
|
|||
|
|
@ -45,6 +45,20 @@ struct ParseCurl_Resp{
|
|||
ParseCurl_Resp ParseCurlStr(std::string in0);
|
||||
std::string RunDownload_Req_ToCurlStr(RunDownload_Req in0);
|
||||
std::string GetFileNameFromUrl(std::string in0);
|
||||
struct MergeTsDir_Resp{
|
||||
std::string ErrMsg;
|
||||
bool IsCancel;
|
||||
MergeTsDir_Resp(): IsCancel(false){}
|
||||
};
|
||||
MergeTsDir_Resp MergeTsDir(std::string in0, std::string in1);
|
||||
void MergeStop();
|
||||
struct MergeGetProgressPercent_Resp{
|
||||
int32_t Percent;
|
||||
std::string SpeedText;
|
||||
bool IsRunning;
|
||||
MergeGetProgressPercent_Resp(): Percent(0),IsRunning(false){}
|
||||
};
|
||||
MergeGetProgressPercent_Resp MergeGetProgressPercent();
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
#include <QFileDialog>
|
||||
#include <QIntValidator>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include "curldialog.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
|
|
@ -19,22 +22,33 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
ui->lineEdit_SkipTsCountFromHead->setValidator(vd);
|
||||
ui->lineEdit_SkipTsCountFromHead->setPlaceholderText("[0,9999]");
|
||||
ui->lineEdit_SaveDir->setPlaceholderText(QString::fromStdString(GetWd()));
|
||||
m_syncUi.AddRunFnOn_OtherThread([this](){
|
||||
while(!this->m_syncUi.Get_Done())
|
||||
m_timer = new QTimer(this);
|
||||
connect(m_timer, &QTimer::timeout, [this](){
|
||||
//更新ui1
|
||||
{
|
||||
QThread::msleep(50);
|
||||
m_syncUi.AddRunFnOn_UiThread([this](){
|
||||
GetProgress_Resp resp = GetProgress();
|
||||
ui->progressBar->setValue(resp.Percent);
|
||||
ui->label_progressBar->setText(QString::fromStdString(resp.Title));
|
||||
GetProgress_Resp resp = GetProgress();
|
||||
ui->progressBar->setValue(resp.Percent);
|
||||
ui->label_progressBar->setText(QString::fromStdString(resp.Title));
|
||||
if(!resp.StatusBar.empty())
|
||||
ui->statusBar->showMessage(QString::fromStdString(resp.StatusBar), 5*1000);
|
||||
});
|
||||
}
|
||||
|
||||
//更新ui2
|
||||
{
|
||||
auto resp = MergeGetProgressPercent();
|
||||
ui->progressBar_merge->setValue(resp.Percent);
|
||||
if(!resp.SpeedText.empty())
|
||||
ui->statusBar->showMessage(QString::fromStdString(resp.SpeedText), 5*1000);
|
||||
}
|
||||
});
|
||||
m_timer->start(50);
|
||||
this->updateDownloadUi(false);
|
||||
this->updateMergeUi(false);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
m_timer->stop();
|
||||
CloseOldEnv();
|
||||
delete ui;
|
||||
}
|
||||
|
|
@ -44,19 +58,7 @@ void MainWindow::on_pushButton_RunDownload_clicked()
|
|||
if (ui->lineEdit_M3u8Url->isEnabled()==false) {
|
||||
return;
|
||||
}
|
||||
ui->lineEdit_M3u8Url->setEnabled(false);
|
||||
ui->lineEdit_SaveDir->setEnabled(false);
|
||||
ui->pushButton_SaveDir->setEnabled(false);
|
||||
ui->lineEdit_FileName->setEnabled(false);
|
||||
ui->lineEdit_SkipTsCountFromHead->setEnabled(false);
|
||||
ui->pushButton_RunDownload->setEnabled(false);
|
||||
ui->checkBox_Insecure->setEnabled(false);
|
||||
ui->progressBar->setValue(0);
|
||||
ui->lineEdit_SetProxy->setEnabled(false);
|
||||
ui->pushButton_curlMode->setEnabled(false);
|
||||
ui->checkBox_SkipRemoveTs->setEnabled(false);
|
||||
ui->lineEdit_ThreadCount->setEnabled(false);
|
||||
ui->pushButton_StopDownload->setEnabled(true);
|
||||
updateDownloadUi(true);
|
||||
|
||||
RunDownload_Req req;
|
||||
req.M3u8Url = ui->lineEdit_M3u8Url->text().toStdString();
|
||||
|
|
@ -72,19 +74,7 @@ void MainWindow::on_pushButton_RunDownload_clicked()
|
|||
m_syncUi.AddRunFnOn_OtherThread([req, this](){
|
||||
RunDownload_Resp resp = RunDownload(req);
|
||||
m_syncUi.AddRunFnOn_UiThread([req, this, resp](){
|
||||
ui->lineEdit_M3u8Url->setEnabled(true);
|
||||
ui->lineEdit_SaveDir->setEnabled(true);
|
||||
ui->pushButton_SaveDir->setEnabled(true);
|
||||
ui->lineEdit_FileName->setEnabled(true);
|
||||
ui->lineEdit_SkipTsCountFromHead->setEnabled(true);
|
||||
ui->pushButton_RunDownload->setEnabled(true);
|
||||
ui->checkBox_Insecure->setEnabled(true);
|
||||
ui->pushButton_RunDownload->setText("开始下载");
|
||||
ui->lineEdit_SetProxy->setEnabled(true);
|
||||
ui->pushButton_StopDownload->setEnabled(false);
|
||||
ui->pushButton_curlMode->setEnabled(true);
|
||||
ui->checkBox_SkipRemoveTs->setEnabled(true);
|
||||
ui->lineEdit_ThreadCount->setEnabled(true);
|
||||
this->updateDownloadUi(false);
|
||||
if (resp.IsCancel) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -142,3 +132,80 @@ void MainWindow::on_lineEdit_M3u8Url_textChanged(const QString &arg1)
|
|||
}
|
||||
ui->lineEdit_FileName->setPlaceholderText(fileName);
|
||||
}
|
||||
|
||||
void MainWindow::on_pushButton_returnDownload_clicked()
|
||||
{
|
||||
ui->stackedWidget->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void MainWindow::on_pushButton_gotoMergeTs_clicked()
|
||||
{
|
||||
ui->stackedWidget->setCurrentIndex(1);
|
||||
}
|
||||
|
||||
void MainWindow::on_pushButton_startMerge_clicked()
|
||||
{
|
||||
QString fileName = ui->lineEdit_mergeFileName->text();
|
||||
if(fileName.isEmpty())
|
||||
fileName = ui->lineEdit_mergeFileName->placeholderText();
|
||||
QString dir = ui->lineEdit_mergeDir->text();
|
||||
|
||||
this->updateMergeUi(true);
|
||||
|
||||
m_syncUi.AddRunFnOn_OtherThread([=](){
|
||||
auto resp = MergeTsDir(dir.toStdString(), fileName.toStdString());
|
||||
|
||||
m_syncUi.AddRunFnOn_UiThread([=](){
|
||||
this->updateMergeUi(false);
|
||||
if(resp.ErrMsg.empty())
|
||||
Toast::Instance()->SetSuccess("合并成功!");
|
||||
else if(!resp.IsCancel)
|
||||
QMessageBox::warning(this, "下载错误", QString::fromStdString(resp.ErrMsg));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::on_pushButton_stopMerge_clicked()
|
||||
{
|
||||
MergeStop();
|
||||
}
|
||||
|
||||
void MainWindow::on_toolButton_selectMergeDir_clicked()
|
||||
{
|
||||
QString dir = QFileDialog::getExistingDirectory(this);
|
||||
if(dir.isEmpty())
|
||||
return;
|
||||
ui->lineEdit_mergeDir->setText(dir);
|
||||
}
|
||||
|
||||
void MainWindow::updateDownloadUi(bool runing)
|
||||
{
|
||||
ui->lineEdit_M3u8Url->setEnabled(!runing);
|
||||
ui->lineEdit_SaveDir->setEnabled(!runing);
|
||||
ui->pushButton_SaveDir->setEnabled(!runing);
|
||||
ui->lineEdit_FileName->setEnabled(!runing);
|
||||
ui->lineEdit_SkipTsCountFromHead->setEnabled(!runing);
|
||||
ui->pushButton_RunDownload->setEnabled(!runing);
|
||||
ui->checkBox_Insecure->setEnabled(!runing);
|
||||
if(runing == false)
|
||||
ui->pushButton_RunDownload->setText("开始下载");
|
||||
ui->lineEdit_SetProxy->setEnabled(!runing);
|
||||
ui->pushButton_StopDownload->setEnabled(runing);
|
||||
ui->pushButton_curlMode->setEnabled(!runing);
|
||||
ui->checkBox_SkipRemoveTs->setEnabled(!runing);
|
||||
ui->lineEdit_ThreadCount->setEnabled(!runing);
|
||||
|
||||
if(runing == false)
|
||||
ui->progressBar->setValue(0);
|
||||
|
||||
ui->pushButton_gotoMergeTs->setEnabled(!runing);
|
||||
}
|
||||
|
||||
void MainWindow::updateMergeUi(bool runing)
|
||||
{
|
||||
ui->lineEdit_mergeDir->setEnabled(!runing);
|
||||
ui->toolButton_selectMergeDir->setEnabled(!runing);
|
||||
ui->pushButton_stopMerge->setEnabled(runing);
|
||||
ui->lineEdit_mergeFileName->setEnabled(!runing);
|
||||
ui->pushButton_returnDownload->setEnabled(!runing);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,22 @@ private slots:
|
|||
|
||||
void on_lineEdit_M3u8Url_textChanged(const QString &arg1);
|
||||
|
||||
void on_pushButton_returnDownload_clicked();
|
||||
|
||||
void on_pushButton_gotoMergeTs_clicked();
|
||||
|
||||
void on_pushButton_startMerge_clicked();
|
||||
|
||||
void on_pushButton_stopMerge_clicked();
|
||||
|
||||
void on_toolButton_selectMergeDir_clicked();
|
||||
private:
|
||||
void updateDownloadUi(bool runing);
|
||||
void updateMergeUi(bool runing);
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
RunOnUiThread m_syncUi;
|
||||
QTimer *m_timer = nullptr;
|
||||
std::map<std::string, std::vector<std::string>> m_HeaderMap;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>762</width>
|
||||
<height>271</height>
|
||||
<width>857</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -16,185 +16,359 @@
|
|||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>m3u8的url</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_M3u8Url">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButton_curlMode">
|
||||
<property name="text">
|
||||
<string>curl模式</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>保存位置</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_SaveDir"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButton_SaveDir">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>99999</width>
|
||||
<height>99999</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>保存的文件名</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_FileName">
|
||||
<property name="placeholderText">
|
||||
<string>all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>跳过前面几个TS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_SkipTsCountFromHead"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>代理设置</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_SetProxy">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>http://127.0.0.1:8080 socks5://127.0.0.1:1089</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>下载线程数</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_ThreadCount">
|
||||
<property name="text">
|
||||
<string>8</string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>[1,1000]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_Insecure">
|
||||
<property name="text">
|
||||
<string>允许不安全的https请求</string>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_SkipTsCountFromHead"/>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_ThreadCount">
|
||||
<property name="text">
|
||||
<string>8</string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>[1,1000]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>保存的文件名</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_FileName">
|
||||
<property name="placeholderText">
|
||||
<string>all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>m3u8的url</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButton_curlMode">
|
||||
<property name="text">
|
||||
<string>curl模式</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>保存位置</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>跳过前面几个TS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>下载线程数</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>代理设置</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_M3u8Url">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_SaveDir"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButton_SaveDir">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>99999</width>
|
||||
<height>99999</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_SetProxy">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>http://127.0.0.1:8080 socks5://127.0.0.1:1089</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_Insecure">
|
||||
<property name="text">
|
||||
<string>允许不安全的https请求</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_SkipRemoveTs">
|
||||
<property name="text">
|
||||
<string>不删除下载的ts文件</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0,0,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_progressBar">
|
||||
<property name="text">
|
||||
<string>下载进度</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_gotoMergeTs">
|
||||
<property name="text">
|
||||
<string>合并ts</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_RunDownload">
|
||||
<property name="text">
|
||||
<string>开始下载</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_StopDownload">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>停止下载</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1,0">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>文件夹:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_mergeDir"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton_selectMergeDir">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="0,1,0">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>输出文件名:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_mergeFileName">
|
||||
<property name="placeholderText">
|
||||
<string>all.mp4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>进度</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar_merge">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_returnDownload">
|
||||
<property name="text">
|
||||
<string>返回</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_startMerge">
|
||||
<property name="text">
|
||||
<string>开始合并</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_stopMerge">
|
||||
<property name="text">
|
||||
<string>停止合并</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_SkipRemoveTs">
|
||||
<property name="text">
|
||||
<string>不删除下载的ts文件</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_progressBar">
|
||||
<property name="text">
|
||||
<string>下载进度</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_RunDownload">
|
||||
<property name="text">
|
||||
<string>开始下载</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_StopDownload">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>停止下载</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
|
|
|
|||
17
merge.go
17
merge.go
|
|
@ -15,6 +15,7 @@ import (
|
|||
type MergeTsFileListToSingleMp4_Req struct {
|
||||
TsFileList []string
|
||||
OutputMp4 string
|
||||
Status *SpeedStatus
|
||||
Ctx context.Context
|
||||
}
|
||||
|
||||
|
|
@ -25,6 +26,10 @@ func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error)
|
|||
}
|
||||
defer mp4file.Close()
|
||||
|
||||
if req.Status != nil {
|
||||
req.Status.SpeedResetBytes()
|
||||
}
|
||||
|
||||
muxer, err := mp4.CreateMp4Muxer(mp4file)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -67,8 +72,6 @@ func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error)
|
|||
}
|
||||
}
|
||||
|
||||
env := getOldEnv()
|
||||
|
||||
for idx, tsFile := range req.TsFileList {
|
||||
select {
|
||||
case <-req.Ctx.Done():
|
||||
|
|
@ -87,9 +90,9 @@ func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error)
|
|||
if OnFrameErr != nil {
|
||||
return OnFrameErr
|
||||
}
|
||||
if env != nil {
|
||||
env.DrawProgressBar(len(req.TsFileList), idx)
|
||||
env.speedAddBytes(len(buf))
|
||||
if req.Status != nil {
|
||||
req.Status.DrawProgressBar(len(req.TsFileList), idx)
|
||||
req.Status.SpeedAddBytes(len(buf))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,8 +104,8 @@ func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error)
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if env != nil {
|
||||
env.DrawProgressBar(1, 1)
|
||||
if req.Status != nil {
|
||||
req.Status.DrawProgressBar(1, 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
84
speed.go
84
speed.go
|
|
@ -1,39 +1,68 @@
|
|||
package m3u8d
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (this *downloadEnv) speedSetBegin() {
|
||||
type SpeedStatus struct {
|
||||
speedBytesLocker sync.Mutex
|
||||
speedBeginTime time.Time
|
||||
speedBytesMap map[time.Time]int64
|
||||
|
||||
progressLocker sync.Mutex
|
||||
progressPercent int
|
||||
progressBarTitle string
|
||||
progressBarShow bool
|
||||
}
|
||||
|
||||
func (this *SpeedStatus) DrawProgressBar(total int, current int) {
|
||||
if total == 0 {
|
||||
return
|
||||
}
|
||||
proportion := float32(current) / float32(total)
|
||||
|
||||
this.progressLocker.Lock()
|
||||
this.progressPercent = int(proportion * 100)
|
||||
title := this.progressBarTitle
|
||||
if this.progressBarShow {
|
||||
width := 50
|
||||
pos := int(proportion * float32(width))
|
||||
fmt.Printf(title+" %s%*s %6.2f%%\r", strings.Repeat("■", pos), width-pos, "", proportion*100)
|
||||
}
|
||||
this.progressLocker.Unlock()
|
||||
}
|
||||
|
||||
func (this *SpeedStatus) SpeedAddBytes(a int) {
|
||||
this.speedBytesLocker.Lock()
|
||||
defer this.speedBytesLocker.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
|
||||
this.speedBytesMap[now] += int64(a)
|
||||
}
|
||||
|
||||
func (this *SpeedStatus) SpeedResetBytes() {
|
||||
this.speedBytesLocker.Lock()
|
||||
defer this.speedBytesLocker.Unlock()
|
||||
|
||||
this.speedBeginTime = time.Now()
|
||||
}
|
||||
|
||||
func (this *downloadEnv) speedAddBytes(a int) {
|
||||
this.speedBytesLocker.Lock()
|
||||
defer this.speedBytesLocker.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
this.speedBytesMap[now] += int64(a)
|
||||
}
|
||||
|
||||
func (this *downloadEnv) speedClearBytes() {
|
||||
this.speedBytesLocker.Lock()
|
||||
defer this.speedBytesLocker.Unlock()
|
||||
|
||||
if this.speedBytesMap == nil {
|
||||
this.speedBytesMap = map[time.Time]int64{}
|
||||
}
|
||||
this.speedBytesMap = map[time.Time]int64{}
|
||||
}
|
||||
|
||||
func (this *downloadEnv) speedRecent5sGetAndUpdate() string {
|
||||
func (this *SpeedStatus) SpeedRecent5sGetAndUpdate() string {
|
||||
this.speedBytesLocker.Lock()
|
||||
defer this.speedBytesLocker.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
if this.GetIsCancel() || this.speedBeginTime.IsZero() || now.Sub(this.speedBeginTime) < time.Second { // 1s以内, 暂时不计算速度
|
||||
return ""
|
||||
if this.speedBeginTime.IsZero() || now.Sub(this.speedBeginTime) < time.Second { // 1s以内, 暂时不计算速度
|
||||
return "x1 " + strconv.FormatBool(this.speedBeginTime.IsZero()) + " " + strconv.FormatBool(now.Sub(this.speedBeginTime) < time.Second)
|
||||
}
|
||||
|
||||
const secondCount = 5
|
||||
|
|
@ -64,3 +93,22 @@ func (this *downloadEnv) speedRecent5sGetAndUpdate() string {
|
|||
v = v / 1024
|
||||
return strconv.FormatFloat(v, 'f', 2, 64) + " MB/s"
|
||||
}
|
||||
|
||||
func (this *SpeedStatus) GetPercent() (percent int) {
|
||||
this.progressLocker.Lock()
|
||||
defer this.progressLocker.Unlock()
|
||||
|
||||
return this.progressPercent
|
||||
}
|
||||
|
||||
func (this *SpeedStatus) GetTitle() (title string) {
|
||||
this.progressLocker.Lock()
|
||||
defer this.progressLocker.Unlock()
|
||||
|
||||
return this.progressBarTitle
|
||||
}
|
||||
func (this *SpeedStatus) SetProgressBarTitle(title string) {
|
||||
this.progressLocker.Lock()
|
||||
this.progressBarTitle = title
|
||||
this.progressLocker.Unlock()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package m3u8d
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSpeedStatus_GetPercent(t *testing.T) {
|
||||
var status SpeedStatus
|
||||
status.SpeedResetBytes()
|
||||
}
|
||||
Loading…
Reference in New Issue