package guess import ( "errors" "git.gammaspectra.live/S.O.N.G/Kirika/audio" "git.gammaspectra.live/S.O.N.G/Kirika/audio/format" "io" "path" "strings" ) type NullFormat struct { name string } func (f NullFormat) Name() string { return f.name } func (f NullFormat) DecoderDescription() string { return "null" } func (f NullFormat) EncoderDescription() string { return "null" } func (f NullFormat) Open(io.ReadSeekCloser) (audio.Source, error) { return nil, errors.New("null format") } func (f NullFormat) OpenAnalyzer(io.ReadSeekCloser) (audio.Source, format.AnalyzerChannel, error) { return nil, nil, errors.New("null format") } func (f NullFormat) Encode(audio.Source, io.WriteCloser, map[string]interface{}) error { return errors.New("null format") } func (f NullFormat) Identify([format.IdentifyPeekBytes]byte, string) bool { return false } var knownFormats []format.Format func AddFormat(format format.Format) { knownFormats = append(knownFormats, format) } func GetFormat(name string) format.Format { for _, formatEntry := range knownFormats { if formatEntry.Name() == name { return formatEntry } } return NullFormat{ name: name, } } func GetDecoder(name string) format.Decoder { for _, formatEntry := range knownFormats { if decoder, ok := formatEntry.(format.Decoder); ok && formatEntry.Name() == name { return decoder } } return NullFormat{ name: name, } } func GetAnalyzerDecoder(name string) format.AnalyzerDecoder { for _, formatEntry := range knownFormats { if decoder, ok := formatEntry.(format.AnalyzerDecoder); ok && formatEntry.Name() == name { return decoder } } return NullFormat{ name: name, } } func GetEncoder(name string) format.Encoder { for _, formatEntry := range knownFormats { if encoder, ok := formatEntry.(format.Encoder); ok && formatEntry.Name() == name { return encoder } } return NullFormat{ name: name, } } func GetDecoders(r io.ReadSeekCloser, pathName string) (decoders []format.Decoder, err error) { extension := strings.ToLower(strings.TrimPrefix(path.Ext(pathName), ".")) var startOffset int64 startOffset, err = r.Seek(0, io.SeekCurrent) if err != nil { return } var peek [format.IdentifyPeekBytes]byte if _, err = r.Read(peek[:]); err != nil { return } if _, err = r.Seek(startOffset, io.SeekStart); err != nil { return } for _, formatEntry := range knownFormats { if decoder, ok := formatEntry.(format.Decoder); ok { if decoder.Identify(peek, extension) { decoders = append(decoders, decoder) } } } if len(decoders) == 0 { return nil, errors.New("could not find decoder") } return } func Open(r io.ReadSeekCloser, decoders []format.Decoder) (source audio.Source, err error) { var startOffset int64 startOffset, err = r.Seek(0, io.SeekCurrent) for _, decoder := range decoders { if _, err = r.Seek(startOffset, io.SeekStart); err != nil { return } source, err = decoder.Open(r) if source != nil && err == nil { return } } //seek back if _, err = r.Seek(startOffset, io.SeekStart); err != nil { return } return nil, errors.New("could not open stream") } func OpenAnalyzer(r io.ReadSeekCloser, decoders []format.Decoder) (source audio.Source, analyzerChannel format.AnalyzerChannel, err error) { var startOffset int64 startOffset, err = r.Seek(0, io.SeekCurrent) for _, decoder := range decoders { if analyzer, ok := decoder.(format.AnalyzerDecoder); ok { if _, err = r.Seek(startOffset, io.SeekStart); err != nil { return } source, analyzerChannel, err = analyzer.OpenAnalyzer(r) if source != nil && err == nil { return } } } //seek back if _, err = r.Seek(startOffset, io.SeekStart); err != nil { return } return nil, nil, errors.New("could not open stream analyzer") }