Skip to content

Commit

Permalink
feat: play mp3 for LDOCE5++ now
Browse files Browse the repository at this point in the history
  • Loading branch information
ChaosNyaruko committed Aug 17, 2024
1 parent 054695e commit df303cc
Show file tree
Hide file tree
Showing 14 changed files with 98 additions and 90 deletions.
66 changes: 36 additions & 30 deletions decoder/mdx.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"path/filepath"
"reflect"
"strconv"
"strings"
"sync"
"time"
"unicode/utf16"
Expand Down Expand Up @@ -67,7 +68,7 @@ type Header struct {

func (m *MDict) Get(word string) string {
m.once.Do(m.dumpKeys)
log.Printf("Get %v from MDict", word)
log.Debugf("Get %v from MDict", word)
if index, ok := m.keymap[word]; ok {
return m.decodeString(m.readAtOffset(int(index)))
}
Expand All @@ -79,7 +80,7 @@ func (m *MDict) dumpKeys() {
for i, k := range m.keys {
key := m.decodeString(k.key)
if e, ok := m.keymap[key]; ok {
log.Printf("key existed: %v, %v->[%v], now: %v->%v",
log.Debugf("key existed: %v, %v->[%v], now: %v->%v",
key, m.keys[e].key, m.decodeString(m.readAtOffset(int(e))),
k, m.decodeString(m.readAtOffset(i)),
)
Expand All @@ -88,7 +89,7 @@ func (m *MDict) dumpKeys() {
m.keymap[key] = uint64(i)
}
if len(m.keymap) != m.numEntries {
log.Printf("dumpKeys: num entries number does not match: map[%d], numEntries:%v", len(m.keymap), m.numEntries)
log.Debugf("dumpKeys: num entries number does not match: map[%d], numEntries:%v", len(m.keymap), m.numEntries)
}
}

Expand All @@ -104,7 +105,7 @@ func (m *MDict) Keys() []string {
func (m *MDict) Decode(fileName string) error {
start := time.Now()
defer func() {
log.Printf("decode cost: %v", time.Since(start))
log.Debugf("decode cost: %v", time.Since(start))
}()
name, err := filepath.Abs(fileName)
if err != nil {
Expand Down Expand Up @@ -158,7 +159,7 @@ func (m *MDict) Decode(fileName string) error {
return err
}

log.Printf("header as structured: %+v\n", header)
log.Debugf("header as structured: %+v\n", header)
if header.GeneratedByEngineVersion != "2.0" {
log.Fatalf("TODO: Only 2.0 Version is supported!, but the input MDX file was generated by engine: %v",
header.GeneratedByEngineVersion)
Expand All @@ -180,16 +181,16 @@ func (m *MDict) Decode(fileName string) error {
return fmt.Errorf("decode keyword section: %v", err)
}
// offset, err := file.Seek(0, io.SeekCurrent)
// log.Printf("offset of Record start: %v, err: %v", offset, err)
// log.Debugf("offset of Record start: %v, err: %v", offset, err)
x := time.Now()
if err := m.decodeRecordSection(file); err != nil {
return fmt.Errorf("decode record section: %v", err)
}
log.Printf("decode record cost: %v", time.Since(x))
log.Debugf("decode record cost: %v", time.Since(x))
// The reader should be at EOF now
var eof = make([]byte, 1)
if n, err := file.Read(eof); err != nil && n == 0 {
// log.Printf("n: %v, err: %v", n, err)
// log.Debugf("n: %v, err: %v", n, err)
if errors.Is(err, io.EOF) {
return nil
}
Expand Down Expand Up @@ -217,7 +218,7 @@ func (m *MDict) readAtOffset(index int) []byte {
if index < len(m.keys)-1 {
end = int(m.keys[index+1].offset)
}
// log.Printf("len(m.keys)=%d, len(m.records)=%d, index: %d, start: %v, end: %v",
// log.Debugf("len(m.keys)=%d, len(m.records)=%d, index: %d, start: %v, end: %v",
// len(m.keys), len(m.records), index, start, end)
return m.records[start:end]
}
Expand All @@ -229,7 +230,7 @@ func (m *MDict) DumpDict() (map[string]string, error) {
}
start := time.Now()
defer func() {
log.Printf("dump dict cost: %v", time.Since(start))
log.Debugf("dump dict cost: %v", time.Since(start))
}()
res := make(map[string]string, m.numEntries)
total := 0
Expand Down Expand Up @@ -266,7 +267,7 @@ func (m *MDict) decodeKeyWordSection(fd io.Reader) error {
// ... ... ...
// key_blocks[num_blocks-1] varying ...

log.Printf("decoding keyword section")
log.Debugf("decoding keyword section")
var rawHeader = make([]byte, 40)
if err := binary.Read(fd, binary.BigEndian, rawHeader); err != nil {
return err
Expand Down Expand Up @@ -303,7 +304,7 @@ func (m *MDict) decodeKeyWordSection(fd io.Reader) error {
}

m.numEntries = int(header.NumEntries)
log.Printf("key header %#v", header)
log.Debugf("key header %#v", header)

// encrypted by the following C function
// #define SWAPNIBBLE(byte) (((byte)>>4) | ((byte)<<4))
Expand All @@ -320,19 +321,19 @@ func (m *MDict) decodeKeyWordSection(fd io.Reader) error {
}
compType := keyIndexEncrypted[:4]
compressedChecksum := keyIndexEncrypted[4:8]
// log.Printf("len(keyIndexEncrypted): %v, %v:%v:%v", len(keyIndexEncrypted), keyIndexEncrypted[:4], keyIndexEncrypted[4:8], keyIndexEncrypted[8:])
// log.Debugf("len(keyIndexEncrypted): %v, %v:%v:%v", len(keyIndexEncrypted), keyIndexEncrypted[:4], keyIndexEncrypted[4:8], keyIndexEncrypted[8:])
keyIndexDecrypted := keyIndexEncrypted
encrypted := (m.encrypted & 2) != 0
if encrypted {
// Decrypt keyword Index if encrypted
// After this, we will get compressed keyword Index
log.Printf("keyword index encrypted, decrypt it")
log.Debugf("keyword index encrypted, decrypt it")
keyIndexDecrypted = keywordIndexDecrypt(keyIndexEncrypted)
}
// log.Printf("len(keyIndexDecrypted): %v, %v:%v:%v", len(keyIndexDecrypted), keyIndexDecrypted[:4], keyIndexDecrypted[4:8], keyIndexDecrypted[8:])
// log.Debugf("len(keyIndexDecrypted): %v, %v:%v:%v", len(keyIndexDecrypted), keyIndexDecrypted[:4], keyIndexDecrypted[4:8], keyIndexDecrypted[8:])
keyIndexDecompressed := decompress(compType, compressedChecksum, keyIndexDecrypted[8:])

// log.Printf("keyIndexDecompressed len: %d", len(keyIndexDecompressed))
// log.Debugf("keyIndexDecompressed len: %d", len(keyIndexDecompressed))
if len(keyIndexDecompressed) != int(header.KeyIndexDecompLen) {
// TODO: according to the exsited Python implementation, this fields only existed in version >= 2
log.Fatalf("the length of decompressed part is wrong: expected: %v, got :%v", header.KeyIndexDecompLen, len(keyIndexDecompressed))
Expand Down Expand Up @@ -384,20 +385,20 @@ func (m *MDict) decodeKeyWordSection(fd io.Reader) error {
if err := binary.Read(r, binary.BigEndian, &compSize); err != nil {
return err
}
// log.Printf("comp len of key_blocks[%d], %v\n", i, compSize)
// log.Debugf("comp len of key_blocks[%d], %v\n", i, compSize)

var decompSize uint64
if err := binary.Read(r, binary.BigEndian, &decompSize); err != nil {
return err
}
// log.Printf("decomp len of key_blocks[%d], %v\n", i, decompSize)
// log.Debugf("decomp len of key_blocks[%d], %v\n", i, decompSize)
keyBlocks = append(keyBlocks, keyBlock{compSize, decompSize, numEntries, firstWord, lastWord})
}

log.Printf("total entries: %v", totalEntries)
log.Debugf("total entries: %v", totalEntries)
// decode key blocks
for _, b := range keyBlocks {
// log.Printf("decoding [%d]th key block", i)
// log.Debugf("decoding [%d]th key block", i)
compressed := make([]byte, b.comp)
if err := binary.Read(fd, binary.BigEndian, compressed); err != nil {
return err
Expand All @@ -413,7 +414,7 @@ func (m *MDict) decodeKeyWordSection(fd io.Reader) error {
}

func (m *MDict) splitKeyBlock(b []byte, keyNum int) {
// log.Printf("block %d, num: %d, %v", index, keyNum, b)
// log.Debugf("block %d, num: %d, %v", index, keyNum, b)
delimiterWidth := 1
delimiter := []byte{0x00}
if m.encoding == "UTF-16" {
Expand All @@ -430,7 +431,7 @@ func (m *MDict) splitKeyBlock(b []byte, keyNum int) {
p += delimiterWidth
}
p += delimiterWidth
// log.Printf("splitKeyBlock key[%v][%v] at offset [%d]\n", len(m.keys), m.decodeString(keyBytes), offset)
// log.Debugf("splitKeyBlock key[%v][%v] at offset [%d]\n", len(m.keys), m.decodeString(keyBytes), offset)
m.keys = append(m.keys, keyOffset{offset, keyBytes})
}
}
Expand All @@ -446,7 +447,7 @@ func (m *MDict) decodeRecordSection(fd io.Reader) error {
if err := binary.Read(fd, binary.BigEndian, &recordHeader); err != nil {
return err
}
// log.Printf("record header: %#v", recordHeader)
// log.Debugf("record header: %#v", recordHeader)
if int(recordHeader.NumEntries) != m.numEntries {
// The number of blocks does NOT need to be equal the number of keyword blocks. Big-endian.
// But the number of entries should be EQUAL to keyword_sect.num_entries. Big-endian.
Expand All @@ -464,7 +465,7 @@ func (m *MDict) decodeRecordSection(fd io.Reader) error {
total := 0
totalDecomp := 0
for i := uint64(0); i < recordHeader.NumBlocks; i++ {
// log.Printf("decoding [%d]th records sizes", i)
// log.Debugf("decoding [%d]th records sizes", i)
if err := binary.Read(fd, binary.BigEndian, &records[i]); err != nil {
return err
}
Expand All @@ -477,7 +478,7 @@ func (m *MDict) decodeRecordSection(fd io.Reader) error {
m.records = make([]byte, 0, totalDecomp)
// decompress record blocks
for i := uint64(0); i < recordHeader.NumBlocks; i++ {
// log.Printf("decoding [%d]th records sizes", i)
// log.Debugf("decoding [%d]th records sizes", i)
compressed := make([]byte, records[i].CompSize)
if err := binary.Read(fd, binary.BigEndian, compressed); err != nil {
return err
Expand Down Expand Up @@ -512,7 +513,7 @@ func keywordIndexDecrypt(data []byte) []byte {
}

func decompress(compType []byte, checksum []byte, before []byte) []byte {
// log.Printf("type: %v, checksum: %v", compType, checksum)
// log.Debugf("type: %v, checksum: %v", compType, checksum)
decompressed := bytes.NewBuffer([]byte{})
in := bytes.NewReader(before)
switch compType[0] {
Expand Down Expand Up @@ -540,7 +541,7 @@ func (m *MDict) DumpData() error {
}
start := time.Now()
defer func() {
log.Printf("dump data cost: %v", time.Since(start))
log.Debugf("dump data cost: %v", time.Since(start))
}()
m.once.Do(m.dumpKeys)
total := 0
Expand All @@ -550,18 +551,23 @@ func (m *MDict) DumpData() error {
// strip the leading "\"
r, size := utf8.DecodeRuneInString(fname)
if r != '\\' {
log.Printf("illegal fname: %q", fname)
log.Warnf("illegal fname: %q", fname)
continue
}
fname = fname[size:]
fname = strings.ReplaceAll(fname, "\\", "/")
log.Debugf("fname: %q, %q", fname, filepath.Dir(fname))
}
path := filepath.Join(util.TmpDir(), filepath.Dir(fname))
if err := os.MkdirAll(path, 0o755); err != nil {
log.Fatalf("make dir for %v err: %v", path, err)
}
// content := m.readAtOffset(i)
fname = filepath.Join(util.TmpDir(), fname)
if file, err := os.Create(fname); err != nil {
log.Fatalf("open %v err: %v", fname, err)
} else {
n, err := file.Write(m.readAtOffset(i))
log.Printf("DumpData [%d] to file: %v, n: %v, err: %v", i, fname, n, err)
log.Debugf("DumpData [%d] to file: %v, n: %v, err: %v", i, fname, n, err)
file.Close()
}

Expand Down
15 changes: 10 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ var engine = flag.String("e", "", "query engine, 'mdx' or others(online query)")
// TODO: prev work, for better source abstractions
var g = sources.G

func init() {
log.SetOutput(os.Stderr)
log.SetLevel(log.InfoLevel)
}

func main() {
flag.Parse()
if *help || flag.NFlag() == 0 || len(flag.Args()) > 0 {
Expand Down Expand Up @@ -104,7 +109,7 @@ func main() {
}
}
}
log.Printf("start a new server: %s/%s/%s/%s", network, addr, *renderFormat, *engine)
log.Debugf("start a new server: %s/%s/%s/%s", network, addr, *renderFormat, *engine)
g.Load()
l, err := net.Listen(network, addr)
if err != nil {
Expand Down Expand Up @@ -138,7 +143,7 @@ func main() {
log.Fatalf("getting ondict path error: %v", err)
}
network, address = autoNetworkAddressPosix(dp, "")
log.Printf("auto mode dp: %v, network: %v, address: %v", dp, network, address)
log.Debugf("auto mode dp: %v, network: %v, address: %v", dp, network, address)
netConn, err = net.DialTimeout(network, address, dialTimeout)

if err == nil { // detect an exsitng server, just forward a request
Expand Down Expand Up @@ -166,7 +171,7 @@ func main() {
"-e=" + *engine,
"-f=" + *renderFormat,
}
log.Printf("starting remote: %v", args)
log.Debugf("starting remote: %v", args)
if err := startRemote(dp, args...); err != nil {
log.Fatal(err)
}
Expand All @@ -185,7 +190,7 @@ func main() {
}
return
}
log.Printf("failed attempt #%d to connect to remote: %v\n", retry+2, err)
log.Debugf("failed attempt #%d to connect to remote: %v\n", retry+2, err)
// In case our failure was a fast-failure, ensure we wait at least
// f.dialTimeout before trying again.
if retry != retries-1 {
Expand Down Expand Up @@ -216,7 +221,7 @@ func main() {

func query(word string, e string, f string) string {
if err := history.Append(word); err != nil {
log.Printf("record %v err: %v", word, err)
log.Debugf("record %v err: %v", word, err)
}
if e == "" {
e = *engine
Expand Down
2 changes: 1 addition & 1 deletion remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func autoNetworkAddressPosix(goplsPath, id string) (network string, address stri
if err := cmd.Run(); err == nil {
pathHash = h.Sum(nil)
} else {
log.Printf("error getting current buildid: %v", err)
log.Debugf("error getting current buildid: %v", err)
sum := sha256.Sum256([]byte(goplsPath))
pathHash = sum[:]
}
Expand Down
30 changes: 13 additions & 17 deletions render/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type HTMLRender struct {
}

func (h *HTMLRender) Render() string {
if strings.HasPrefix(h.SourceType, LongmanEasy) {
if !strings.HasPrefix(h.SourceType, "LONGMAN") {
return h.Raw
}
info := strings.NewReader(h.Raw)
Expand All @@ -38,7 +38,7 @@ func (h *HTMLRender) Render() string {
var b bytes.Buffer
err = html.Render(&b, doc)
if err != nil {
log.Printf("html.Render err: %v", err)
log.Debugf("html.Render err: %v", err)
return h.Raw
}
return b.String()
Expand All @@ -53,28 +53,24 @@ func modifyImgSrc(n *html.Node) {
n.Attr[i].Val = "tmp/" + a.Val
}
}
// log.Printf("modifyImgSrc %#v", n)
// log.Debugf("modifyImgSrc %#v", n)
}

func replaceMp3(n *html.Node, val string, i int) {
new := fmt.Sprintf("/%s", url.QueryEscape(strings.TrimPrefix(val, "sound://")))
log.Infof("href sound: %v, new: %q", strings.TrimPrefix(val, "sound://"), new)
n.Attr[i].Val = new
}

func modifyHref(n *html.Node) {
for i, a := range n.Attr {
if a.Key == "href" {
if strings.HasPrefix(a.Val, "entry://") {
new := fmt.Sprintf("/dict?query=%s&engine=mdx&format=html", url.QueryEscape(strings.TrimPrefix(a.Val, "entry://")))
log.Printf("href entry: %v, new: %q", strings.TrimPrefix(a.Val, "entry://"), new)
log.Infof("href entry: %v, new: %q", strings.TrimPrefix(a.Val, "entry://"), new)
n.Attr[i].Val = new
} else if strings.HasPrefix(a.Val, "sound://") {
new := strings.Replace(a.Val, "sound://", "/", 1)
log.Printf("href sound: %v, new: %q", strings.TrimPrefix(a.Val, "sound://"), new)
n.Attr[i].Val = new
} else if strings.HasSuffix(a.Val, ".mp3") {
m := strings.Split(a.Val, "/")
if len(m) > 0 {
mp3Name := m[len(m)-1]
new := "/" + mp3Name
log.Printf("href sound-mp3: %v, new: %q", a.Val, new)
n.Attr[i].Val = new
}
replaceMp3(n, a.Val, i)
}
}
}
Expand All @@ -85,7 +81,7 @@ func dfs(n *html.Node, level int, parent *html.Node, ft string) string {
return ""
}
if IsElement(n, "a", "") {
log.Printf("<a> %v", n)
log.Debugf("<a> %v", n)
modifyHref(n)
return ""
}
Expand All @@ -108,7 +104,7 @@ func IsElement(n *html.Node, ele string, class string) bool {
}
for _, a := range n.Attr {
if a.Key == "class" && a.Val == class {
log.Printf("[wft] readElement good %v, %v, %#v", ele, class, n.Data)
log.Debugf("[wft] readElement good %v, %v, %#v", ele, class, n.Data)
return true
}
}
Expand Down
Loading

0 comments on commit df303cc

Please sign in to comment.