Kirika/audio/format/guess/guess.go

172 lines
3.7 KiB
Go

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")
}