diff --git a/src/api/__init__.py b/src/api/__init__.py index 013dabd..1950571 100644 --- a/src/api/__init__.py +++ b/src/api/__init__.py @@ -24,13 +24,13 @@ def create_api(): from .controllers.user import user from .controllers.playlist import playlist - from .controllers.file import file + from .controllers.file import files from .controllers.auth import auth from .controllers.roles import roles_bp app.register_blueprint(user, url_prefix='/api') app.register_blueprint(playlist, url_prefix='/api') - app.register_blueprint(file, url_prefix='/api/file') + app.register_blueprint(files, url_prefix='/api') app.register_blueprint(auth, url_prefix='/api/auth') app.register_blueprint(roles_bp, url_prefix='/api') diff --git a/src/api/abl/PlaylistAbl.py b/src/api/abl/PlaylistAbl.py index 2be49e0..7bdad01 100644 --- a/src/api/abl/PlaylistAbl.py +++ b/src/api/abl/PlaylistAbl.py @@ -105,7 +105,7 @@ class PlaylistAbl: @staticmethod def remove_file(playlist_id, data): query = db.session.query(PlaylistFile) \ - .filter(PlaylistFile.id == data['id']) \ + .filter(PlaylistFile.file_id == data['file_id']) \ .first() db.session.delete(query) db.session.commit() diff --git a/src/api/controllers/file.py b/src/api/controllers/file.py index 863189a..41f03d0 100644 --- a/src/api/controllers/file.py +++ b/src/api/controllers/file.py @@ -2,15 +2,14 @@ from flask import Blueprint, request, jsonify, send_file from ..models import File from .. import db -file = Blueprint('file', __name__) +files = Blueprint('files', __name__) FILE_DIR = './data/' -@file.route('/', methods=['POST']) +@files.route('/files', methods=['POST']) def upload(): - files = request.files.getlist('file') - print(files) res = [] - for file in files: + for file_key in request.files: + file = request.files[file_key] exists = db.session.query(File).filter(File.name == file.filename).first() if not exists: file.save(FILE_DIR + file.filename) @@ -19,10 +18,10 @@ def upload(): db.session.flush() res.append(new_file.as_dict().copy()) - db.session.commit() - return jsonify(res) + db.session.commit() + return jsonify(res) -@file.route('/', methods=['GET']) +@files.route('/files', methods=['GET']) def list(): files = db.session.query(File).all() res = [] @@ -30,12 +29,12 @@ def list(): res.append(file.as_dict()) return jsonify(res) -@file.route('/', methods=['GET']) +@files.route('/files/', methods=['GET']) def load(file_id): file = db.session.query(File).filter(File.id == file_id).first() return send_file(('../../data/' + file.name), mimetype=file.type) -@file.route('/', methods=['DELETE']) +@files.route('/files/', methods=['DELETE']) def delete(file_id): rows = db.session.query(File).filter(File.id == file_id).all() for row in rows: diff --git a/src/api/models.py b/src/api/models.py index d13f128..30181eb 100644 --- a/src/api/models.py +++ b/src/api/models.py @@ -59,7 +59,7 @@ class Role(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), default=None) - permissions= db.Column(db.Integer, default=0) + permissions = db.Column(db.Integer, default=0) parent_id = db.Column(db.Integer, db.ForeignKey('role.id'), default=None) users = db.relationship('User', secondary='UserRole', back_populates='roles') playlists_view = db.relationship('Playlist', secondary='PlaylistView', back_populates='view') diff --git a/src/screen/SlideShow.py b/src/screen/SlideShow.py index e4b8293..ffb6e42 100644 --- a/src/screen/SlideShow.py +++ b/src/screen/SlideShow.py @@ -1,35 +1,145 @@ import tkinter as tk -from PIL import ImageTk, Image +import cv2 +from PIL import Image, ImageTk, Image +from tkvideo import tkvideo import time +import imageio class SlideShow: def __init__(self, root, files): + print(files) self.root = root self.files = files - self.idx = 0 + self.idx = -1 - self.image_label = tk.Label(root) - self.image_label.pack() - self.image_label.pack(fill=tk.BOTH, expand=True) + self.canvas = tk.Canvas(root, bg='black') + self.canvas.pack() + self.canvas.pack(fill=tk.BOTH, expand=True) + self.canvas.pack_propagate(False) self.root.after(100, self.next_file) def next_file(self): - file = self.files[self.idx] - path = './data/' + file['name'] - image = Image.open(path) + media = None + while media is None or not media.supported: + self.idx = (self.idx + 1) % len(self.files) + file = self.files[self.idx] + media = MediaFactory(self, file) + print(media.time) + print(self.idx) + + self.root.after(media.time, self.next_file) + + def resize_full_screen(self, image): # Get root window width and height screen_width = self.root.winfo_width() screen_height = self.root.winfo_height() # Resize the image to fit the screen - image = image.resize((screen_width, screen_height), Image.ANTIALIAS) + return image.resize((screen_width, screen_height), Image.BICUBIC) - photo = ImageTk.PhotoImage(image) - self.image_label.config(image=photo) - self.image_label.image = photo + def show_image(self, image): + self.image = image + self.canvas.create_image(0, 0, image=self.image, anchor=tk.NW) - self.idx = (self.idx + 1) % len(self.files) - self.root.after(file['seconds'] * 1000, self.next_file) +class MediaFactory: + def __init__(self, parent, file): + self.parent = parent + self.file = file + print(self.file) + self.supported = True + match file['type']: + case "image/gif": + self.gif_player() + case "image/jpeg" | "image/jpg": + self.image_player() + case "video/mp4": + self.video_player() + case _: + print(file['type'], " not supported") + self.supported = False + def image_player(self): + print("image player") + path = './data/' + self.file['name'] + image = Image.open(path) + + image = self.parent.resize_full_screen(image) + photo = ImageTk.PhotoImage(image=image) + self.parent.show_image(photo) + self.time = self.file['seconds'] * 1000 + + def video_player(self): + video_player = VideoPlayer(self.parent, self.file) + self.time = video_player.time + + def gif_player(self): + gif_player = GIFPlayer(self.parent, self.file) + self.time = gif_player.time + +class VideoPlayer: + def __init__(self, parent, file): + self.file = file + self.parent = parent + self.path = './data/' + self.file['name'] + + self.cap = cv2.VideoCapture(self.path) + + self.total_frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT)) + self.fps = int(self.cap.get(cv2.CAP_PROP_FPS)) + print(self.total_frames, self.fps) + self.time = int(self.total_frames * ((int(1000/self.fps)+1))) + self.time = 30 * 1000 + print(int(1000/self.fps)) + self.is_playing = True + self.i = 0 + self.update() + + def update(self): + if self.is_playing: + self.i = self.i + 1 + #print(self.i) + ret, frame = self.cap.read() + if ret: + image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) + image = self.parent.resize_full_screen(image) + photo = ImageTk.PhotoImage(image=image) + self.parent.show_image(photo) + else: + self.is_playing = False + self.cap.release() + self.parent.root.after(int(1000/self.fps), self.update) + +class GIFPlayer(): + def __init__(self, parent, file): + self.parent = parent + self.file = file + self.path = './data/' + self.file['name'] + self.current_frame = 0 + self.time = 0 + self.play_gif() + + + def load_gif_frames(self): + gif = Image.open(self.path) + frames = [] + try: + while True: + frames.append(ImageTk.PhotoImage(gif.copy())) + gif.seek(len(frames)) # Move to the next frame + except EOFError: + pass # Reached the end of the GIF + + return frames + + def play_gif(self): + try: + frame = ImageTk.PhotoImage(file=self.path, format="gif -index %i" %(self.current_frame)) + self.parent.label.config(image=frame) + self.parent.label.image = frame + + self.current_frame = self.current_frame + 1 + self.after((100), self.play_gif) + except: + pass