From dead3a16bc7f928c86fbd92ef7ce7444b03ac79c Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Mon, 17 Jun 2024 09:44:11 -0500 Subject: [PATCH] adding some details to readme, todo, and emacs interface --- README.org | 2 + TODO.org | 3 +- src/emacs/lumina.el | 188 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 src/emacs/lumina.el diff --git a/README.org b/README.org index 585f3b5..532b2db 100644 --- a/README.org +++ b/README.org @@ -4,6 +4,8 @@ * Introduction This is an attempt at building a church presentation application in Qt/QML. QML provides a very powerful and easy declarative way of creating a UI so it should also be a very simple method of creating on screen slides and presentations. This experiment is to see how difficult it is to rebuild these applications in QML as opposed to other more complicated systems. After digging through the source code of OpenLP, I discovered they are essentially creating a web server and rendering a webpage onto the screen to show slides. This felt like a waste of resources and added complexity when something so simple and useful as QML exists. +In hind site, I may have been a bit too harsh on how OpenLP chose to create slides, that said, my focus was on simplicity and an actual working program so that I could do my work from linux and not need windows. This has now given a lot more programming experience and have rewritten parts of this project twice now. Potentially to do it again. + ** Features (planned are in parentheses) - Presents songs lyrics with image and video backgrounds - Use MPV as a rendering system for videos diff --git a/TODO.org b/TODO.org index 7fc973d..0d4d267 100644 --- a/TODO.org +++ b/TODO.org @@ -4,13 +4,14 @@ :CATEGORY: dev :END: -* Tasks [64%] [54/84] +* Tasks [63%] [54/85] ** TODO [#B] start and end times for videos :feature: This is something I couldn't get right in my head and plans and I hope rust will help me to solve it. I've got a sorta working concept. It hinges on MPV's --start and --end properties. We'll use this to make sure the video has the right settings. But, when switching to another video, we'll need to reset it. It does reset, but doesn't if the video we are switching to is the same video, but different start and end times. This could be problematic if the user wanted to have two sections of the same video loaded. For say a teaching moment or something like that. +** TODO Plugin architecture with steel or some scheme as an extension language ** TODO Refactor service_item_model.rs and slide_model.rs I've been thinking about my design of the service item model and slide model classes and believe I've used way too many properties for these models than is necessary. Instead I would really only need to have the title, type, and ids of the various items in the other models, then find a way to look them up when requesting them for the slide_object. diff --git a/src/emacs/lumina.el b/src/emacs/lumina.el new file mode 100644 index 0000000..98b7a9e --- /dev/null +++ b/src/emacs/lumina.el @@ -0,0 +1,188 @@ +;;; lumina.el -*- lexical-binding: t; -*- + +(require 'cl-lib) +(require 'request) + +(defvar lumina-db (sqlite-open "~/.local/share/lumina/library-db.sqlite3")) + +(defvar lumina-songs (sqlite-select lumina-db "select * from songs;")) + +(defvar lumina-songs-set (sqlite-select lumina-db "select * from songs;" nil :set)) + +(defvar lumina-buffer) + +(define-derived-mode lumina-mode tabulated-list-mode "lumina:songs" + "A mode for working with the lumina database and updating and adding songs" + (setf tabulated-list-format ['("Title" 10 t) + '("Lyrics" 30 nil) + '("Author" 10 t) + '("CCLI" 7 nil) + '("B" 1 nil) + '("BT" 10 nil) + '("h" 1 nil) + '("v" 1 nil) + '("f" 10 nil) + '("fs" 2 nil)])) + +(defun lumina-get-ids () + "Gets the ids of all songs in the sql result" + (cl-loop for song in lumina-songs + collect (car song))) + +(defun lumina-get-songs () + "Gets the songs from the sql result without the id" + (cl-loop for song in lumina-songs + collect (seq--into-vector (cdr song)))) + +(defun lumina-table () + "creates the list necessary for the tabulated-list-entries table") + +(cl-mapcar #'cons (lumina-get-ids) (lumina-get-songs)) + +(defun lumina () + "Start lumina up" + (interactive) + (setf lumina-buffer (get-buffer-create "*lumina*")) + (with-current-buffer lumina-buffer + (lumina-mode) + (setf tabulated-list-entries + (cl-mapcar #'list (lumina-get-ids) (lumina-get-songs))) + (tabulated-list-print t t)) + (switch-to-buffer lumina-buffer)) + +;;Elements are in this order, id, title, lyrics, author, +;;ccli, audio file, verse order, background, background type, +;;halign, valign, font, fontsize + +(defun lumina-select-song () + "Select which song to edit" + (interactive) + (with-current-buffer (get-buffer-create "*lumina*") + (org-mode) + (delete-region (point-min) (point-max)) + (point-min) + (let* ((title (completing-read "Select a song: " (cl-loop for song in lumina-songs + collect (cadr song)))) + (song (cl-loop for song in lumina-songs + when (string= (cadr song) title) + return song)) + (lyrics (elt song 2)) + (author (elt song 3)) + (ccli (elt song 4)) + (audio (elt song 5)) + (verse-order (elt song 6)) + (background (elt song 7)) + (background-type (elt song 8)) + (halign (elt song 9)) + (valign (elt song 10)) + (font (elt song 11)) + (font-size (elt song 12))) + (insert (concat "#+TITLE: " title)) + (newline) + (insert (concat "#+AUTHOR: " author)) + (newline) + (insert (concat "#+AUDIO: " audio)) + (newline) + (insert (concat "#+VERSE_ORDER: " verse-order)) + (newline) + (insert (concat "#+BACKGROUND: " background)) + (newline) + (insert (concat "#+BACKGROUND_TYPE: " background-type)) + (newline) + (insert (concat "#+HALIGN: " halign)) + (newline) + (insert (concat "#+VALIGN: " valign)) + (newline) + (insert (concat "#+FONT: " font)) + (newline) + (insert (concat "#+FONT_SIZE: " (number-to-string font-size))) + (newline) + (newline) + (insert (concat "* Lyrics\n" lyrics)) + (print song) + (setf lumina-current-song title))) + (switch-to-buffer "*lumina*")) + +(defvar lumina-current-song) + +(defun lumina-grab-lyrics () + (with-current-buffer (get-buffer "*lumina*") + (goto-char (point-min)) + (search-forward "* Lyrics") + (next-line) + (move-to-left-margin) + (buffer-substring-no-properties (point) (point-max)))) + +(defun lumina-get-verse-order () + (with-current-buffer (get-buffer "*lumina*") + (goto-char (point-min)) + (search-forward "#+VERSE_ORDER: ") + (buffer-substring-no-properties (point) nil))) + +(defvar lumina-lyrics-update-query + (concat "update songs set lyrics = \"?" + (lumina-grab-lyrics) + "\" where title = " + lumina-current-song)) + +(defun lumina-update-lyrics () + "Update the lyrics in the db" + (interactive) + (sqlite-execute lumina-db + "update songs set lyrics = ? where title = ?" + `(,(lumina-grab-lyrics) ,lumina-current-song)) + (setf lumina-songs (sqlite-select lumina-db "select * from songs;"))) + + +(defun lumina-get-lyrics-genius (song) + "retrieve lyrics to a song from genius lyrics" + (let* ((url (concat "https://api.genius.com/search?" + "access_token=" + "R0Y0ZW50Il9LSh5su3LKfdyfmQRx41NpVvLFJ0VxMo-hQ_4H1OVg_IE0Q-UUoFQx" + "&q=" + song)) + (songs + (cl-loop for song across + (cdr (cadadr + (plz 'get (url-encode-url url) :as #'json-read))) + collect `(,(concat + (cdr (elt (elt song 3) 19)) " by " + (cdr (elt (elt (elt song 3) 23) 7)) + " with id " + (number-to-string + (cdr (elt (elt song 3) 7))))))) + (selected-song (completing-read "song? " songs)) + (id (replace-regexp-in-string "[^0-9]" "" selected-song))) + (plz 'get + (url-encode-url + (concat "https://api.genius.com/songs/" id + "?access_token=R0Y0ZW50Il9LSh5su3LKfdyfmQRx41NpVvLFJ0VxMo-hQ_4H1OVg_IE0Q-UUoFQx"))))) + +(defun lumina-presentation () + "Creates a lumina presentation from an org document") + +(defun lumina-add-item () + "add and item to the lumina presentation org buffer" + (interactive) + (with-current-buffer (get-buffer "*lumina*") + (goto-char (point-max)) + (insert " +* +:PROPERTIES: +:TITLE: +:AUTHOR: +:AUDIO: +:VERSE_ORDER: +:BACKGROUND: +:BACKGROUND_TYPE: +:HALIGN: +:VALIGN: +:FONT: +:FONT_SIZE: +:END: + +"))) + +(cdr (elt (elt (elt (lumina-get-lyrics-genius "Death Was Arrested") 0) 3) 7)) + +(lumina-get-lyrics-genius "Death Was Arrested")