2020-12-25 20:54:59 +00:00
|
|
|
package tm
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"github.com/umlock-music/cli/algo/common"
|
|
|
|
)
|
|
|
|
|
2020-12-26 07:03:34 +00:00
|
|
|
var replaceHeader = []byte{0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70}
|
|
|
|
var magicHeader = []byte{0x51, 0x51, 0x4D, 0x55} //0x15, 0x1D, 0x1A, 0x21
|
2020-12-25 20:54:59 +00:00
|
|
|
|
|
|
|
type Decoder struct {
|
2020-12-26 07:03:34 +00:00
|
|
|
file []byte
|
|
|
|
audio []byte
|
|
|
|
headerMatch bool
|
|
|
|
audioExt string
|
2020-12-25 20:54:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Decoder) GetCoverImage() []byte {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Decoder) GetAudioData() []byte {
|
2020-12-26 07:03:34 +00:00
|
|
|
return d.audio
|
2020-12-25 20:54:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Decoder) GetAudioExt() string {
|
2020-12-26 07:03:34 +00:00
|
|
|
return d.audioExt
|
2020-12-25 20:54:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Decoder) GetMeta() common.Meta {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Decoder) Validate() error {
|
|
|
|
if len(d.file) < 8 {
|
|
|
|
return errors.New("invalid file size")
|
|
|
|
}
|
2020-12-26 07:03:34 +00:00
|
|
|
if !bytes.Equal(magicHeader, d.file[:4]) {
|
2020-12-25 20:54:59 +00:00
|
|
|
return errors.New("not a valid tm file")
|
|
|
|
}
|
2020-12-26 07:03:34 +00:00
|
|
|
d.headerMatch = true
|
2020-12-25 20:54:59 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Decoder) Decode() error {
|
2020-12-26 07:03:34 +00:00
|
|
|
d.audio = d.file
|
|
|
|
if d.headerMatch {
|
|
|
|
for i := 0; i < 8; i++ {
|
|
|
|
d.audio[i] = replaceHeader[i]
|
|
|
|
}
|
|
|
|
d.audioExt = "m4a"
|
|
|
|
}
|
2020-12-25 20:54:59 +00:00
|
|
|
return nil
|
|
|
|
}
|
2020-12-26 07:47:10 +00:00
|
|
|
|
2020-12-26 08:07:48 +00:00
|
|
|
//goland:noinspection GoUnusedExportedFunction
|
2020-12-26 07:47:10 +00:00
|
|
|
func NewDecoder(data []byte) common.Decoder {
|
|
|
|
return &Decoder{file: data}
|
|
|
|
}
|
|
|
|
|
2020-12-26 08:07:48 +00:00
|
|
|
func DecoderFuncWithExt(ext string) common.NewDecoderFunc {
|
|
|
|
return func(file []byte) common.Decoder {
|
|
|
|
return &Decoder{file: file, audioExt: ext}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-26 07:47:10 +00:00
|
|
|
func init() {
|
|
|
|
// QQ Music IOS M4a
|
2020-12-26 08:07:48 +00:00
|
|
|
common.RegisterDecoder("tm2", DecoderFuncWithExt("m4a"))
|
|
|
|
common.RegisterDecoder("tm6", DecoderFuncWithExt("m4a"))
|
2020-12-26 07:47:10 +00:00
|
|
|
// QQ Music IOS Mp3
|
2020-12-26 08:07:48 +00:00
|
|
|
common.RegisterDecoder("tm0", common.DecoderFuncWithExt("mp3"))
|
|
|
|
common.RegisterDecoder("tm3", common.DecoderFuncWithExt("mp3"))
|
2020-12-26 07:47:10 +00:00
|
|
|
|
|
|
|
}
|