summaryrefslogtreecommitdiff
path: root/internal/media/media.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/media/media.go')
-rw-r--r--internal/media/media.go110
1 files changed, 70 insertions, 40 deletions
diff --git a/internal/media/media.go b/internal/media/media.go
index aa11787b2..022de063e 100644
--- a/internal/media/media.go
+++ b/internal/media/media.go
@@ -33,15 +33,15 @@ type Media struct {
below fields represent the processing state of the media thumbnail
*/
- thumbing processState
- thumb *ImageMeta
+ thumbstate processState
+ thumb *ImageMeta
/*
below fields represent the processing state of the full-sized media
*/
- processing processState
- processed *ImageMeta
+ fullSizeState processState
+ fullSize *ImageMeta
/*
below pointers to database and storage are maintained so that
@@ -58,20 +58,20 @@ func (m *Media) Thumb(ctx context.Context) (*ImageMeta, error) {
m.mu.Lock()
defer m.mu.Unlock()
- switch m.thumbing {
+ switch m.thumbstate {
case received:
// we haven't processed a thumbnail for this media yet so do it now
thumb, err := deriveThumbnail(m.rawData, m.attachment.File.ContentType)
if err != nil {
m.err = fmt.Errorf("error deriving thumbnail: %s", err)
- m.thumbing = errored
+ m.thumbstate = errored
return nil, m.err
}
// put the thumbnail in storage
if err := m.storage.Put(m.attachment.Thumbnail.Path, thumb.image); err != nil {
m.err = fmt.Errorf("error storing thumbnail: %s", err)
- m.thumbing = errored
+ m.thumbstate = errored
return nil, m.err
}
@@ -89,12 +89,12 @@ func (m *Media) Thumb(ctx context.Context) (*ImageMeta, error) {
if err := m.database.Put(ctx, m.attachment); err != nil {
if err != db.ErrAlreadyExists {
m.err = fmt.Errorf("error putting attachment: %s", err)
- m.thumbing = errored
+ m.thumbstate = errored
return nil, m.err
}
if err := m.database.UpdateByPrimaryKey(ctx, m.attachment); err != nil {
m.err = fmt.Errorf("error updating attachment: %s", err)
- m.thumbing = errored
+ m.thumbstate = errored
return nil, m.err
}
}
@@ -103,7 +103,7 @@ func (m *Media) Thumb(ctx context.Context) (*ImageMeta, error) {
m.thumb = thumb
// we're done processing the thumbnail!
- m.thumbing = complete
+ m.thumbstate = complete
fallthrough
case complete:
return m.thumb, nil
@@ -111,46 +111,76 @@ func (m *Media) Thumb(ctx context.Context) (*ImageMeta, error) {
return nil, m.err
}
- return nil, fmt.Errorf("thumbnail processing status %d unknown", m.thumbing)
+ return nil, fmt.Errorf("thumbnail processing status %d unknown", m.thumbstate)
}
-func (m *Media) Full(ctx context.Context) (*ImageMeta, error) {
- var clean []byte
- var err error
- var original *ImageMeta
-
- ct := m.attachment.File.ContentType
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- switch ct {
- case mimeImageJpeg, mimeImagePng:
- // first 'clean' image by purging exif data from it
- var exifErr error
- if clean, exifErr = purgeExif(m.rawData); exifErr != nil {
- return nil, fmt.Errorf("error cleaning exif data: %s", exifErr)
+func (m *Media) FullSize(ctx context.Context) (*ImageMeta, error) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ switch m.fullSizeState {
+ case received:
+ var clean []byte
+ var err error
+ var decoded *ImageMeta
+
+ ct := m.attachment.File.ContentType
+ switch ct {
+ case mimeImageJpeg, mimeImagePng:
+ // first 'clean' image by purging exif data from it
+ var exifErr error
+ if clean, exifErr = purgeExif(m.rawData); exifErr != nil {
+ err = exifErr
+ break
+ }
+ decoded, err = decodeImage(clean, ct)
+ case mimeImageGif:
+ // gifs are already clean - no exif data to remove
+ clean = m.rawData
+ decoded, err = decodeGif(clean)
+ default:
+ err = fmt.Errorf("content type %s not a processible image type", ct)
}
- original, err = decodeImage(clean, ct)
- case mimeImageGif:
- // gifs are already clean - no exif data to remove
- clean = m.rawData
- original, err = decodeGif(clean)
- default:
- err = fmt.Errorf("content type %s not a processible image type", ct)
- }
- if err != nil {
- return nil, err
+ if err != nil {
+ m.err = err
+ m.fullSizeState = errored
+ return nil, err
+ }
+
+ // set the fullsize of this media
+ m.fullSize = decoded
+
+ // we're done processing the full-size image
+ m.fullSizeState = complete
+ fallthrough
+ case complete:
+ return m.fullSize, nil
+ case errored:
+ return nil, m.err
}
- return original, nil
+ return nil, fmt.Errorf("full size processing status %d unknown", m.fullSizeState)
}
+// PreLoad begins the process of deriving the thumbnail and encoding the full-size image.
+// It does this in a non-blocking way, so you can call it and then come back later and check
+// if it's finished.
func (m *Media) PreLoad(ctx context.Context) {
go m.Thumb(ctx)
- m.mu.Lock()
- defer m.mu.Unlock()
+ go m.FullSize(ctx)
}
-func (m *Media) Load() {
- m.mu.Lock()
- defer m.mu.Unlock()
+// Load is the blocking equivalent of pre-load. It makes sure the thumbnail and full-size image
+// have been processed, then it returns the full-size image.
+func (m *Media) Load(ctx context.Context) (*gtsmodel.MediaAttachment, error) {
+ if _, err := m.Thumb(ctx); err != nil {
+ return nil, err
+ }
+
+ if _, err := m.FullSize(ctx); err != nil {
+ return nil, err
+ }
+
+ return m.attachment, nil
}