summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/app/app.go48
-rw-r--r--pkg/media/library.go51
-rw-r--r--pkg/media/video.go22
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()