Something went wrong on our end
-
Ernesto Rico Schmidt authoredErnesto Rico Schmidt authored
types.go 6.17 KiB
//
// tank, Import and Playlist Daemon for Aura project
// Copyright (C) 2017-2020 Christian Pointner <equinox@helsinki.at>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
package store
import (
"errors"
"fmt"
"sync"
"time"
"github.com/jinzhu/gorm"
)
const (
FileURIScheme = "file"
// well-known table names
migrationsTn = "__migrations__"
)
//******* Errors
var (
ErrNotImplemented = errors.New("not implemented")
ErrNotFound = gorm.ErrRecordNotFound
ErrShowAlreadyExists = errors.New("show already exists")
ErrFileNotNew = errors.New("file does not exist or is not new")
ErrFileImportNotDone = errors.New("file import is not done")
ErrPlaylistHasMultipleNullDurationEntries = errors.New("playlists may only have one entry without a duration")
)
type ErrFileInUse struct {
Playlists []Playlist `json:"playlists"`
}
func (e *ErrFileInUse) Error() string {
return fmt.Sprintf("the file is still in use by %d playlist(s)", len(e.Playlists))
}
type ErrInvalidMetadataField string
func (e ErrInvalidMetadataField) Error() string {
return "invalid metadata field: " + string(e)
}
type ErrInvalidPlaylistEntry struct {
idx int
message string
}
func (e ErrInvalidPlaylistEntry) Error() string {
return fmt.Sprintf("playlist entry #%d is invalid: %s", e.idx, e.message)
}
//******* Logs
type LogLine struct {
Stream string `json:"stream"`
Timestamp time.Time `json:"timestamp"`
Line string `json:"line"`
}
// This implements json.Marshaler and therefore doesn't need `lines` to be public.
type Log struct {
m sync.RWMutex
lines []LogLine
}
//******* Shows
type Show struct {
ID uint64 `json:"id" gorm:"primary_key"`
CreatedAt time.Time `json:"created"`
UpdatedAt time.Time `json:"updated"`
}
func (g Show) String() uint64 {
return g.ID
}
//******* Files
type ImportState int
const (
ImportNew ImportState = iota
ImportInitializing
ImportPending
ImportRunning
ImportDone
ImportAborted
)
func (s ImportState) String() string {
switch s {
case ImportNew:
return "new"
case ImportInitializing:
return "initializing"
case ImportPending:
return "pending"
case ImportRunning:
return "running"
case ImportDone:
return "done"
case ImportAborted:
return "aborted"
}
return "unknown"
}
func (s *ImportState) fromString(str string) error {
switch str {
case "new":
*s = ImportNew
case "initializing":
*s = ImportInitializing
case "pending":
*s = ImportPending
case "running":
*s = ImportRunning
case "done":
*s = ImportDone
case "aborted":
*s = ImportAborted
default:
return errors.New("invalid import state: '" + str + "'")
}
return nil
}
func (s ImportState) MarshalText() (data []byte, err error) {
data = []byte(s.String())
return
}
func (s *ImportState) UnmarshalText(data []byte) (err error) {
return s.fromString(string(data))
}
type Import struct {
State ImportState `json:"state" swaggertype:"string"`
Error string `json:"error,omitempty"`
}
type FileSource struct {
URI string `json:"uri" gorm:"size:1024"`
Hash string `json:"hash"`
Import Import `json:"import" gorm:"embedded;embedded_prefix:import__"`
}
type FileMetadata struct {
// actually a full-text index would be nice here...
Artist string `json:"artist,omitempty" gorm:"index"`
Title string `json:"title,omitempty" gorm:"index"`
Album string `json:"album,omitempty" gorm:"index"`
Organization string `json:"organization,omitempty" gorm:"index"`
ISRC string `json:"isrc,omitempty" gorm:"index"`
// TODO: add more fields...
}
type File struct {
ID uint64 `json:"id" gorm:"primary_key"`
CreatedAt time.Time `json:"created"`
UpdatedAt time.Time `json:"updated"`
ShowID uint64 `json:"showId" gorm:"not null;index"`
Show Show `json:"-" gorm:"association_foreignkey:ID"`
Source FileSource `json:"source" gorm:"embedded;embedded_prefix:source__"`
Metadata FileMetadata `json:"metadata" gorm:"embedded;embedded_prefix:metadata__"`
Size uint64 `json:"size"`
Duration float64 `json:"duration"`
}
//******* ImportLogs
type ImportLog struct {
ID uint64 `gorm:"primary_key"`
File File `gorm:"association_autoupdate:false;association_autocreate:false"`
FileID uint64 `gorm:"not null;index;unique_index:unique_import_log_step"`
ImportStep string `gorm:"not null;index;unique_index:unique_import_log_step"`
Encoded []byte `gorm:"size:-1"`
}
// Mind that ImportLogs is not []ImportLog but rather a map containing objects of type LOG
type ImportLogs map[string]*Log
//******* Playlists
type PlaylistEntry struct {
ID uint64 `json:"-" gorm:"primary_key"`
PlaylistID uint64 `json:"-" gorm:"not null;index;unique_index:unique_playlist_line_numbers"`
LineNum uint `json:"-" gorm:"not null;unique_index:unique_playlist_line_numbers"`
URI string `json:"uri" gorm:"size:1024"`
Duration *float64 `json:"duration,omitempty"`
File *File `json:"file,omitempty" gorm:"association_autoupdate:false;association_autocreate:false"`
FileID *uint64 `json:"-" gorm:"index"`
}
type Playlist struct {
ID uint64 `json:"id" gorm:"primary_key"`
CreatedAt time.Time `json:"created"`
UpdatedAt time.Time `json:"updated"`
Description string `json:"description"`
PlayoutMode string `json:"playoutMode" gorm:"not null;default:'linear'"`
ShowID uint64 `json:"showId" gorm:"not null;index"`
Show Show `json:"-" gorm:"association_foreignkey:ID"`
Entries []PlaylistEntry `json:"entries"`
}
//****************