Added tune previews
This commit is contained in:
@@ -4,16 +4,16 @@
|
|||||||
** TODO Ordenar els resultats de la cerca de temes
|
** TODO Ordenar els resultats de la cerca de temes
|
||||||
** TODO Suport per a diverses organitzacions (no només jam de Sant Cugat)
|
** TODO Suport per a diverses organitzacions (no només jam de Sant Cugat)
|
||||||
** TODO Usuaris i permisos granulars
|
** TODO Usuaris i permisos granulars
|
||||||
** TODO Arreglar visualitzador de pdf, suportar més d'un visualitzador per pàgina
|
|
||||||
** Lilypond support (o similar)
|
** Lilypond support (o similar)
|
||||||
*** TODO Fer cançoners "en directe"
|
*** TODO Fer cançoners "en directe"
|
||||||
*** DONE Suport de caràcters especials (al títol i més llocs?)
|
*** DONE Suport de caràcters especials (al títol i més llocs?)
|
||||||
*** DONE Mostrar partitura als enllaços (resultats de cerca)
|
*** DONE Mostrar partitura als enllaços (resultats de cerca)
|
||||||
** DONE Arreglar estadístiques de temes (dos temes tocats a la mateixa sessió compten un cop)
|
** DONE Arreglar estadístiques de temes (dos temes tocats a la mateixa sessió compten un cop)
|
||||||
|
** TODO Arreglar visualitzador de pdf, suportar més d'un visualitzador per pàgina
|
||||||
* Idees
|
* Idees
|
||||||
** Jams
|
** Jams
|
||||||
*** Properes jams
|
*** Properes jams
|
||||||
**** Info dels temes que es tocaràn (a la slow jam)
|
**** Info dels temes que es tocaran (a la slow jam)
|
||||||
** Temes
|
** Temes
|
||||||
*** Navegació
|
*** Navegació
|
||||||
**** Cerca de temes
|
**** Cerca de temes
|
||||||
|
|||||||
@@ -35,64 +35,12 @@ async def set_score(
|
|||||||
score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id)
|
score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id)
|
||||||
if not score:
|
if not score:
|
||||||
raise HTTPException(status_code=404, detail="Could not find lyric!")
|
raise HTTPException(status_code=404, detail="Could not find lyric!")
|
||||||
|
new_score = await scores_service.render_score(score=score, title=title, source=source)
|
||||||
tune = lilypond_build.tune_from_tema_id(tema_id=tema_id, score_source=source)
|
|
||||||
tune_source = lilypond_source.tune_source(tune=tune)
|
|
||||||
pdf_result, png_result = await render_tune(tune_source=tune_source, tema_id=tema_id)
|
|
||||||
if errors := pdf_result.error:
|
|
||||||
new_score = dataclasses.replace(
|
|
||||||
score,
|
|
||||||
source=source,
|
|
||||||
title=title,
|
|
||||||
errors=errors,
|
|
||||||
)
|
|
||||||
elif png_result is None:
|
|
||||||
raise RuntimeError(f"Received empty png_result with pdf_result: {pdf_result}")
|
|
||||||
elif errors := png_result.error:
|
|
||||||
new_score = dataclasses.replace(
|
|
||||||
score,
|
|
||||||
source=source,
|
|
||||||
title=title,
|
|
||||||
errors=errors,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
pdf_file = pdf_result.result
|
|
||||||
png_file = png_result.result
|
|
||||||
new_score = dataclasses.replace(
|
|
||||||
score,
|
|
||||||
source=source,
|
|
||||||
title=title,
|
|
||||||
pdf_url=files.get_db_file_path(pdf_file) if pdf_file else None,
|
|
||||||
img_url=files.get_db_file_path(png_file) if png_file else None,
|
|
||||||
errors=[],
|
|
||||||
)
|
|
||||||
scores_service.update_score(score=new_score)
|
scores_service.update_score(score=new_score)
|
||||||
files.clean_orphan_files()
|
files.clean_orphan_files()
|
||||||
return scores_fragments.score(request=request, logged_in=logged_in, score=new_score)
|
return scores_fragments.score(request=request, logged_in=logged_in, score=new_score)
|
||||||
|
|
||||||
|
|
||||||
async def render_tune(
|
|
||||||
tune_source: str,
|
|
||||||
tema_id: int,
|
|
||||||
) -> tuple[lilypond_render.RenderResult, lilypond_render.RenderResult | None]:
|
|
||||||
async with files.tmp_file(content=tune_source) as source_file:
|
|
||||||
pdf_file = files.create_tema_filename(tema_id=tema_id)
|
|
||||||
pdf_result = await lilypond_render.render_file(
|
|
||||||
input_file=source_file,
|
|
||||||
output=lilypond_render.RenderOutput.PDF,
|
|
||||||
output_file=pdf_file,
|
|
||||||
)
|
|
||||||
if pdf_result.error:
|
|
||||||
return pdf_result, None
|
|
||||||
png_file = files.create_tema_filename(tema_id=tema_id)
|
|
||||||
png_result = await lilypond_render.render_file(
|
|
||||||
input_file=source_file,
|
|
||||||
output=lilypond_render.RenderOutput.PNG_CROPPED,
|
|
||||||
output_file=png_file,
|
|
||||||
)
|
|
||||||
return pdf_result, png_result
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/api/tema/{tema_id}/score")
|
@router.post("/api/tema/{tema_id}/score")
|
||||||
def add_score(
|
def add_score(
|
||||||
request: Request,
|
request: Request,
|
||||||
|
|||||||
@@ -693,10 +693,6 @@ video {
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table {
|
|
||||||
display: table;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -899,10 +895,6 @@ video {
|
|||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-b {
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.border-none {
|
.border-none {
|
||||||
border-style: none;
|
border-style: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,32 +12,34 @@
|
|||||||
<i>{{ query }}</i>
|
<i>{{ query }}</i>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<table class="text-left min-w-full w-full">
|
<ul class="text-left min-w-full w-full">
|
||||||
<tr class="border-b border-beige">
|
|
||||||
<td class="font-bold py-2 px-4">Nom</td>
|
|
||||||
<td class="font-bold py-2 px-4">Enllaços</td>
|
|
||||||
<td class="font-bold py-2 px-4">Cops tocat</td>
|
|
||||||
</tr>
|
|
||||||
{% for tema in temes %}
|
{% for tema in temes %}
|
||||||
<tr class="border-b border-beige">
|
<li class="flex flex-col
|
||||||
<td class="py-2 px-4">
|
m-4 rounded-lg
|
||||||
|
bg-white">
|
||||||
|
<div class="py-2 px-4 text-brown font-bold">
|
||||||
<a href="/tema/{{ tema.id }}">
|
<a href="/tema/{{ tema.id }}">
|
||||||
{{ tema.title }}
|
{{ tema.title }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</div>
|
||||||
<td class="py-2 px-4">
|
{% if tema.main_score() and tema.main_score().preview_url %}
|
||||||
{% include "fragments/temes/result_links.html" %}
|
<img class="p-2 max-w"
|
||||||
</td>
|
src="{{ tema.main_score().preview_url }}" />
|
||||||
<td class="py-2 px-4">
|
{% endif %}
|
||||||
{% if tema.stats is none %}
|
{% if tema.properties %}
|
||||||
-
|
<ul class="flex flex-wrap text-sm
|
||||||
{% else %}
|
py-2 px-4">
|
||||||
{{ tema.stats.times_played }}
|
{% for property in tema.properties %}
|
||||||
{% endif %}
|
<div class="bg-beige text-white rounded
|
||||||
</td>
|
m-1 px-2">
|
||||||
</tr>
|
{{ property.value }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</ul>
|
||||||
{% if prev_offset is not none or next_offset is not none %}
|
{% if prev_offset is not none or next_offset is not none %}
|
||||||
<div class="py-2">
|
<div class="py-2">
|
||||||
{% if prev_offset is not none %}
|
{% if prev_offset is not none %}
|
||||||
|
|||||||
10
folkugat_web/assets/templates/lilypond/preview.ly
Normal file
10
folkugat_web/assets/templates/lilypond/preview.ly
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
\version "2.24.4"
|
||||||
|
{% if tune.score_source is not none %}
|
||||||
|
\score {
|
||||||
|
\language "english"
|
||||||
|
<<
|
||||||
|
{{ score_beginning }}
|
||||||
|
{{ tune.score_source | safe }}
|
||||||
|
>>
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
@@ -79,6 +79,7 @@ def create_scores_table(con: Connection):
|
|||||||
errors TEXT NOT NULL,
|
errors TEXT NOT NULL,
|
||||||
img_url TEXT,
|
img_url TEXT,
|
||||||
pdf_url TEXT,
|
pdf_url TEXT,
|
||||||
|
preview_url TEXT,
|
||||||
hidden BOOLEAN,
|
hidden BOOLEAN,
|
||||||
FOREIGN KEY(tema_id) REFERENCES temes(id) ON DELETE CASCADE
|
FOREIGN KEY(tema_id) REFERENCES temes(id) ON DELETE CASCADE
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from folkugat_web.dal.sql import Connection, get_connection
|
|||||||
from folkugat_web.model import temes as model
|
from folkugat_web.model import temes as model
|
||||||
from folkugat_web.model.lilypond.processing import RenderError
|
from folkugat_web.model.lilypond.processing import RenderError
|
||||||
|
|
||||||
ScoreRowTuple = tuple[int, int, str, str, str, str | None, str | None, bool]
|
ScoreRowTuple = tuple[int, int, str, str, str, str | None, str | None, str | None, bool]
|
||||||
|
|
||||||
|
|
||||||
class ScoreRowDict(TypedDict):
|
class ScoreRowDict(TypedDict):
|
||||||
@@ -17,6 +17,7 @@ class ScoreRowDict(TypedDict):
|
|||||||
source: str
|
source: str
|
||||||
img_url: str | None
|
img_url: str | None
|
||||||
pdf_url: str | None
|
pdf_url: str | None
|
||||||
|
preview_url: str | None
|
||||||
hidden: bool
|
hidden: bool
|
||||||
|
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ def score_to_row(score: model.Score) -> ScoreRowDict:
|
|||||||
"source": score.source,
|
"source": score.source,
|
||||||
"img_url": score.img_url,
|
"img_url": score.img_url,
|
||||||
"pdf_url": score.pdf_url,
|
"pdf_url": score.pdf_url,
|
||||||
|
"preview_url": score.preview_url,
|
||||||
"hidden": score.hidden,
|
"hidden": score.hidden,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +45,8 @@ def row_to_score(row: ScoreRowTuple) -> model.Score:
|
|||||||
errors=list(map(RenderError.from_dict, errors_dicts)),
|
errors=list(map(RenderError.from_dict, errors_dicts)),
|
||||||
img_url=row[5],
|
img_url=row[5],
|
||||||
pdf_url=row[6],
|
pdf_url=row[6],
|
||||||
hidden=bool(row[7]),
|
preview_url=row[7],
|
||||||
|
hidden=bool(row[8]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -78,7 +81,7 @@ def get_scores(score_id: int | None = None, tema_id: int | None = None, con: Con
|
|||||||
|
|
||||||
query = f"""
|
query = f"""
|
||||||
SELECT
|
SELECT
|
||||||
id, tema_id, title, source, errors, img_url, pdf_url, hidden
|
id, tema_id, title, source, errors, img_url, pdf_url, preview_url, hidden
|
||||||
FROM tema_scores
|
FROM tema_scores
|
||||||
{filter_clause}
|
{filter_clause}
|
||||||
"""
|
"""
|
||||||
@@ -92,9 +95,9 @@ def insert_score(score: model.Score, con: Connection | None = None) -> model.Sco
|
|||||||
data = score_to_row(score)
|
data = score_to_row(score)
|
||||||
query = f"""
|
query = f"""
|
||||||
INSERT INTO tema_scores
|
INSERT INTO tema_scores
|
||||||
(id, tema_id, title, source, errors, img_url, pdf_url, hidden)
|
(id, tema_id, title, source, errors, img_url, pdf_url, preview_url, hidden)
|
||||||
VALUES
|
VALUES
|
||||||
(:id, :tema_id, :title, :source, :errors, :img_url, :pdf_url, :hidden)
|
(:id, :tema_id, :title, :source, :errors, :img_url, :pdf_url, :preview_url, :hidden)
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"""
|
"""
|
||||||
with get_connection(con) as con:
|
with get_connection(con) as con:
|
||||||
@@ -110,7 +113,7 @@ def update_score(score: model.Score, con: Connection | None = None):
|
|||||||
UPDATE tema_scores
|
UPDATE tema_scores
|
||||||
SET
|
SET
|
||||||
tema_id = :tema_id, title = :title, source = :source, errors = :errors,
|
tema_id = :tema_id, title = :title, source = :source, errors = :errors,
|
||||||
img_url = :img_url, pdf_url = :pdf_url, hidden = :hidden
|
img_url = :img_url, pdf_url = :pdf_url, preview_url = :preview_url, hidden = :hidden
|
||||||
WHERE
|
WHERE
|
||||||
id = :id
|
id = :id
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ from folkugat_web.model import temes as model
|
|||||||
from folkugat_web.model.lilypond.processing import RenderError
|
from folkugat_web.model.lilypond.processing import RenderError
|
||||||
from folkugat_web.model.pagines import Pages
|
from folkugat_web.model.pagines import Pages
|
||||||
from folkugat_web.services import sessions as sessions_service
|
from folkugat_web.services import sessions as sessions_service
|
||||||
from folkugat_web.services.temes import links as links_service
|
from folkugat_web.services.temes import properties as properties_service
|
||||||
from folkugat_web.services.temes import lyrics as lyrics_service
|
|
||||||
from folkugat_web.services.temes import query as temes_q
|
from folkugat_web.services.temes import query as temes_q
|
||||||
from folkugat_web.services.temes import scores as scores_service
|
from folkugat_web.services.temes import scores as scores_service
|
||||||
from folkugat_web.services.temes import search as temes_s
|
from folkugat_web.services.temes import search as temes_s
|
||||||
@@ -43,8 +42,7 @@ def temes_busca(request: Request, logged_in: bool, query: str, offset: int = 0,
|
|||||||
temes = (
|
temes = (
|
||||||
FnChain.transform(temes) |
|
FnChain.transform(temes) |
|
||||||
temes_q.temes_compute_stats |
|
temes_q.temes_compute_stats |
|
||||||
links_service.add_links_to_temes |
|
properties_service.add_properties_to_temes |
|
||||||
lyrics_service.add_lyrics_to_temes |
|
|
||||||
scores_service.add_scores_to_temes |
|
scores_service.add_scores_to_temes |
|
||||||
list
|
list
|
||||||
).result()
|
).result()
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ class Score:
|
|||||||
source: str
|
source: str
|
||||||
img_url: str | None
|
img_url: str | None
|
||||||
pdf_url: str | None
|
pdf_url: str | None
|
||||||
|
preview_url: str | None
|
||||||
hidden: bool
|
hidden: bool
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -81,6 +82,7 @@ class Score:
|
|||||||
errors=[],
|
errors=[],
|
||||||
img_url=link.url if link.link_type is LinkType.IMAGE else None,
|
img_url=link.url if link.link_type is LinkType.IMAGE else None,
|
||||||
pdf_url=link.url if link.link_type is LinkType.PDF else None,
|
pdf_url=link.url if link.link_type is LinkType.PDF else None,
|
||||||
|
preview_url=None,
|
||||||
hidden=False,
|
hidden=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,8 @@ def get_orphan_files() -> Iterator[Path]:
|
|||||||
link_urls = {link.url for link in links_dal.get_links()}
|
link_urls = {link.url for link in links_dal.get_links()}
|
||||||
score_pdf_urls = {score.pdf_url for score in scores_dal.get_scores() if score.pdf_url is not None}
|
score_pdf_urls = {score.pdf_url for score in scores_dal.get_scores() if score.pdf_url is not None}
|
||||||
score_img_urls = {score.img_url for score in scores_dal.get_scores() if score.img_url is not None}
|
score_img_urls = {score.img_url for score in scores_dal.get_scores() if score.img_url is not None}
|
||||||
alive_urls = link_urls | score_pdf_urls | score_img_urls
|
score_preview_urls = {score.preview_url for score in scores_dal.get_scores() if score.preview_url is not None}
|
||||||
|
alive_urls = link_urls | score_pdf_urls | score_img_urls | score_preview_urls
|
||||||
return filter(
|
return filter(
|
||||||
lambda p: p.is_file() and get_db_file_path(p) not in alive_urls,
|
lambda p: p.is_file() and get_db_file_path(p) not in alive_urls,
|
||||||
itertools.chain(
|
itertools.chain(
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ RenderResult = Result[Path, list[RenderError]]
|
|||||||
class RenderOutput(enum.Enum):
|
class RenderOutput(enum.Enum):
|
||||||
PDF = "pdf"
|
PDF = "pdf"
|
||||||
PNG_CROPPED = "png-cropped"
|
PNG_CROPPED = "png-cropped"
|
||||||
PNG_PREVIEW = "png-preview"
|
PREVIEW = "preview"
|
||||||
|
|
||||||
|
|
||||||
async def render(
|
async def render(
|
||||||
@@ -61,16 +61,16 @@ async def render_file(
|
|||||||
]
|
]
|
||||||
output_file = output_file.with_suffix(".cropped.png")
|
output_file = output_file.with_suffix(".cropped.png")
|
||||||
# output_file = output_file.with_suffix(".png")
|
# output_file = output_file.with_suffix(".png")
|
||||||
case RenderOutput.PNG_PREVIEW:
|
case RenderOutput.PREVIEW:
|
||||||
command = [
|
command = [
|
||||||
"lilypond",
|
"lilypond",
|
||||||
"-f", "png",
|
"-f", "svg",
|
||||||
"-dpreview=#t",
|
"-dpreview=#t",
|
||||||
"-dno-print-pages",
|
"-dno-print-pages",
|
||||||
"-o", str(output_file),
|
"-o", str(output_file),
|
||||||
str(input_file)
|
str(input_file)
|
||||||
]
|
]
|
||||||
output_file = output_file.with_suffix(".preview.png")
|
output_file = output_file.with_suffix(".preview.svg")
|
||||||
|
|
||||||
proc = await asyncio.create_subprocess_exec(
|
proc = await asyncio.create_subprocess_exec(
|
||||||
*command,
|
*command,
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ def tune_source(tune: LilypondTune) -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def preview_source(tune: LilypondTune) -> str:
|
||||||
|
return templates.get_template("lilypond/preview.ly").render(
|
||||||
|
score_beginning=SCORE_BEGINNING,
|
||||||
|
tune=tune,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def set_source(tune_set: LilypondSet) -> str:
|
def set_source(tune_set: LilypondSet) -> str:
|
||||||
return templates.get_template("lilypond/tune_set.ly").render(
|
return templates.get_template("lilypond/tune_set.ly").render(
|
||||||
score_beginning=SCORE_BEGINNING,
|
score_beginning=SCORE_BEGINNING,
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
|
import dataclasses
|
||||||
from collections.abc import Iterable, Iterator
|
from collections.abc import Iterable, Iterator
|
||||||
|
|
||||||
from fastapi import HTTPException
|
|
||||||
from folkugat_web.dal.sql.temes import scores as scores_dal
|
from folkugat_web.dal.sql.temes import scores as scores_dal
|
||||||
from folkugat_web.model import temes as model
|
from folkugat_web.model import temes as model
|
||||||
from folkugat_web.model.lilypond import score as lilypond_model
|
from folkugat_web.services import files as files_service
|
||||||
from folkugat_web.services import lilypond
|
from folkugat_web.services.lilypond import build as lilypond_build
|
||||||
from folkugat_web.services.temes import lyrics as lyrics_service
|
from folkugat_web.services.lilypond import render as lilypond_render
|
||||||
from folkugat_web.services.temes import properties as properties_service
|
from folkugat_web.services.lilypond import source as lilypond_source
|
||||||
from folkugat_web.services.temes import query as temes_q
|
|
||||||
from folkugat_web.utils import FnChain
|
|
||||||
|
|
||||||
|
|
||||||
def add_scores_to_tema(tema: model.Tema) -> model.Tema:
|
def add_scores_to_tema(tema: model.Tema) -> model.Tema:
|
||||||
@@ -42,34 +40,56 @@ def create_score(tema_id: int) -> model.Score:
|
|||||||
errors=[],
|
errors=[],
|
||||||
img_url=None,
|
img_url=None,
|
||||||
pdf_url=None,
|
pdf_url=None,
|
||||||
|
preview_url=None,
|
||||||
hidden=True,
|
hidden=True,
|
||||||
)
|
)
|
||||||
return scores_dal.insert_score(score=new_score)
|
return scores_dal.insert_score(score=new_score)
|
||||||
|
|
||||||
|
|
||||||
def build_tune_set_full_source(tema_ids: list[int]) -> str:
|
async def render_score(score: model.Score, title: str, source: str) -> model.Score:
|
||||||
temes = (
|
tune = lilypond_build.tune_from_tema_id(tema_id=score.tema_id, score_source=source)
|
||||||
FnChain.transform(temes_q.get_temes_by_ids(tema_ids=tema_ids)) |
|
output_file = files_service.create_tema_filename(tema_id=score.tema_id)
|
||||||
properties_service.add_properties_to_temes |
|
|
||||||
lyrics_service.add_lyrics_to_temes |
|
tune_source = lilypond_source.tune_source(tune=tune)
|
||||||
add_scores_to_temes |
|
async with files_service.tmp_file(content=tune_source) as source_file:
|
||||||
list
|
# Render PDF
|
||||||
).result()
|
pdf_result = await lilypond_render.render_file(
|
||||||
if not temes:
|
input_file=source_file,
|
||||||
return ""
|
output=lilypond_render.RenderOutput.PDF,
|
||||||
set_title = " i ".join(filter(bool, [
|
output_file=output_file,
|
||||||
", ".join([tema.title for tema in temes[:-1]]),
|
)
|
||||||
temes[-1].title
|
if errors := pdf_result.error:
|
||||||
]))
|
return dataclasses.replace(score, source=source, title=title, errors=errors)
|
||||||
tune_set = lilypond_model.LilypondSet(
|
# Render IMAGE
|
||||||
title=set_title,
|
img_result = await lilypond_render.render_file(
|
||||||
tunes=[
|
input_file=source_file,
|
||||||
lilypond_model.LilypondTune(
|
output=lilypond_render.RenderOutput.PNG_CROPPED,
|
||||||
header=lilypond_model.HeaderData.from_tema(tema=tema),
|
output_file=output_file,
|
||||||
score_source=tema.scores[0].source if tema.scores else None,
|
)
|
||||||
lyrics=lilypond_model.LyricsText.from_lyrics(lyrics=tema.lyrics[0]) if tema.lyrics else None,
|
if errors := img_result.error:
|
||||||
) for tema in temes
|
return dataclasses.replace(score, source=source, title=title, errors=errors)
|
||||||
]
|
|
||||||
|
preview_source = lilypond_source.preview_source(tune=tune)
|
||||||
|
async with files_service.tmp_file(content=preview_source) as source_file:
|
||||||
|
# Render PREVIEW
|
||||||
|
preview_result = await lilypond_render.render_file(
|
||||||
|
input_file=source_file,
|
||||||
|
output=lilypond_render.RenderOutput.PREVIEW,
|
||||||
|
output_file=output_file,
|
||||||
|
)
|
||||||
|
if errors := preview_result.error:
|
||||||
|
return dataclasses.replace(score, source=source, title=title, errors=errors)
|
||||||
|
|
||||||
|
pdf_file = pdf_result.result
|
||||||
|
img_file = img_result.result
|
||||||
|
preview_file = preview_result.result if preview_result.result and preview_result.result.exists() else None
|
||||||
|
|
||||||
|
return dataclasses.replace(
|
||||||
|
score,
|
||||||
|
source=source,
|
||||||
|
title=title,
|
||||||
|
pdf_url=files_service.get_db_file_path(pdf_file) if pdf_file else None,
|
||||||
|
img_url=files_service.get_db_file_path(img_file) if img_file else None,
|
||||||
|
preview_url=files_service.get_db_file_path(preview_file) if preview_file else None,
|
||||||
|
errors=[],
|
||||||
)
|
)
|
||||||
print("TUNE SET HASH: ", tune_set.hash().hex())
|
|
||||||
return lilypond.tune_set_score(tune_set=tune_set)
|
|
||||||
|
|||||||
8
scripts/03_add_preview_url.py
Normal file
8
scripts/03_add_preview_url.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from folkugat_web.dal.sql import get_connection
|
||||||
|
|
||||||
|
with get_connection() as con:
|
||||||
|
cur = con.cursor()
|
||||||
|
alter_query = """ ALTER TABLE tema_scores ADD COLUMN preview_url TEXT"""
|
||||||
|
_ = cur.execute(alter_query)
|
||||||
|
|
||||||
|
print("DONE!")
|
||||||
Reference in New Issue
Block a user