Commit 464508ba authored by Juergen Enge's avatar Juergen Enge
Browse files

audio/video viewer added

parent 6b64a8cc
Pipeline #13795 passed with stages
in 3 minutes and 25 seconds
......@@ -125,6 +125,7 @@ func main() {
// add some helpful actions
srv.AddAction(memostream.NewActionImageIIIF(srv))
srv.AddAction(memostream.NewActionVideo(srv))
srv.AddAction(memostream.NewActionMaster(srv))
go func() {
......
package memostream
import (
"fmt"
"net/http"
"strings"
)
// image Action using IIIF server for image manipulation
type ActionAudio struct {
ms *memoServer
}
func NewActionAudio(ms *memoServer) *ActionAudio {
aa := &ActionAudio{ms: ms}
return aa
}
func (aa *ActionAudio) GetType() []string { return []string{"video"} }
func (aa *ActionAudio) Do(w http.ResponseWriter, req *http.Request, me *MediaEntry, action string, params ...string) (bool, error) {
switch action {
case "viewer":
return aa.viewer(w, req, me, action, params...)
default:
}
return false, nil
}
func (aa *ActionAudio) viewer(w http.ResponseWriter, req *http.Request, me *MediaEntry, action string, params ...string) (bool, error) {
type vData struct {
AudioSource string
AudioTitle string
BackgroundColor string
}
var err error
newtoken := ""
if me.Access != Media_Public {
newtoken, err = NewJWT(aa.ms.jwtSecret, me.Signature, aa.ms.jwtAlg[0], 7200, "", "")
if err != nil {
return false, fmt.Errorf("Cannot create token: %v", err)
}
}
scheme := "http"
if req.TLS != nil {
scheme = "https"
}
data := vData{
AudioSource: fmt.Sprintf("%s://%s/%s/%s?auth=%s",
scheme,
req.Host,
strings.Trim(aa.ms.urlPrefix, "/"),
me.Signature,
newtoken),
AudioTitle: "Audio",
BackgroundColor: "#000000",
}
aa.ms.audioViewerTemplate.Execute(w, data)
return true, nil
}
......@@ -4,6 +4,7 @@ import (
"fmt"
"github.com/goph/emperror"
"net/http"
"path/filepath"
"regexp"
"strconv"
"strings"
......@@ -34,10 +35,22 @@ func (iai *ActionImageIIIF) Do(w http.ResponseWriter, req *http.Request, me *Med
return iai.resize(w, req, me, action, params...)
case "viewer":
return iai.viewer(w, req, me, action, params...)
case "iiif":
return iai.iiif(w, req, me, action, params...)
default:
}
return false, nil
}
func (iai *ActionImageIIIF) iiif(w http.ResponseWriter, req *http.Request, me *MediaEntry, action string, params ...string) (bool, error) {
if !iai.ms.fspool.Exist(me.URI) {
return false, fmt.Errorf("file not found: %v", me.URI)
}
if err := iai.ms.proxyIIIF(req, w, me.Signature, filepath.ToSlash(iai.ms.fspool.Truename(me.URI)), strings.Join(params, "/"), me.Access == Media_Public); err != nil {
return false, fmt.Errorf("cannot proxy to iiif server: %v", err)
}
return true, nil
}
func (iai *ActionImageIIIF) viewer(w http.ResponseWriter, req *http.Request, me *MediaEntry, action string, params ...string) (bool, error) {
type vData struct {
......
......@@ -15,22 +15,31 @@ func NewActionMaster(ms *memoServer) *ActionMaster {
return am
}
func (am *ActionMaster) GetType() []string { return []string{"image", "video", "audio"} }
func (am *ActionMaster) GetType() []string { return []string{"image", "video", "audio", "unknown"} }
func (am *ActionMaster) Do(w http.ResponseWriter, req *http.Request, me *MediaEntry, action string, params ...string) (bool, error) {
if action != "master" {
if action != "master" && action != "" {
return false, nil
}
w.Header().Set("Content-Disposition", fmt.Sprintf("filename=\"%s\"", me.Signature))
reader, modTime, err := am.ms.fspool.OpenUri(me.URI)
if err != nil {
return false, fmt.Errorf("cannot open uri %s: %v", me.URI, err)
switch me.Protocol {
case Media_File: // stream the file directly
w.Header().Set("Content-Disposition", fmt.Sprintf("filename=\"%s\"", me.Signature))
reader, modTime, err := am.ms.fspool.OpenUri(me.URI)
if err != nil {
return false, fmt.Errorf("cannot open uri %s: %v", me.URI, err)
}
defer reader.Close()
http.ServeContent(w, req, me.Signature, modTime, reader)
case Media_Redirect: // just redirect
http.Redirect(w, req, me.URI.String(),
http.StatusTemporaryRedirect)
case Media_Proxy: // do all the proxy stuff
w.Header().Set("Content-Disposition", fmt.Sprintf("filename=\"%s\"", me.Signature))
proxy(me.URI, w, req)
default: // don't know what to do
return false, fmt.Errorf("only type \"file\", \"redirect\" and \"proxy\" is supported for signature %v: type %v given", me.Signature, me.getProtocolString())
}
defer reader.Close()
http.ServeContent(w, req, me.Signature, modTime, reader)
return true, nil
}
package memostream
import (
"fmt"
"net/http"
"strings"
)
// image Action using IIIF server for image manipulation
type ActionVideo struct {
ms *memoServer
}
func NewActionVideo(ms *memoServer) *ActionVideo {
av := &ActionVideo{ms: ms}
return av
}
func (av *ActionVideo) GetType() []string { return []string{"video"} }
func (av *ActionVideo) Do(w http.ResponseWriter, req *http.Request, me *MediaEntry, action string, params ...string) (bool, error) {
switch action {
case "viewer":
return av.viewer(w, req, me, action, params...)
default:
}
return false, nil
}
func (av *ActionVideo) viewer(w http.ResponseWriter, req *http.Request, me *MediaEntry, action string, params ...string) (bool, error) {
type vData struct {
BackgroundColor string
VideoSource string
VideoType string
}
var err error
newtoken := ""
if me.Access != Media_Public {
newtoken, err = NewJWT(av.ms.jwtSecret, me.Signature, av.ms.jwtAlg[0], 7200, "", "")
if err != nil {
return false, fmt.Errorf("Cannot create token: %v", err)
}
}
scheme := "http"
if req.TLS != nil {
scheme = "https"
}
data := vData{
BackgroundColor: "#000000",
VideoSource: fmt.Sprintf("%s://%s/%s/%s/master?auth=%s",
scheme,
req.Host,
strings.Trim(av.ms.urlPrefix, "/"),
me.Signature,
newtoken),
VideoType: "video/mp4",
}
av.ms.videoViewerTemplate.Execute(w, data)
return true, nil
}
......@@ -11,12 +11,10 @@
package memostream
import (
"fmt"
"github.com/gorilla/mux"
"net/http"
"net/http/httputil"
"net/url"
"path/filepath"
"strings"
)
......@@ -66,6 +64,9 @@ func (ms *memoServer) mainHandler(w http.ResponseWriter, req *http.Request) {
}
}
if me.Type == "" {
me.Type = "unknown"
}
if actions, ok := ms.actions[me.Type]; ok {
for _, a := range actions {
ok, err := a.Do(w, req, me, action, strings.Split(params, "/")...)
......@@ -78,100 +79,6 @@ func (ms *memoServer) mainHandler(w http.ResponseWriter, req *http.Request) {
}
}
}
// todo: create better code here
if action == "audio" && params == "view" {
type vData struct {
AudioSource string
AudioTitle string
BackgroundColor string
}
newtoken := ""
if me.Access != Media_Public {
newtoken, err = NewJWT(ms.jwtSecret, signature, ms.jwtAlg[0], 7200, "", "")
if err != nil {
ms.DoPanicf(w, http.StatusInternalServerError, "Cannot create token: %v", err)
return
}
}
scheme := "http"
if req.TLS != nil {
scheme = "https"
}
data := vData{
AudioSource: fmt.Sprintf("%s://%s/%s/%s?auth=%s",
scheme,
req.Host,
strings.Trim(ms.urlPrefix, "/"),
signature,
newtoken),
AudioTitle: "Audio",
BackgroundColor: "#000000",
}
ms.audioViewerTemplate.Execute(w, data)
return
}
if action == "video" && params == "view" {
type vData struct {
BackgroundColor string
VideoSource string
VideoType string
}
newtoken := ""
if me.Access != Media_Public {
newtoken, err = NewJWT(ms.jwtSecret, signature, ms.jwtAlg[0], 7200, "", "")
if err != nil {
ms.DoPanicf(w, http.StatusInternalServerError, "Cannot create token: %v", err)
return
}
}
scheme := "http"
if req.TLS != nil {
scheme = "https"
}
data := vData{
BackgroundColor: "#000000",
VideoSource: fmt.Sprintf("%s://%s/%s/%s?auth=%s",
scheme,
req.Host,
strings.Trim(ms.urlPrefix, "/"),
signature,
newtoken),
VideoType: "video/mp4",
}
ms.videoViewerTemplate.Execute(w, data)
return
}
if action == "iiif" && params == "info.json" {
if !ms.fspool.Exist(me.URI) {
ms.DoPanicf(w, http.StatusNotFound, "file not found: %v", me.URI)
return
}
if err := ms.proxyIIIF(req, w, signature, filepath.ToSlash(ms.fspool.Truename(me.URI)), params, me.Access == Media_Public); err != nil {
ms.DoPanicf(w, http.StatusInternalServerError, "cannot proxy to iiif server: %v", err)
return
}
return
}
switch me.Protocol {
case Media_File: // stream the file directly
rsc, modTime, err := ms.fspool.OpenUri(me.URI)
if err != nil {
ms.DoPanicf(w, http.StatusNotFound, "cannot create reader from url %s for signature %s: %v", me.URI.String(), signature, err)
return
}
defer rsc.Close()
http.ServeContent(w, req, NameFromUri(me.URI), modTime, rsc)
case Media_Redirect: // just redirect
http.Redirect(w, req, me.URI.String(),
http.StatusTemporaryRedirect)
case Media_Proxy: // do all the proxy stuff
proxy(me.URI, w, req)
default: // don't know what to do
ms.DoPanicf(w, http.StatusNotImplemented, "only type \"file\", \"redirect\" and \"proxy\" is supported for signature %v: type %v given", signature, me.getProtocolString())
return
}
ms.DoPanicf(w, http.StatusInternalServerError, "Cannot execute action %s on signature %s: %v", action, me.Signature, err)
return
}
......@@ -60,7 +60,7 @@ func (rdm *ResolverDBMySQL) Resolve(signature string) (*MediaEntry, error) {
case sql.ErrNoRows: // dataset not found
return nil, emperror.Wrapf(err, "cannot find signature %s", signature)
case nil: // all fine, dataset found
if !typ.Valid {
if !typ.Valid && protocol == "file" {
return nil, fmt.Errorf("no metadata for signature %s", signature)
}
return NewMediaEntry(
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment