Skip to content
Snippets Groups Projects
types.go 4.95 KiB
Newer Older
  • Learn to ignore specific revisions
  • Christian Pointner's avatar
    Christian Pointner committed
    //
    //  tank
    //
    //  Import and Playlist Daemon for autoradio project
    //
    //
    
    //  Copyright (C) 2017-2019 Christian Pointner <equinox@helsinki.at>
    
    Christian Pointner's avatar
    Christian Pointner committed
    //
    //  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 store
    
    import (
    	"errors"
    
    Christian Pointner's avatar
    Christian Pointner committed
    	"time"
    
    
    	"github.com/jinzhu/gorm"
    
    	FileURIScheme = "file"
    
    
    	// well-known table names
    
    	migrationsTn = "__migrations__"
    
    Christian Pointner's avatar
    Christian Pointner committed
    
    	// fixtures
    
    //******* Errors
    
    // TODO: make all errors types???
    
    
    Christian Pointner's avatar
    Christian Pointner committed
    var (
    
    	ErrNotImplemented    = errors.New("not implemented")
    	ErrNotFound          = gorm.ErrRecordNotFound
    
    	ErrFileImportNotDone = errors.New("file import is not done")
    
    type ErrFileInUse struct {
    	Playlists Playlists `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)
    }
    
    
    	Name      string    `json:"name" gorm:"primary_key"`
    	CreatedAt time.Time `json:"created"`
    	UpdatedAt time.Time `json:"updated"`
    
    func (g Show) String() string {
    
    //******* Files
    
    
    type ImportState int
    
    const (
    	ImportNew ImportState = iota
    	ImportPending
    	ImportRunning
    	ImportDone
    	ImportAborted
    )
    
    func (s ImportState) String() string {
    	switch s {
    	case ImportNew:
    		return "new"
    	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 "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 ImportLogLine struct {
    // 	Timestamp time.Time `json:"timestamp"`
    // 	Message   string    `json:"message"`
    // }
    
    // type ImportLog []ImportLogLine
    
    // func (l ImportLog) Append(message string) {
    // 	l = append(l, ImportLogLine{time.Now(), message})
    // }
    
    
    type Import struct {
    
    	State ImportState `json:"state"`
    
    	//	Log     ImportLog   `json:"log"`
    }
    
    Christian Pointner's avatar
    Christian Pointner committed
    type FileSource struct {
    
    	URI    string `json:"uri" gorm:"size:1024"`
    
    	Hash   string `json:"hash"`
    	Import Import `json:"import" gorm:"embedded;embedded_prefix:import__"`
    
    Christian Pointner's avatar
    Christian Pointner committed
    }
    
    type FileMetadata struct {
    
    	// TODO: 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"`
    
    Christian Pointner's avatar
    Christian Pointner committed
    	// TODO: add more fields
    }
    
    type File struct {
    
    	ID        uint64        `json:"id" gorm:"primary_key"`
    	CreatedAt time.Time     `json:"created"`
    	UpdatedAt time.Time     `json:"updated"`
    
    	ShowName  string        `json:"show" gorm:"not null;index"`
    	Show      Show          `json:"-" gorm:"association_foreignkey:Name"`
    
    	Source    FileSource    `json:"source" gorm:"embedded;embedded_prefix:source__"`
    	Metadata  FileMetadata  `json:"metadata" gorm:"embedded;embedded_prefix:metadata__"`
    	Size      uint64        `json:"size"`
    	Duration  time.Duration `json:"duration"`
    
    //******* 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"`
    
    	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"`
    	ShowName    string          `json:"show" gorm:"not null;index"`
    	Show        Show            `json:"-" gorm:"association_foreignkey:Name"`
    	Entries     []PlaylistEntry `json:"entries,omitempty"`
    
    type Playlists []Playlist
    
    
    //****************