diff options
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/app/app.go | 48 | ||||
| -rw-r--r-- | pkg/media/library.go | 51 | ||||
| -rw-r--r-- | pkg/media/video.go | 22 |
3 files changed, 93 insertions, 28 deletions
diff --git a/pkg/app/app.go b/pkg/app/app.go index 7774a71..1cf147e 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -1,12 +1,12 @@ package app import ( - "errors" "html/template" "log" "net" "net/http" + "github.com/fsnotify/fsnotify" "github.com/gorilla/mux" "github.com/wybiral/tube/pkg/media" ) @@ -14,7 +14,7 @@ import ( type App struct { Config *Config Library *media.Library - Playlist media.Playlist + Watcher *fsnotify.Watcher Templates *template.Template Listener net.Listener Router *mux.Router @@ -27,17 +27,12 @@ func NewApp(cfg *Config) (*App, error) { a := &App{ Config: cfg, } - lib := media.NewLibrary() - err := lib.Import(cfg.LibraryPath) + a.Library = media.NewLibrary() + w, err := fsnotify.NewWatcher() if err != nil { return nil, err } - a.Library = lib - pl := lib.Playlist() - if len(pl) == 0 { - return nil, errors.New("No valid videos found") - } - a.Playlist = pl + a.Watcher = w ln, err := newListener(cfg.Server) if err != nil { return nil, err @@ -59,12 +54,41 @@ func NewApp(cfg *Config) (*App, error) { } func (a *App) Run() error { + path := a.Config.LibraryPath + err := a.Library.Import(path) + if err != nil { + return err + } + a.Watcher.Add(path) + go a.watch() return http.Serve(a.Listener, a.Router) } +func (a *App) watch() { + for { + e, ok := <-a.Watcher.Events + if !ok { + return + } + if e.Op&fsnotify.Create > 0 { + // add new files to library + a.Library.Add(e.Name) + } else if e.Op&(fsnotify.Write|fsnotify.Chmod) > 0 { + // writes and chmods should remove old file before adding again + a.Library.Remove(e.Name) + a.Library.Add(e.Name) + } else if e.Op&(fsnotify.Remove|fsnotify.Rename) > 0 { + // remove and rename just remove file + // fsnotify will signal a Create event with the new file name + a.Library.Remove(e.Name) + } + } +} + func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) { log.Printf("/") - http.Redirect(w, r, "/"+a.Playlist[0].ID, 302) + pl := a.Library.Playlist() + http.Redirect(w, r, "/"+pl[0].ID, 302) } func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) { @@ -81,7 +105,7 @@ func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) { Playlist media.Playlist }{ Playing: playing, - Playlist: a.Playlist, + Playlist: a.Library.Playlist(), }) } diff --git a/pkg/media/library.go b/pkg/media/library.go index b18fe3a..337907d 100644 --- a/pkg/media/library.go +++ b/pkg/media/library.go @@ -2,11 +2,15 @@ package media import ( "io/ioutil" + "log" + "path/filepath" "sort" "strings" + "sync" ) type Library struct { + mu sync.RWMutex Videos map[string]*Video } @@ -23,30 +27,47 @@ func (lib *Library) Import(path string) error { return err } for _, info := range files { - name := info.Name() - v, err := ParseVideo(path + "/" + name) + err = lib.Add(path + "/" + info.Name()) if err != nil { // Ignore files that can't be parsed continue } - // Set modified date property - v.Modified = info.ModTime().Format("2006-01-02") - // Default title is filename - if v.Title == "" { - v.Title = name - } - // ID is name without extension - idx := strings.LastIndex(name, ".") - if idx == -1 { - idx = len(name) - } - v.ID = name[:idx] - lib.Videos[v.ID] = v } return nil } +func (lib *Library) Add(path string) error { + v, err := ParseVideo(path) + if err != nil { + return err + } + lib.mu.Lock() + defer lib.mu.Unlock() + lib.Videos[v.ID] = v + log.Println("Added:", path) + return nil +} + +func (lib *Library) Remove(path string) { + name := filepath.Base(path) + // ID is name without extension + idx := strings.LastIndex(name, ".") + if idx == -1 { + idx = len(name) + } + id := name[:idx] + lib.mu.Lock() + defer lib.mu.Unlock() + _, ok := lib.Videos[id] + if ok { + delete(lib.Videos, id) + log.Println("Removed:", path) + } +} + func (lib *Library) Playlist() Playlist { + lib.mu.RLock() + defer lib.mu.RUnlock() pl := make(Playlist, 0) for _, v := range lib.Videos { pl = append(pl, v) diff --git a/pkg/media/video.go b/pkg/media/video.go index bd0def8..f79ab44 100644 --- a/pkg/media/video.go +++ b/pkg/media/video.go @@ -2,6 +2,7 @@ package media import ( "os" + "strings" "github.com/dhowden/tag" ) @@ -21,14 +22,33 @@ func ParseVideo(path string) (*Video, error) { if err != nil { return nil, err } + info, err := f.Stat() + if err != nil { + return nil, err + } + modified := info.ModTime().Format("2006-01-02") + name := info.Name() + // ID is name without extension + idx := strings.LastIndex(name, ".") + if idx == -1 { + idx = len(name) + } + id := name[:idx] m, err := tag.ReadFrom(f) if err != nil { return nil, err } + title := m.Title() + // Default title is filename + if title == "" { + title = name + } v := &Video{ - Title: m.Title(), + ID: id, + Title: title, Album: m.Album(), Description: m.Comment(), + Modified: modified, } // Add thumbnail (if exists) p := m.Picture() |
