Newer
Older
//
// tank
//
// Import and Playlist Daemon for autoradio project
//
//
// Copyright (C) 2017-2018 Christian Pointner <equinox@helsinki.at>
//
// This file is part of tank.
//
// tank is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// tank is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with tank. If not, see <http://www.gnu.org/licenses/>.
//
package importer
import (
ErrNotImplemented = errors.New("not implemented")
ErrNotFound = errors.New("not found")
ErrSourceNotSupported = errors.New("source uri format is not supported")
ErrImportNotRunning = errors.New("import not running")
ErrSourceAlreadyAttached = errors.New("source is already attached")
ErrFileNotNew = errors.New("importing already running or done")
ErrTooManyJobs = errors.New("too many pending jobs")
ErrAlreadyCanceled = errors.New("job is already canceled")
type SourceURL url.URL
func (s *SourceURL) String() string {
return (*url.URL)(s).String()
}
func (s *SourceURL) MarshalText() (data []byte, err error) {
data = []byte(s.String())
return
}
func (s *SourceURL) UnmarshalText(data []byte) (err error) {
_, err = (*url.URL)(s).Parse(string(data))
return
}
//******* Source
type JobSource struct {
len uint64
r io.Reader
}
// it is important that JobCanceled is smaller than any other state of the job
// see job.Cancel() for why this is!
JobCanceled JobState = iota
JobNew
JobInitializing
JobPending
JobRunning
JobDestroying
)
func (s *JobState) String() string {
switch JobState(atomic.LoadUint32((*uint32)(s))) {
case JobNew:
return "new"
case JobInitializing:
return "initializing"
case JobPending:
return "pending"
case JobRunning:
return "running"
case JobDestroying:
return "destroying"
}
return "unknown"
}
func (s *JobState) fromString(str string) error {
switch str {
case "new":
atomic.StoreUint32((*uint32)(s), uint32(JobNew))
atomic.StoreUint32((*uint32)(s), uint32(JobInitializing))
atomic.StoreUint32((*uint32)(s), uint32(JobPending))
atomic.StoreUint32((*uint32)(s), uint32(JobRunning))
atomic.StoreUint32((*uint32)(s), uint32(JobDestroying))
default:
return errors.New("invalid job state: '" + str + "'")
}
return nil
}
func (s *JobState) MarshalText() (data []byte, err error) {
data = []byte(s.String())
return
}
func (s *JobState) UnmarshalText(data []byte) (err error) {
return s.fromString(string(data))
}
const (
StepFetching JobProgressStep = iota
StepNormalizing
)
func (s JobProgressStep) String() string {
switch s {
case StepFetching:
return "fetching"
case StepNormalizing:
return "normalizing"
}
return "unknown"
}
func (s JobProgressStep) MarshalText() (data []byte, err error) {
data = []byte(s.String())
return
}
func (p *JobProgress) set(step JobProgressStep, progress float32) {
tmp := uint64(step) << 32
tmp |= uint64(math.Float32bits(progress))
atomic.StoreUint64((*uint64)(p), tmp)
func (p *JobProgress) get() (step JobProgressStep, progress float32) {
tmp := atomic.LoadUint64((*uint64)(p))
step = JobProgressStep(tmp >> 32)
progress = math.Float32frombits(uint32(tmp))
return
}
func (p *JobProgress) MarshalJSON() ([]byte, error) {
step, progress := p.get()
return json.Marshal(struct {
Step JobProgressStep `json:"step"`
//******* Timestamp
type Timestamp int64
func (t *Timestamp) set(ts time.Time) {
atomic.StoreInt64((*int64)(t), ts.Unix())
}
func (t *Timestamp) get() (ts time.Time) {
return time.Unix(atomic.LoadInt64((*int64)(t)), 0)
}
func (t *Timestamp) MarshalJSON() (data []byte, err error) {
return t.get().MarshalJSON()
}