summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ass.go446
-rw-r--r--lib/go.mod17
-rw-r--r--lib/mkv.go297
-rw-r--r--lib/shared.go54
-rw-r--r--lib/utils.go220
5 files changed, 0 insertions, 1034 deletions
diff --git a/lib/ass.go b/lib/ass.go
deleted file mode 100644
index 7482ac8..0000000
--- a/lib/ass.go
+++ /dev/null
@@ -1,446 +0,0 @@
-package mkvlib
-
-import (
- "encoding/binary"
- "fmt"
- "github.com/antchfx/xmlquery"
- "github.com/asticode/go-astisub"
- "io"
- "log"
- "os"
- "path"
- "regexp"
- "strconv"
- "strings"
- "sync"
- "time"
-)
-
-const (
- ttx = "ttx"
- pyftsubset = "pyftsubset"
-)
-
-type fontInfo struct {
- file string
- str string
- index string
- oldName string
- newName string
- ttx string
- sFont string
-}
-
-type assProcessor struct {
- files []string
- _fonts string
- output string
- m map[string]*fontInfo
- fonts []string
- sFonts []string
- subtitles map[string]string
-}
-
-func (self *assProcessor) parse() bool {
- ec := 0
- self.subtitles = make(map[string]string)
- for _, file := range self.files {
- f, err := openFile(file, true, false)
- if err != nil {
- ec++
- } else {
- data, _ := io.ReadAll(f)
- str := string(data)
- if err == nil {
- self.subtitles[file] = str
- } else {
- ec++
- }
- }
- if ec > 0 {
- log.Printf(`Failed to read the ass file: "%s"`, file)
- }
- }
- if ec == 0 {
- reg, _ := regexp.Compile(`\{?\\fn@?([^\r\n\\\}]+)[\\\}]`)
- m := make(map[string]map[rune]bool)
- for k, v := range self.subtitles {
- subtitle, err := astisub.ReadFromSSA(strings.NewReader(v))
- if err != nil {
- ec++
- log.Printf(`Failed to read the ass file: "%s"`, k)
- continue
- }
- for _, item := range subtitle.Items {
- for _, _item := range item.Lines {
- for _, __item := range _item.Items {
- name := item.Style.InlineStyle.SSAFontName
- if __item.InlineStyle != nil {
- arr := reg.FindStringSubmatch(__item.InlineStyle.SSAEffect)
- if len(arr) > 1 {
- name = arr[1]
- }
- }
- if strings.HasPrefix(name, "@") && len(name) > 1 {
- name = name[1:]
- }
- if m[name] == nil {
- m[name] = make(map[rune]bool)
- }
- str := __item.Text
- for _, char := range str {
- m[name][char] = true
- }
- }
- }
- }
- }
- self.m = make(map[string]*fontInfo)
- reg, _ = regexp.Compile("[A-Za-z0-9]]")
- for k, v := range m {
- str := ""
- for _k, _ := range v {
- str += string(_k)
- }
- str = strings.TrimSpace(str)
- if str != "" {
- str = reg.ReplaceAllString(str, "")
- str += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
- reg, _ = regexp.Compile("[1234567890]")
- if reg.MatchString(str) {
- str = reg.ReplaceAllString(str, "")
- str += "1234567890"
- }
- self.m[k] = new(fontInfo)
- self.m[k].str = str
- self.m[k].oldName = k
- }
- }
- }
- if len(self.m) == 0 {
- log.Printf(`Not Found item in the ass file(s): "%d"`, len(self.files))
- }
- return ec == 0
-}
-
-func (self *assProcessor) getTTCCount(file string) int {
- f, err := openFile(file, true, false)
- if err == nil {
- defer func() { _ = f.Close() }()
- data := make([]byte, 4)
- if n, err := f.ReadAt(data, 8); err == nil && n == 4 {
- return int(binary.BigEndian.Uint32(data))
- }
- }
- return 0
-}
-
-func (self *assProcessor) dumpFont(file string, full bool) bool {
- ok := false
- count := 1
- _, n, _, _ := splitPath(file)
- if strings.HasSuffix(file, ".ttc") {
- count = self.getTTCCount(file)
- if count < 1 {
- log.Printf(`Failed to get the ttc font count: "%s".`, n)
- return ok
- }
- }
- for i := 0; i < count; i++ {
- fn := fmt.Sprintf("%s_%d.ttx", file, i)
- args := make([]string, 0)
- args = append(args, "-q")
- args = append(args, "-f")
- args = append(args, "-y", strconv.Itoa(i))
- args = append(args, "-o", fn)
- if !full {
- args = append(args, "-t", "name")
- }
- args = append(args, file)
- if p, err := newProcess(nil, nil, nil, "", ttx, args...); err == nil {
- s, err := p.Wait()
- ok = err == nil && s.ExitCode() == 0
- }
- if !ok {
- log.Printf(`Failed to dump font(%t): "%s"[%d].`, full, n, i)
- }
- }
- return ok
-}
-
-func (self *assProcessor) dumpFonts(files []string, full bool) bool {
- ok := 0
- l := len(files)
- wg := new(sync.WaitGroup)
- wg.Add(l)
- m := new(sync.Mutex)
- for _, item := range files {
- go func(_item string) {
- _ok := self.dumpFont(_item, full)
- if _ok {
- m.Lock()
- ok++
- m.Unlock()
- }
- wg.Done()
- }(item)
- }
- wg.Wait()
- return ok == l
-}
-
-func (self *assProcessor) getFontName(p string) []string {
- f, err := openFile(p, true, false)
- if err == nil {
- defer func() { _ = f.Close() }()
- names := make([]string, 0)
- if xml, err := xmlquery.Parse(f); err == nil {
- for _, v := range xml.SelectElements(`ttFont/name/namerecord[@platformID=3]`) {
- id := v.SelectAttr("nameID")
- name := strings.TrimSpace(v.FirstChild.Data)
- switch id {
- case "1":
- names = append(names, name)
- break
- case "4":
- names = append(names, name)
- break
- }
- }
- }
- return names
- }
- return nil
-}
-
-func (self *assProcessor) getFontsName() map[string][]string {
- files, _ := findPath(self._fonts, `\.ttx$`)
- l := len(files)
- wg := new(sync.WaitGroup)
- wg.Add(l)
- m := new(sync.Mutex)
- _m := make(map[string][]string)
- for _, item := range files {
- go func(_item string) {
- names := self.getFontName(_item)
- if len(names) > 0 {
- m.Lock()
- _m[_item] = names
- m.Unlock()
- }
- wg.Done()
- }(item)
- }
- wg.Wait()
- return _m
-}
-
-func (self *assProcessor) matchFonts() bool {
- if !self.dumpFonts(self.fonts, false) {
- return false
- }
- m := self.getFontsName()
- if len(m) > 0 {
- reg, _ := regexp.Compile(`_(\d+)\.ttx$`)
- for k, _ := range self.m {
- for _k, v := range m {
- for _, _v := range v {
- if _v == k {
- self.m[k].file = reg.ReplaceAllString(_k, "")
- self.m[k].ttx = _k
- self.m[k].index = reg.FindStringSubmatch(_k)[1]
- self.m[k].newName = randomStr(8)
- break
- }
- }
- }
- }
- }
- ok := true
- for _, v := range self.m {
- if v.file == "" {
- ok = false
- log.Printf(`Missing the font: "%s".`, v.oldName)
- }
- }
- return ok
-}
-
-func (self *assProcessor) createFontSubset(font *fontInfo) bool {
- ok := false
- fn := fmt.Sprintf(`%s.txt`, font.file)
- _, n, e, ne := splitPath(font.file)
- if e == ".ttc" {
- e = ".ttf"
- }
- if os.MkdirAll(self.output, os.ModePerm) != nil {
- log.Println("Failed to create the output folder.")
- return false
- }
- if os.WriteFile(fn, []byte(font.str), os.ModePerm) == nil {
- _fn := fmt.Sprintf("%s.%s%s", ne, font.newName, e)
- _fn = path.Join(self.output, _fn)
- args := make([]string, 0)
- args = append(args, "--text-file="+fn)
- args = append(args, "--output-file="+_fn)
- args = append(args, "--name-languages="+"*")
- args = append(args, "--font-number="+font.index)
- args = append(args, font.file)
- if p, err := newProcess(nil, nil, nil, "", pyftsubset, args...); err == nil {
- s, err := p.Wait()
- ok = err == nil && s.ExitCode() == 0
- }
- if !ok {
- log.Printf(`Failed to subset font: "%s"[%s].`, n, font.index)
- } else {
- font.sFont = _fn
- }
-
- } else {
- log.Printf(`Failed to write the font text: "%s".`, n)
- }
- return ok
-}
-
-func (self *assProcessor) createFontsSubset() bool {
- err := os.RemoveAll(self.output)
- if !(err == nil || err == os.ErrNotExist) {
- log.Println("Failed to clean the output folder.")
- return false
- }
- ok := 0
- l := len(self.m)
- wg := new(sync.WaitGroup)
- wg.Add(l)
- m := new(sync.Mutex)
- for _, item := range self.m {
- go func(_item *fontInfo) {
- _ok := self.createFontSubset(_item)
- if _ok {
- m.Lock()
- ok++
- m.Unlock()
- }
- wg.Done()
- }(item)
- }
- wg.Wait()
- return ok == l
-}
-
-func (self *assProcessor) changeFontName(font *fontInfo) bool {
- ec := 0
- if self.dumpFont(font.sFont, true) {
- fn := fmt.Sprintf("%s_0.ttx", font.sFont)
- f, err := openFile(fn, true, false)
- if err == nil {
- defer func() {
- _ = f.Close()
- _ = os.Remove(fn)
- }()
- if xml, err := xmlquery.Parse(f); err == nil {
- for _, v := range xml.SelectElements(`ttFont/name/namerecord`) {
- id := v.SelectAttr("nameID")
- switch id {
- case "0":
- v.FirstChild.Data = "Processed by " + LibFName + " at " + time.Now().Format("2006-01-02 15:04:05")
- break
- case "1", "3", "4", "6":
- v.FirstChild.Data = font.newName
- break
- }
- }
- str := `<?xml version="1.0" encoding="UTF-8"?>`
- str += xml.SelectElement("ttFont").OutputXML(true)
- if os.WriteFile(fn, []byte(str), os.ModePerm) == nil {
- args := make([]string, 0)
- args = append(args, "-q")
- args = append(args, "-f")
- args = append(args, "-o", font.sFont)
- args = append(args, fn)
- ok := false
- if p, err := newProcess(os.Stdin, nil, nil, "", ttx, args...); err == nil {
- s, err := p.Wait()
- ok = err == nil && s.ExitCode() == 0
- }
- if !ok {
- ec++
- _, n, _, _ := splitPath(font.sFont)
- log.Printf(`Failed to compile the font: "%s".`, n)
- }
- }
- } else {
- log.Printf(`Faild to change the font name: "%s".`, font.oldName)
- }
- }
- }
- return ec == 0
-}
-
-func (self *assProcessor) changeFontsName() bool {
- ok := 0
- l := len(self.m)
- wg := new(sync.WaitGroup)
- wg.Add(l)
- m := new(sync.Mutex)
- for _, item := range self.m {
- go func(_item *fontInfo) {
- _ok := self.changeFontName(_item)
- if _ok {
- m.Lock()
- ok++
- m.Unlock()
- }
- wg.Done()
- }(item)
- }
- wg.Wait()
- return ok == l
-}
-
-func (self *assProcessor) replaceFontNameInAss() bool {
- ec := 0
- m := make(map[string]map[string]bool)
- for _, v := range self.m {
- for f, s := range self.subtitles {
- if m[f] == nil {
- m[f] = make(map[string]bool)
- }
- n := regexp.QuoteMeta(v.oldName)
- reg, _ := regexp.Compile(fmt.Sprintf(`(Style:[^,\r\n]+,|\\fn)(@?)%s([,\\\}])`, n))
- if reg.MatchString(s) {
- r := fmt.Sprintf("${1}${2}%s${3}", v.newName)
- s = reg.ReplaceAllString(s, r)
- m[f][v.oldName] = true
- self.subtitles[f] = s
- }
- }
- }
- for f, s := range self.subtitles {
- comments := make([]string, 0)
- comments = append(comments, "[Script Info]")
- comments = append(comments, "; ----- Font subset begin -----")
- for k, _ := range m[f] {
- comments = append(comments, fmt.Sprintf("; Font subset: %s - %s", self.m[k].newName, k))
- }
- if len(comments) > 2 {
- comments = append(comments, "")
- comments = append(comments, "; Processed by "+LibFName+" at "+time.Now().Format("2006-01-02 15:04:05"))
- comments = append(comments, "; ----- Font subset end -----")
- comments = append(comments, "")
- s = strings.Replace(s, "[Script Info]\r\n", strings.Join(comments, "\r\n"), 1)
- _, n, _, _ := splitPath(f)
- fn := path.Join(self.output, n)
- ok := false
- if os.WriteFile(fn, []byte(s), os.ModePerm) == nil {
- ok = true
- } else {
- ec++
- }
- if !ok {
- log.Printf(`Failed to write the new ass file: "%s".`, fn)
- }
- }
- }
- return ec == 0
-}
diff --git a/lib/go.mod b/lib/go.mod
deleted file mode 100644
index 3be11ce..0000000
--- a/lib/go.mod
+++ /dev/null
@@ -1,17 +0,0 @@
-module mkvlib
-
-go 1.17
-
-require (
- github.com/antchfx/xmlquery v1.3.8
- github.com/asticode/go-astisub v0.19.0
-)
-
-require (
- github.com/antchfx/xpath v1.2.0 // indirect
- github.com/asticode/go-astikit v0.20.0 // indirect
- github.com/asticode/go-astits v1.8.0 // indirect
- github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
- golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
- golang.org/x/text v0.3.2 // indirect
-)
diff --git a/lib/mkv.go b/lib/mkv.go
deleted file mode 100644
index e5eeb85..0000000
--- a/lib/mkv.go
+++ /dev/null
@@ -1,297 +0,0 @@
-package mkvlib
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "log"
- "os"
- "path"
- "regexp"
- "strings"
-)
-
-const (
- mkvmerge = `mkvmerge`
- mkvextract = `mkvextract`
-)
-
-type mkvInfo struct {
- Attachments []struct {
- ID int `json:"id"`
- FileName string `json:"file_name"`
- Size int `json:"size"`
- ContentType string `json:"content_type"`
- } `json:"attachments"`
- Tracks []struct {
- ID int `json:"id"`
- Type string `json:"type"`
- Codec string `json:"codec"`
- Properties struct {
- Language string `json:"language"`
- TrackName string `json:"track_name"`
- } `json:"properties"`
- }
-}
-
-type mkvProcessor bool
-
-func (self *mkvProcessor) GetMKVInfo(file string) *mkvInfo {
- buf := bytes.NewBufferString("")
- if p, err := newProcess(nil, buf, nil, "", mkvmerge, "-J", file); err == nil {
- if s, err := p.Wait(); err == nil && s.ExitCode() == 0 {
- obj := new(mkvInfo)
- _ = json.Unmarshal(buf.Bytes(), obj)
- return obj
- }
- }
- return nil
-}
-
-func (self *mkvProcessor) DumpMKV(file, output string, subset bool) bool {
- ec := 0
- obj := self.GetMKVInfo(file)
- if obj == nil {
- log.Printf(`Failed to get the mkv file info: "%s".`, file)
- return false
- }
- attachments := make([]string, 0)
- tracks := make([]string, 0)
- for _, _item := range obj.Attachments {
- attachments = append(attachments, fmt.Sprintf(`%d:%s`, _item.ID, path.Join(output, "fonts", _item.FileName)))
- }
- for _, _item := range obj.Tracks {
- if _item.Type == "subtitles" {
- s := fmt.Sprintf(`%d_%s_%s`, _item.ID, _item.Properties.Language, _item.Properties.TrackName)
- if _item.Codec == "SubStationAlpha" {
- s += ".ass"
- } else {
- s += ".sub"
- }
- tracks = append(tracks, fmt.Sprintf(`%d:%s`, _item.ID, path.Join(output, s)))
- }
- }
- args := make([]string, 0)
- args = append(args, file)
- args = append(args, "attachments")
- args = append(args, attachments...)
- args = append(args, "tracks")
- args = append(args, tracks...)
- if p, err := newProcess(nil, nil, nil, "", mkvextract, args...); err == nil {
- s, err := p.Wait()
- ok := err == nil && s.ExitCode() == 0
- if ok {
- if subset {
- asses := make([]string, 0)
- for _, _item := range tracks {
- _arr := strings.Split(_item, ":")
- f := _arr[len(_arr)-1]
- if strings.HasSuffix(f, ".ass") {
- asses = append(asses, f)
- }
- if len(asses) > 0 {
- if !self.ASSFontSubset(asses, "", "", false) {
- ec++
- }
- }
- }
- }
- } else {
- ec++
- }
- } else {
- ec++
- }
- return ec == 0
-}
-
-func (self *mkvProcessor) CheckSubset(file string) (bool, bool) {
- obj := self.GetMKVInfo(file)
- if obj == nil {
- log.Printf(`Failed to get the mkv file info: "%s".`, file)
- return false, true
- }
- ass := false
- ok := false
- reg, _ := regexp.Compile(`\.[A-Z0-9]{8}\.\S+$`)
- for _, track := range obj.Tracks {
- ass = track.Type == "subtitles" && track.Codec == "SubStationAlpha"
- if ass {
- break
- }
- }
- for _, attachment := range obj.Attachments {
- ok = !ass || (strings.HasPrefix(attachment.ContentType, "font/") && reg.MatchString(attachment.FileName))
- if ok {
- break
- }
- }
- return !ass || (ass && ok), false
-}
-
-func (self *mkvProcessor) CreateMKV(file string, tracks, attachments []string, output, slang, stitle string, clean bool) bool {
- args := make([]string, 0)
- args = append(args, "--output", output)
- if clean {
- args = append(args, "--no-subtitles", "--no-attachments")
- }
- args = append(args, file)
- for _, _item := range attachments {
- args = append(args, "--attach-file", _item)
- }
- for _, _item := range tracks {
- _, _, _, f := splitPath(_item)
- _arr := strings.Split(f, "_")
- _sl := slang
- _st := stitle
- if len(_arr) > 1 {
- _sl = _arr[1]
- }
- if len(_arr) > 2 {
- _st = _arr[2]
- }
- if _sl != "" {
- args = append(args, "--language", "0:"+_sl)
- }
- if _st != "" {
- args = append(args, "--track-name", "0:"+_st)
- }
- args = append(args, _item)
- }
- if p, err := newProcess(nil, nil, nil, "", mkvmerge, args...); err == nil {
- s, err := p.Wait()
- return err == nil && s.ExitCode() == 0
- }
- return false
-}
-
-func (self *mkvProcessor) DumpMKVs(dir, output string, subset bool) bool {
- ec := 0
- files := findMKVs(dir)
- l := len(files)
- for i, item := range files {
- p := strings.TrimPrefix(item, dir)
- d, _, _, f := splitPath(p)
- p = path.Join(output, d, f)
- if !self.DumpMKV(item, p, subset) {
- ec++
- log.Printf(`Failed to dump the mkv file "%s".`, item)
- }
- log.Printf("Dump (%d/%d) done.", i+1, l)
- }
- return ec == 0
-}
-
-func (self *mkvProcessor) QueryFolder(dir string) []string {
- ec := 0
- lines := make([]string, 0)
- files := findMKVs(dir)
- l := len(files)
- for i, file := range files {
- a, b := self.CheckSubset(file)
- if b {
- ec++
- } else if !a {
- lines = append(lines, file)
- }
- log.Printf("Query (%d/%d) done.", i+1, l)
- }
- return lines
-}
-
-func (self *mkvProcessor) CreateMKVs(vDir, sDir, fDir, tDir, oDir string, slang, stitle string, clean bool) bool {
- ec := 0
- if tDir == "" {
- tDir = os.TempDir()
- }
- tDir = path.Join(tDir, randomStr(8))
- files, _ := findPath(vDir, fmt.Sprintf(`\.\S+$`))
- l := len(files)
- for i, item := range files {
- _, _, _, _f := splitPath(item)
- tmp, _ := findPath(sDir, fmt.Sprintf(`%s\S*\.\S+$`, regexp.QuoteMeta(_f)))
- asses := make([]string, 0)
- subs := make([]string, 0)
- p := path.Join(tDir, _f)
- for _, sub := range tmp {
- if strings.HasSuffix(sub, ".ass") {
- _, _, _, __f := splitPath(sub)
- _s := path.Join(p, __f) + ".ass"
- _ = copyFileOrDir(sub, _s)
- asses = append(asses, _s)
- } else {
- subs = append(subs, sub)
- }
- }
- attachments := make([]string, 0)
- tracks := make([]string, 0)
- if len(asses) > 0 {
- _ = os.RemoveAll(tDir)
- if !self.ASSFontSubset(asses, fDir, "", false) {
- ec++
- } else {
- __p := path.Join(p, "subsetted")
- attachments = findFonts(__p)
- tracks, _ = findPath(__p, `\.ass$`)
- }
- }
- tracks = append(tracks, subs...)
- fn := path.Join(oDir, _f) + ".mkv"
- if !self.CreateMKV(item, tracks, attachments, fn, slang, stitle, clean) {
- ec++
- }
- if ec > 0 {
- log.Printf(`Failed to create the mkv file: "%s".`, item)
- }
- log.Printf("Create (%d/%d) done.", i+1, l)
- }
- _ = os.RemoveAll(tDir)
- return ec == 0
-}
-
-func (self *mkvProcessor) MakeMKVs(dir, data, output, slang, sttlte string) bool {
- ec := 0
- files := findMKVs(dir)
- l := len(files)
- for i, item := range files {
- p := strings.TrimPrefix(item, dir)
- d, n, _, f := splitPath(p)
- p = path.Join(data, d, f)
- _p := path.Join(p, "subsetted")
- subs, _ := findPath(p, `\.sub`)
- asses, _ := findPath(_p, `\.ass$`)
- attachments := findFonts(_p)
- tracks := append(subs, asses...)
- fn := path.Join(output, d, n)
- if !self.CreateMKV(item, tracks, attachments, fn, slang, sttlte, true) {
- ec++
- log.Printf(`Faild to make the mkv file: "%s".`, item)
- }
- log.Printf("Make (%d/%d) done.", i+1, l)
- }
- return ec == 0
-}
-
-func (self *mkvProcessor) ASSFontSubset(files []string, fonts, output string, dirSafe bool) bool {
- if len(files) == 0 {
- return false
- }
- obj := new(assProcessor)
- obj.files = files
- obj._fonts = fonts
- obj.output = output
- d, _, _, _ := splitPath(obj.files[0])
- if obj._fonts == "" {
- obj._fonts += path.Join(d, "fonts")
- }
- if obj.output == "" {
- obj.output = d
- dirSafe = true
- }
- if dirSafe {
- obj.output = path.Join(obj.output, "subseted")
- }
- obj.fonts = findFonts(obj._fonts)
-
- return obj.parse() && obj.matchFonts() && obj.createFontsSubset() && obj.changeFontsName() && obj.replaceFontNameInAss()
-}
diff --git a/lib/shared.go b/lib/shared.go
deleted file mode 100644
index b0cfb2f..0000000
--- a/lib/shared.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package mkvlib
-
-import (
- "log"
- "os"
- "os/exec"
- "path/filepath"
- "runtime"
- "strings"
-)
-
-const libName = "mkvlib"
-const libVer = "v1.0.2"
-
-const LibFName = libName + " " + libVer
-
-var _instance *mkvProcessor
-
-func GetInstance() *mkvProcessor {
- ec := 0
- n := "PATH"
- s := ":"
- if runtime.GOOS == "windows" {
- n = "path"
- s = ";"
- }
- p := os.Getenv(n)
- if !strings.HasSuffix(p, s) {
- p += s
- }
- e, _ := os.Executable()
- e, _ = filepath.Split(e)
- p += e
- _ = os.Setenv(n, p)
- _, _ttx := exec.LookPath(ttx)
- _, _pyftsubset := exec.LookPath(pyftsubset)
- _, _mkvextract := exec.LookPath(mkvextract)
- _, _mkvmerge := exec.LookPath(mkvmerge)
- if _ttx != nil || _pyftsubset != nil {
- log.Printf(`Missing dependency: fonttools (need "%s" & "%s").`, ttx, pyftsubset)
- ec++
- }
- if _mkvextract != nil || _mkvmerge != nil {
- log.Printf(`Missing dependency: mkvtoolnix (need "%s" & "%s").`, mkvextract, mkvmerge)
- ec++
- }
- if ec > 0 {
- return nil
- }
- if _instance == nil {
- _instance = new(mkvProcessor)
- }
- return _instance
-}
diff --git a/lib/utils.go b/lib/utils.go
deleted file mode 100644
index a76a05d..0000000
--- a/lib/utils.go
+++ /dev/null
@@ -1,220 +0,0 @@
-package mkvlib
-
-import (
- "errors"
- "fmt"
- "io"
- "math/rand"
- "os"
- "os/exec"
- "path"
- "path/filepath"
- "regexp"
- "strings"
- "time"
-)
-
-func newProcess(stdin io.Reader, stdout, stderr io.Writer, dir, prog string, args ...string) (p *os.Process, err error) {
- cmd := exec.Command(prog, args...)
- if dir != "" {
- cmd.Dir = dir
- }
- if stdin != nil {
- cmd.Stdin = stdin
- }
- if stdout != nil {
- cmd.Stdout = stdout
- }
- if stderr != nil {
- cmd.Stderr = stderr
- }
- err = cmd.Start()
- if err == nil {
- p = cmd.Process
- }
- return
-}
-
-func newDir(path string) error {
- return os.MkdirAll(path, os.ModePerm)
-}
-
-func queryPath(path string, cb func(string) bool) error {
- return filepath.Walk(path, func(path string, f os.FileInfo, err error) error {
- if f == nil {
- return err
- }
- if f.IsDir() {
- return nil
- }
- if cb(path) {
- return nil
- }
- return errors.New("call cb return false")
- })
-}
-
-func findPath(path, expr string) (list []string, err error) {
- list = make([]string, 0)
- reg, e := regexp.Compile(expr)
- if e != nil {
- err = e
- return
- }
- err = queryPath(path, func(path string) bool {
- if expr == "" || reg.MatchString(path) {
- list = append(list, path)
- }
- return true
- })
- return
-}
-
-func copyFolder(src, dst string) error {
- e, f := isExists(src)
- if !e {
- return errors.New("src is not exists")
- }
- if !f {
- return errors.New("src is not folder")
- }
- if newDir(dst) != nil {
- return errors.New("faild to create dst folder")
- }
- s := len(src)
- if _, n, _, _ := splitPath(dst); n == "" {
- _, n, _, _ = splitPath(src)
- if n == "" {
- _, n, _, _ = splitPath(src[:len(src)-1])
- }
- dst = fmt.Sprintf("%s/%s", dst, n)
- }
- return filepath.Walk(src, func(path string, f os.FileInfo, err error) error {
- if f == nil {
- return err
- }
- if f.IsDir() {
- return nil
- }
- return copyFile(path, dst+"/"+path[s:])
- })
-}
-
-func newFile(fp string) (file *os.File, err error) {
- dir, _ := filepath.Split(fp)
- if dir != "" {
- err = newDir(dir)
- if err != nil {
- return
- }
- }
- if err == nil {
- file, err = os.Create(fp)
- }
- return
-}
-
-func openFile(filepath string, readOnly, create bool) (file *os.File, err error) {
- f := os.O_RDWR | os.O_CREATE
- if readOnly {
- f = os.O_RDONLY
- }
- file, err = os.OpenFile(filepath, f, os.ModePerm)
- if err != nil && create {
- file, err = newFile(filepath)
- }
- return
-}
-
-func copyFile(src, dst string) error {
- e, f := isExists(src)
- if !e {
- return errors.New("src is not exists")
- }
- if f {
- return errors.New("src is not file")
- }
- if _, n, _, _ := splitPath(dst); n == "" {
- _, n, _, _ = splitPath(src)
- dst = path.Join(dst, n)
- }
- sf, err := openFile(src, true, false)
- if err != nil {
- return err
- }
- defer sf.Close()
- df, err := openFile(dst, false, true)
- if err != nil {
- return err
- }
- defer df.Close()
-
- _, err = io.Copy(df, sf)
- return err
-}
-
-func splitPath(p string) (dir, name, ext, namewithoutext string) {
- dir, name = filepath.Split(p)
- ext = filepath.Ext(name)
- n := strings.LastIndex(name, ".")
- if n > 0 {
- namewithoutext = name[:n]
- }
- return
-}
-
-func isExists(path string) (exists bool, isFolder bool) {
- f, err := os.Stat(path)
- exists = err == nil || os.IsExist(err)
- if exists {
- isFolder = f.IsDir()
- }
- return
-}
-
-func copyFileOrDir(src, dst string) error {
- e, f := isExists(src)
- if !e {
- return errors.New("src is not exists")
- }
- if !f {
- return copyFile(src, dst)
- }
- return copyFolder(src, dst)
-}
-
-func randomStr(l int) string {
- str := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- bytes := []byte(str)
- var result []byte
- lstr := len(str) - 1
- for i := 0; i < l; i++ {
- n := randomNumber(0, lstr)
- result = append(result, bytes[n])
- }
- return string(result)
-}
-
-var r = rand.New(rand.NewSource(time.Now().UnixNano()))
-
-func randomN(n int) int {
- return r.Intn(n)
-}
-
-func randomNumber(min, max int) int {
- sub := max - min + 1
- if sub <= 1 {
- return min
- }
- return min + randomN(sub)
-}
-
-func findMKVs(dir string) []string {
- list, _ := findPath(dir, `\.mkv$`)
- return list
-}
-
-func findFonts(dir string) []string {
- list, _ := findPath(dir, `\.((ttf)|(otf)|(ttc)|(fon))$`)
- return list
-}