slide_selection_iterator.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. # Copyright © 2024 Noah Vogt <noah@noahvogt.com>
  2. # This program is free software: you can redistribute it and/or modify
  3. # it under the terms of the GNU General Public License as published by
  4. # the Free Software Foundation, either version 3 of the License, or
  5. # (at your option) any later version.
  6. # This program is distributed in the hope that it will be useful,
  7. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. # GNU General Public License for more details.
  10. # You should have received a copy of the GNU General Public License
  11. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. import os
  13. from utils import (
  14. log,
  15. create_min_obs_subdirs,
  16. error_msg,
  17. expand_dir,
  18. )
  19. from input import parse_metadata, generate_final_prompt
  20. from slides import SlideStyle
  21. import config as const
  22. import slidegen
  23. def slide_selection_iterator(
  24. disable_async_enabled: bool, slide_style: SlideStyle
  25. ) -> None:
  26. iterator_prompt = "Exit now? [y/N]: "
  27. structure_prompt = (
  28. "Choose song structure (leave blank for full song)"
  29. + " eg. [1,R,2,R] / [1-4]: "
  30. )
  31. rclone_local_dir = expand_dir(const.RCLONE_LOCAL_DIR)
  32. song_counter = 0
  33. while True:
  34. song_counter += 1
  35. input_prompt_prefix = "[{}{}] ".format(
  36. const.OBS_SUBDIR_NAMING, song_counter
  37. )
  38. prompt_answer = str(input(input_prompt_prefix + iterator_prompt))
  39. if prompt_answer.lower() == "y":
  40. create_min_obs_subdirs()
  41. break
  42. os.system(
  43. "cd {} && fzf {} > {}".format(
  44. rclone_local_dir,
  45. const.FZF_ARGS,
  46. os.path.join(
  47. const.SSYNC_CACHE_DIR, const.SSYNC_CHOSEN_FILE_NAMING
  48. ),
  49. )
  50. )
  51. chosen_song_file = read_chosen_song_file()
  52. if len(chosen_song_file) == 0:
  53. log("no slides chosen, skipping...")
  54. else:
  55. src_dir = os.path.join(rclone_local_dir, chosen_song_file)
  56. dest_dir = create_and_get_dest_dir(
  57. expand_dir(const.OBS_SLIDES_DIR), song_counter
  58. )
  59. full_song_structure = get_structure_for_prompt(
  60. slide_style, src_dir, dest_dir
  61. )
  62. log(
  63. "full song structure of '{}':\n{}".format(
  64. chosen_song_file,
  65. full_song_structure,
  66. ),
  67. color="magenta",
  68. )
  69. structure_prompt_answer = input(
  70. input_prompt_prefix + structure_prompt
  71. ).strip()
  72. log(
  73. "generating slides '{}' to '{}{}'...".format(
  74. chosen_song_file, const.OBS_SUBDIR_NAMING, song_counter
  75. )
  76. )
  77. generate_slides_for_selected_song(
  78. slide_style,
  79. src_dir,
  80. dest_dir,
  81. generate_final_prompt(
  82. structure_prompt_answer, full_song_structure
  83. ),
  84. disable_async_enabled,
  85. )
  86. remove_chosenfile()
  87. def generate_slides_for_selected_song(
  88. classic_slide_style: SlideStyle,
  89. src_dir: str,
  90. dest_dir: str,
  91. calculated_prompt: str | list[str],
  92. disable_async_enabled: bool,
  93. ) -> None:
  94. executing_slidegen_instance = slidegen.Slidegen(
  95. classic_slide_style,
  96. src_dir,
  97. dest_dir,
  98. calculated_prompt,
  99. )
  100. executing_slidegen_instance.execute(disable_async_enabled)
  101. def get_structure_for_prompt(classic_slide_style, src_dir, dest_dir):
  102. dummy_slidegen_instance = slidegen.Slidegen(
  103. classic_slide_style,
  104. src_dir,
  105. dest_dir,
  106. "",
  107. )
  108. parse_metadata(dummy_slidegen_instance)
  109. full_song_structure = dummy_slidegen_instance.metadata["structure"]
  110. return full_song_structure
  111. def get_file_list_inside(rclone_local_dir):
  112. file_list_str = ""
  113. try:
  114. for file in os.listdir(rclone_local_dir):
  115. file_list_str += file + "\n"
  116. except (FileNotFoundError, PermissionError, IOError) as error:
  117. error_msg(
  118. "Failed to access items in '{}'. Reason: {}".format(
  119. rclone_local_dir, error
  120. )
  121. )
  122. file_list_str = file_list_str[:-1]
  123. file_list_str = file_list_str.replace("\n", "\\n")
  124. return file_list_str
  125. def remove_chosenfile() -> None:
  126. try:
  127. if os.path.isfile(
  128. os.path.join(const.SSYNC_CACHE_DIR, const.SSYNC_CHOSEN_FILE_NAMING)
  129. ):
  130. os.remove(
  131. os.path.join(
  132. const.SSYNC_CACHE_DIR, const.SSYNC_CHOSEN_FILE_NAMING
  133. ),
  134. )
  135. except (FileNotFoundError, PermissionError, IOError) as error:
  136. error_msg("Failed to remove chosenfile. Reason: {}".format(error))
  137. def create_and_get_dest_dir(obs_slides_dir, index) -> str:
  138. dest_dir = os.path.join(
  139. obs_slides_dir,
  140. const.OBS_SUBDIR_NAMING + str(index),
  141. )
  142. os.mkdir(dest_dir)
  143. return dest_dir
  144. def read_chosen_song_file() -> str:
  145. with open(
  146. os.path.join(const.SSYNC_CACHE_DIR, const.SSYNC_CHOSEN_FILE_NAMING),
  147. encoding="utf-8-sig",
  148. mode="r",
  149. ) as tempfile_file_opener:
  150. chosen_song_file = tempfile_file_opener.read()[:-1].strip()
  151. return chosen_song_file