song_slides.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. """
  2. Copyright © 2022 Noah Vogt <noah@noahvogt.com>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. """
  14. from threading import Thread
  15. from os import path
  16. from wand.exceptions import BlobError
  17. from utils import (
  18. log,
  19. error_msg,
  20. )
  21. import config as const
  22. def generate_song_slides(
  23. slidegen,
  24. slide_count,
  25. template_img,
  26. zfill_length,
  27. ) -> None:
  28. log("generating song slides...")
  29. # unique_structures: list = list(set(chosen_structure))
  30. current_slide_index: int = 0
  31. threads = []
  32. for index, structure in enumerate(slidegen.chosen_structure):
  33. structure_element_splitted: list = slidegen.songtext[
  34. structure
  35. ].splitlines()
  36. line_count = len(structure_element_splitted)
  37. use_line_ranges_per_index = []
  38. use_lines_per_index = []
  39. if line_count <= const.STRUCTURE_ELEMENT_MAX_LINES:
  40. inner_slide_count = 1
  41. else:
  42. inner_slide_count: int = (
  43. line_count // const.STRUCTURE_ELEMENT_MAX_LINES + 1
  44. )
  45. use_lines_per_index = [
  46. line_count // inner_slide_count
  47. ] * inner_slide_count
  48. for inner_slide in range(inner_slide_count):
  49. if sum(use_lines_per_index) == line_count:
  50. break
  51. use_lines_per_index[inner_slide] = (
  52. use_lines_per_index[inner_slide] + 1
  53. )
  54. for inner_slide in range(inner_slide_count):
  55. use_line_ranges_per_index.append(
  56. sum(use_lines_per_index[:inner_slide])
  57. )
  58. for inner_slide in range(inner_slide_count):
  59. current_slide_index += 1
  60. log(
  61. "spawning subprocess for song slide [{} / {}]...".format(
  62. current_slide_index, slide_count
  63. ),
  64. color="yellow",
  65. )
  66. if inner_slide_count == 1:
  67. structure_element_value: str = slidegen.songtext[structure]
  68. else:
  69. splitted_wanted_range: list = structure_element_splitted[
  70. use_line_ranges_per_index[
  71. inner_slide
  72. ] : use_line_ranges_per_index[inner_slide]
  73. + use_lines_per_index[inner_slide]
  74. ]
  75. structure_element_value: str = ""
  76. for element in splitted_wanted_range:
  77. structure_element_value += element + "\n"
  78. structure_element_value = structure_element_value[:-1]
  79. threads.append(
  80. Thread(
  81. target=generate_song_slide,
  82. args=(
  83. slidegen.song_slide_form,
  84. template_img,
  85. structure_element_value,
  86. slidegen,
  87. index,
  88. inner_slide_count,
  89. inner_slide,
  90. current_slide_index,
  91. zfill_length,
  92. ),
  93. )
  94. )
  95. for thread in threads:
  96. thread.start()
  97. for thread in threads:
  98. thread.join()
  99. def generate_song_slide(
  100. song_slide,
  101. template_img,
  102. structure_element_value,
  103. slidegen,
  104. index,
  105. inner_slide_count,
  106. inner_slide,
  107. current_slide_index,
  108. zfill_length,
  109. ):
  110. song_slide_img = song_slide.get_slide(
  111. self=slidegen.song_slide_form(),
  112. template_img=template_img,
  113. slide_text=structure_element_value,
  114. song_structure=slidegen.chosen_structure,
  115. index=index,
  116. use_arrow=bool(
  117. inner_slide_count != 1 and inner_slide != inner_slide_count - 1
  118. ),
  119. )
  120. song_slide_img.format = const.IMAGE_FORMAT
  121. try:
  122. song_slide_img.save(
  123. filename=path.join(
  124. slidegen.output_dir,
  125. const.FILE_NAMEING
  126. + str(current_slide_index + 1).zfill(zfill_length)
  127. + "."
  128. + const.FILE_EXTENSION,
  129. )
  130. )
  131. log("song slide {} generated and saved".format(current_slide_index))
  132. except BlobError:
  133. error_msg(
  134. "could not write song slide {} to target directory".format(
  135. current_slide_index
  136. )
  137. )