multimedia_paradise 1.1.314

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of multimedia_paradise might be problematic. Click here for more details.

Files changed (417) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +2340 -0
  3. data/bin/audio_player +12 -0
  4. data/bin/auto_title +7 -0
  5. data/bin/convert_audio_to_mp4video_with_image +7 -0
  6. data/bin/cut_audio +7 -0
  7. data/bin/cut_multimedia +7 -0
  8. data/bin/extract_audio +7 -0
  9. data/bin/ffmpeg_merge +7 -0
  10. data/bin/file_duration +7 -0
  11. data/bin/gtk_radio +7 -0
  12. data/bin/loop_this_video +7 -0
  13. data/bin/merge_avi_files +7 -0
  14. data/bin/merge_mp3 +7 -0
  15. data/bin/missing_video_files +7 -0
  16. data/bin/movie_searcher +7 -0
  17. data/bin/mp3_to_opus +7 -0
  18. data/bin/mplayer_wrapper +7 -0
  19. data/bin/multimedia_information +11 -0
  20. data/bin/multimedia_paradise +9 -0
  21. data/bin/multimedia_paradise_sinatra +7 -0
  22. data/bin/play_random_simpsons_video +7 -0
  23. data/bin/playlist +7 -0
  24. data/bin/random_video +7 -0
  25. data/bin/remove_audio +9 -0
  26. data/bin/remove_last_second +7 -0
  27. data/bin/remove_subtitles +7 -0
  28. data/bin/tag_mp3_files +7 -0
  29. data/bin/to_aiff +10 -0
  30. data/bin/to_mp4 +7 -0
  31. data/bin/verbose_analyse_this_mp3_file_for_id3_tags +9 -0
  32. data/bin/video_codec +7 -0
  33. data/bin/video_information +8 -0
  34. data/bin/video_player +11 -0
  35. data/bin/video_to_images +7 -0
  36. data/bin/vp9 +9 -0
  37. data/bin/waveform +73 -0
  38. data/doc/CHANGELOG.md +44 -0
  39. data/doc/LINKS.md +6 -0
  40. data/doc/MOTIVATION_FOR_THIS_PROJECT.md +22 -0
  41. data/doc/MergingVideoLectures.md +12 -0
  42. data/doc/README.gen +2300 -0
  43. data/doc/Readme_for_the_cut_audio_component.md +168 -0
  44. data/doc/todo/todo_for_the_GUIs.md +0 -0
  45. data/doc/todo/todo_for_the_multimedia_paradise_project.md +111 -0
  46. data/lib/multimedia_paradise/audio/audio_player/audio_player.rb +83 -0
  47. data/lib/multimedia_paradise/audio/audio_player/constants.rb +136 -0
  48. data/lib/multimedia_paradise/audio/audio_player/menu.rb +164 -0
  49. data/lib/multimedia_paradise/audio/audio_player/misc.rb +718 -0
  50. data/lib/multimedia_paradise/audio/audio_player/reset.rb +77 -0
  51. data/lib/multimedia_paradise/audio/audio_player/tab.rb +35 -0
  52. data/lib/multimedia_paradise/audio/audio_tag_reader/README.md +7 -0
  53. data/lib/multimedia_paradise/audio/audio_tag_reader/audio_tag_reader.rb +503 -0
  54. data/lib/multimedia_paradise/audio/base.rb +67 -0
  55. data/lib/multimedia_paradise/audio/compress.rb +97 -0
  56. data/lib/multimedia_paradise/audio/create_m3u_playlist.rb +245 -0
  57. data/lib/multimedia_paradise/audio/extract_audio/constants.rb +37 -0
  58. data/lib/multimedia_paradise/audio/extract_audio/extract_audio.rb +417 -0
  59. data/lib/multimedia_paradise/audio/file_duration/constants.rb +53 -0
  60. data/lib/multimedia_paradise/audio/file_duration/file_duration.rb +602 -0
  61. data/lib/multimedia_paradise/audio/genres/boogie.rb +35 -0
  62. data/lib/multimedia_paradise/audio/genres/concerts.rb +35 -0
  63. data/lib/multimedia_paradise/audio/genres/constants.rb +53 -0
  64. data/lib/multimedia_paradise/audio/genres/eurodance.rb +35 -0
  65. data/lib/multimedia_paradise/audio/genres/genre.rb +696 -0
  66. data/lib/multimedia_paradise/audio/genres/hip_hop.rb +35 -0
  67. data/lib/multimedia_paradise/audio/genres/italian_songs.rb +35 -0
  68. data/lib/multimedia_paradise/audio/genres/the_1980s.rb +35 -0
  69. data/lib/multimedia_paradise/audio/genres/trance.rb +35 -0
  70. data/lib/multimedia_paradise/audio/lyrics_fetcher.rb +238 -0
  71. data/lib/multimedia_paradise/audio/merge_audio_files.rb +136 -0
  72. data/lib/multimedia_paradise/audio/modify_year_of_audio_file.rb +151 -0
  73. data/lib/multimedia_paradise/audio/n_audio_songs.rb +216 -0
  74. data/lib/multimedia_paradise/audio/play_all_audio_files.rb +122 -0
  75. data/lib/multimedia_paradise/audio/playlist/playlist.rb +1559 -0
  76. data/lib/multimedia_paradise/audio/remove_audio.rb +98 -0
  77. data/lib/multimedia_paradise/audio/remove_last_second.rb +83 -0
  78. data/lib/multimedia_paradise/audio/report_missing_id.rb +139 -0
  79. data/lib/multimedia_paradise/audio/streamripper/constants.rb +51 -0
  80. data/lib/multimedia_paradise/audio/streamripper/streamripper_wrapper.rb +279 -0
  81. data/lib/multimedia_paradise/audio/to_mp3.rb +138 -0
  82. data/lib/multimedia_paradise/audio/to_ogg.rb +104 -0
  83. data/lib/multimedia_paradise/audio/wav_to_mp3.rb +87 -0
  84. data/lib/multimedia_paradise/audio/waveform/class.rb +341 -0
  85. data/lib/multimedia_paradise/audio/waveform/constants.rb +38 -0
  86. data/lib/multimedia_paradise/audio/waveform/log.rb +101 -0
  87. data/lib/multimedia_paradise/autoinclude.rb +3 -0
  88. data/lib/multimedia_paradise/autoinclude_remove_audio.rb +6 -0
  89. data/lib/multimedia_paradise/base/base.rb +34 -0
  90. data/lib/multimedia_paradise/base/colours.rb +354 -0
  91. data/lib/multimedia_paradise/base/commandline_arguments.rb +52 -0
  92. data/lib/multimedia_paradise/base/constants.rb +19 -0
  93. data/lib/multimedia_paradise/base/encoding.rb +31 -0
  94. data/lib/multimedia_paradise/base/misc.rb +618 -0
  95. data/lib/multimedia_paradise/base/namespace.rb +36 -0
  96. data/lib/multimedia_paradise/base/time.rb +25 -0
  97. data/lib/multimedia_paradise/colours/colours.rb +82 -0
  98. data/lib/multimedia_paradise/commandline/menu.rb +498 -0
  99. data/lib/multimedia_paradise/configuration/play_zoomed.yml +1 -0
  100. data/lib/multimedia_paradise/constants/constants.rb +23 -0
  101. data/lib/multimedia_paradise/constants/conversions.rb +62 -0
  102. data/lib/multimedia_paradise/constants/directory_constants.rb +133 -0
  103. data/lib/multimedia_paradise/constants/encodings.rb +26 -0
  104. data/lib/multimedia_paradise/constants/file_constants.rb +171 -0
  105. data/lib/multimedia_paradise/constants/misc.rb +80 -0
  106. data/lib/multimedia_paradise/constants/my_video_directory.rb +30 -0
  107. data/lib/multimedia_paradise/constants/namespace.rb +14 -0
  108. data/lib/multimedia_paradise/constants/newline.rb +14 -0
  109. data/lib/multimedia_paradise/constants/video_filetypes.rb +27 -0
  110. data/lib/multimedia_paradise/constants/web_constants.rb +150 -0
  111. data/lib/multimedia_paradise/conversions/README.md +2 -0
  112. data/lib/multimedia_paradise/conversions/conversions.rb +930 -0
  113. data/lib/multimedia_paradise/css/project.css +15 -0
  114. data/lib/multimedia_paradise/data/asoundrc +12 -0
  115. data/lib/multimedia_paradise/ffmpeg/README.md +2 -0
  116. data/lib/multimedia_paradise/ffmpeg/ffmpeg.rb +620 -0
  117. data/lib/multimedia_paradise/gui/fox/play_from_radio_station.rb +75 -0
  118. data/lib/multimedia_paradise/gui/gosu/video_player/video_player.rb +109 -0
  119. data/lib/multimedia_paradise/gui/gtk2/lyrics/lyrics.rb +33 -0
  120. data/lib/multimedia_paradise/gui/gtk2/multimedia_converter/multimedia_converter.rb +33 -0
  121. data/lib/multimedia_paradise/gui/gtk2/notebook.rb +144 -0
  122. data/lib/multimedia_paradise/gui/gtk2/play_video_from_my_collection/play_video_from_my_collection.rb +43 -0
  123. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/README.md +12 -0
  124. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/simple_play_widget.rb +40 -0
  125. data/lib/multimedia_paradise/gui/gtk2/video_collection/video_collection.rb +56 -0
  126. data/lib/multimedia_paradise/gui/gtk2/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +42 -0
  127. data/lib/multimedia_paradise/gui/gtk2/youtube_downloader/youtube_downloader.rb +32 -0
  128. data/lib/multimedia_paradise/gui/gtk3/change_metadata_widget/README.md +3 -0
  129. data/lib/multimedia_paradise/gui/gtk3/change_metadata_widget/change_metadata_widget.rb +150 -0
  130. data/lib/multimedia_paradise/gui/gtk3/cut_multimedia/cut_multimedia.rb +321 -0
  131. data/lib/multimedia_paradise/gui/gtk3/information_about_a_mp3_file/information_about_a_mp3_file.rb +421 -0
  132. data/lib/multimedia_paradise/gui/gtk3/lyrics/lyrics.rb +33 -0
  133. data/lib/multimedia_paradise/gui/gtk3/multimedia_converter/multimedia_converter.rb +34 -0
  134. data/lib/multimedia_paradise/gui/gtk3/multimedia_notebook/multimedia_notebook.rb +34 -0
  135. data/lib/multimedia_paradise/gui/gtk3/play_video_from_my_collection/play_video_from_my_collection.rb +34 -0
  136. data/lib/multimedia_paradise/gui/gtk3/playlist/playlist.rb +34 -0
  137. data/lib/multimedia_paradise/gui/gtk3/radio/misc.rb +487 -0
  138. data/lib/multimedia_paradise/gui/gtk3/radio/radio.rb +698 -0
  139. data/lib/multimedia_paradise/gui/gtk3/simple_play_widget/simple_play_widget.rb +38 -0
  140. data/lib/multimedia_paradise/gui/gtk3/sound_effect_widget/sound_effect_widget.rb +34 -0
  141. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/connect_skeleton.rb +61 -0
  142. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/create.rb +405 -0
  143. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/misc.rb +1820 -0
  144. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/tag_mp3_files.config +6 -0
  145. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/tag_mp3_files.rb +66 -0
  146. data/lib/multimedia_paradise/gui/gtk3/video_collection/video_collection.rb +43 -0
  147. data/lib/multimedia_paradise/gui/gtk3/video_editor/video_editor.rb +34 -0
  148. data/lib/multimedia_paradise/gui/gtk3/video_player/video_player.rb +34 -0
  149. data/lib/multimedia_paradise/gui/gtk3/webcam_widget/webcam_widget.rb +425 -0
  150. data/lib/multimedia_paradise/gui/gtk3/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +36 -0
  151. data/lib/multimedia_paradise/gui/gtk3/youtube_channels/youtube_channels.rb +210 -0
  152. data/lib/multimedia_paradise/gui/gtk3/youtube_downloader/youtube_downloader.rb +32 -0
  153. data/lib/multimedia_paradise/gui/gui_base.rb +92 -0
  154. data/lib/multimedia_paradise/gui/libui/change_metadata_widget/change_metadata_widget.rb +115 -0
  155. data/lib/multimedia_paradise/gui/libui/cut_multimedia/cut_multimedia.rb +119 -0
  156. data/lib/multimedia_paradise/gui/libui/lyrics/lyrics.rb +67 -0
  157. data/lib/multimedia_paradise/gui/libui/simple_play_widget/simple_play_widget.rb +119 -0
  158. data/lib/multimedia_paradise/gui/libui/tag_mp3_files/tag_mp3_files.rb +268 -0
  159. data/lib/multimedia_paradise/gui/libui/video_player/video_player.rb +81 -0
  160. data/lib/multimedia_paradise/gui/libui/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +126 -0
  161. data/lib/multimedia_paradise/gui/libui/youtube_channels/youtube_channels.rb +116 -0
  162. data/lib/multimedia_paradise/gui/libui/youtube_downloader/youtube_downloader.rb +107 -0
  163. data/lib/multimedia_paradise/gui/shared_code/change_metadata_widget/change_metadata_widget_module.rb +538 -0
  164. data/lib/multimedia_paradise/gui/shared_code/cut_multimedia/cut_multimedia_module.rb +268 -0
  165. data/lib/multimedia_paradise/gui/shared_code/information_about_a_mp3_file/information_about_a_mp3_file_module.rb +120 -0
  166. data/lib/multimedia_paradise/gui/shared_code/lyrics/lyrics_module.rb +141 -0
  167. data/lib/multimedia_paradise/gui/shared_code/multimedia_converter/multimedia_converter_module.rb +478 -0
  168. data/lib/multimedia_paradise/gui/shared_code/multimedia_notebook/multimedia_notebook_module.rb +171 -0
  169. data/lib/multimedia_paradise/gui/shared_code/play_video_from_my_collection/play_video_from_my_collection_module.rb +464 -0
  170. data/lib/multimedia_paradise/gui/shared_code/playlist/playlist_module.rb +151 -0
  171. data/lib/multimedia_paradise/gui/shared_code/simple_play_widget/simple_play_widget_module.rb +257 -0
  172. data/lib/multimedia_paradise/gui/shared_code/sound_effect_widget/sound_effect_widget_module.rb +173 -0
  173. data/lib/multimedia_paradise/gui/shared_code/tag_mp3_files/tag_mp3_files_module.rb +73 -0
  174. data/lib/multimedia_paradise/gui/shared_code/video_editor/video_editor_module.rb +287 -0
  175. data/lib/multimedia_paradise/gui/shared_code/video_player/video_player_module.rb +185 -0
  176. data/lib/multimedia_paradise/gui/shared_code/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio_module.rb +310 -0
  177. data/lib/multimedia_paradise/gui/shared_code/youtube_downloader/youtube_downloader_module.rb +339 -0
  178. data/lib/multimedia_paradise/gui/tk/tk_multimedia_wrapper.rb +60 -0
  179. data/lib/multimedia_paradise/help/help.rb +75 -0
  180. data/lib/multimedia_paradise/images/MULTIMEDIA.jpg +0 -0
  181. data/lib/multimedia_paradise/images/MULTIMEDIA_PARADISE_ID_TAG_GUI_IN_RUBY_GTK3.png +0 -0
  182. data/lib/multimedia_paradise/images/MULTIMEDIA_PARADISE_LOGO.png +0 -0
  183. data/lib/multimedia_paradise/images/UK_flag.png +0 -0
  184. data/lib/multimedia_paradise/images/US_flag.png +0 -0
  185. data/lib/multimedia_paradise/images/austrian_flag.png +0 -0
  186. data/lib/multimedia_paradise/images/french_flag.png +0 -0
  187. data/lib/multimedia_paradise/images/german_flag.png +0 -0
  188. data/lib/multimedia_paradise/images/radio_image.png +0 -0
  189. data/lib/multimedia_paradise/images/trance.png +0 -0
  190. data/lib/multimedia_paradise/java/AudioPlayer.class +0 -0
  191. data/lib/multimedia_paradise/java/AudioPlayer.java +103 -0
  192. data/lib/multimedia_paradise/java/README.md +3 -0
  193. data/lib/multimedia_paradise/misc/long_format_to_milliseconds_converter.rb +182 -0
  194. data/lib/multimedia_paradise/misc/milliseconds_to_long_format_converter.rb +186 -0
  195. data/lib/multimedia_paradise/multimedia/analyse_multimedia_file.rb +180 -0
  196. data/lib/multimedia_paradise/multimedia/avisynth/README.md +4 -0
  197. data/lib/multimedia_paradise/multimedia/avisynth/avisynth_code.avs +471 -0
  198. data/lib/multimedia_paradise/multimedia/base.rb +60 -0
  199. data/lib/multimedia_paradise/multimedia/chord.rb +174 -0
  200. data/lib/multimedia_paradise/multimedia/convert_audio_to_video_with_image.rb +171 -0
  201. data/lib/multimedia_paradise/multimedia/cut_multimedia/10_minutes_chop.rb +29 -0
  202. data/lib/multimedia_paradise/multimedia/cut_multimedia/15_minutes_chop.rb +29 -0
  203. data/lib/multimedia_paradise/multimedia/cut_multimedia/30_minutes_chop.rb +29 -0
  204. data/lib/multimedia_paradise/multimedia/cut_multimedia/5_minutes_chop.rb +29 -0
  205. data/lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb +2017 -0
  206. data/lib/multimedia_paradise/multimedia/cut_multimedia/evaluate_from_this_file.rb +79 -0
  207. data/lib/multimedia_paradise/multimedia/cut_multimedia/interactive_menu.rb +514 -0
  208. data/lib/multimedia_paradise/multimedia/interactive_shell.rb +84 -0
  209. data/lib/multimedia_paradise/multimedia/merge_multimedia.rb +125 -0
  210. data/lib/multimedia_paradise/multimedia/note.rb +500 -0
  211. data/lib/multimedia_paradise/multimedia/play_from_this_list.rb +163 -0
  212. data/lib/multimedia_paradise/multimedia/read_meta_tags.rb +173 -0
  213. data/lib/multimedia_paradise/multimedia/simulate_youtube_playlist.rb +209 -0
  214. data/lib/multimedia_paradise/multimedia/start_length_duration.rb +205 -0
  215. data/lib/multimedia_paradise/multimedia/video_downloader/video_downloader.rb +143 -0
  216. data/lib/multimedia_paradise/project/project.rb +47 -0
  217. data/lib/multimedia_paradise/requires/require_audio_files.rb +74 -0
  218. data/lib/multimedia_paradise/requires/require_cut_multimedia.rb +7 -0
  219. data/lib/multimedia_paradise/requires/require_extract_audio.rb +7 -0
  220. data/lib/multimedia_paradise/requires/require_file_duration.rb +7 -0
  221. data/lib/multimedia_paradise/requires/require_streamripper.rb +7 -0
  222. data/lib/multimedia_paradise/requires/require_the_audio_player.rb +7 -0
  223. data/lib/multimedia_paradise/requires/require_the_multimedia_paradise_project.rb +38 -0
  224. data/lib/multimedia_paradise/requires/require_the_sinatra_components.rb +7 -0
  225. data/lib/multimedia_paradise/requires/require_toplevel_methods_files.rb +25 -0
  226. data/lib/multimedia_paradise/requires/require_video_files.rb +25 -0
  227. data/lib/multimedia_paradise/requires/require_video_player.rb +7 -0
  228. data/lib/multimedia_paradise/sinatra/app.rb +311 -0
  229. data/lib/multimedia_paradise/sinatra/embeddable_interface.rb +379 -0
  230. data/lib/multimedia_paradise/sound_effects/README.md +12 -0
  231. data/lib/multimedia_paradise/sound_effects/cat_meow.mp3 +0 -0
  232. data/lib/multimedia_paradise/sound_effects/channel_opened.mp3 +0 -0
  233. data/lib/multimedia_paradise/sound_effects/phone_ring.mp3 +0 -0
  234. data/lib/multimedia_paradise/statistics/README.md +5 -0
  235. data/lib/multimedia_paradise/statistics/video.rb +84 -0
  236. data/lib/multimedia_paradise/toplevel_cut_audio.rb +16 -0
  237. data/lib/multimedia_paradise/toplevel_methods/analyze_audio_stream.rb +31 -0
  238. data/lib/multimedia_paradise/toplevel_methods/chop_into_segments_of_n_seconds_size.rb +32 -0
  239. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_five_minutes.rb +22 -0
  240. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_n_seconds.rb +92 -0
  241. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_ten_minutes.rb +22 -0
  242. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_two_minutes.rb +24 -0
  243. data/lib/multimedia_paradise/toplevel_methods/codecs.rb +50 -0
  244. data/lib/multimedia_paradise/toplevel_methods/copy_and_merge_this_video_n_times.rb +51 -0
  245. data/lib/multimedia_paradise/toplevel_methods/copy_file.rb +18 -0
  246. data/lib/multimedia_paradise/toplevel_methods/create_video_from_this_audio.rb +65 -0
  247. data/lib/multimedia_paradise/toplevel_methods/cut_from_to.rb +156 -0
  248. data/lib/multimedia_paradise/toplevel_methods/delay_audio.rb +31 -0
  249. data/lib/multimedia_paradise/toplevel_methods/denoise.rb +90 -0
  250. data/lib/multimedia_paradise/toplevel_methods/deshake.rb +43 -0
  251. data/lib/multimedia_paradise/toplevel_methods/e.rb +16 -0
  252. data/lib/multimedia_paradise/toplevel_methods/encode_this_video.rb +49 -0
  253. data/lib/multimedia_paradise/toplevel_methods/ensure_that_the_output_directory_exists.rb +27 -0
  254. data/lib/multimedia_paradise/toplevel_methods/esystem.rb +43 -0
  255. data/lib/multimedia_paradise/toplevel_methods/files_and_directories.rb +90 -0
  256. data/lib/multimedia_paradise/toplevel_methods/flip_and_rotate.rb +58 -0
  257. data/lib/multimedia_paradise/toplevel_methods/increase_volume_of_this_audio_file.rb +61 -0
  258. data/lib/multimedia_paradise/toplevel_methods/is_a_multimedia_file.rb +27 -0
  259. data/lib/multimedia_paradise/toplevel_methods/is_audio_file.rb +27 -0
  260. data/lib/multimedia_paradise/toplevel_methods/is_image_file.rb +31 -0
  261. data/lib/multimedia_paradise/toplevel_methods/is_on_roebe.rb +17 -0
  262. data/lib/multimedia_paradise/toplevel_methods/is_video_file.rb +62 -0
  263. data/lib/multimedia_paradise/toplevel_methods/merge_multimedia_file.rb +327 -0
  264. data/lib/multimedia_paradise/toplevel_methods/merge_these_videos.rb +105 -0
  265. data/lib/multimedia_paradise/toplevel_methods/misc.rb +885 -0
  266. data/lib/multimedia_paradise/toplevel_methods/n_local_videos.rb +56 -0
  267. data/lib/multimedia_paradise/toplevel_methods/opn.rb +24 -0
  268. data/lib/multimedia_paradise/toplevel_methods/output_directory.rb +59 -0
  269. data/lib/multimedia_paradise/toplevel_methods/player_in_use.rb +80 -0
  270. data/lib/multimedia_paradise/toplevel_methods/query_the_audio_codec_of_this_file.rb +24 -0
  271. data/lib/multimedia_paradise/toplevel_methods/radio.rb +360 -0
  272. data/lib/multimedia_paradise/toplevel_methods/rds.rb +24 -0
  273. data/lib/multimedia_paradise/toplevel_methods/return_all_video_files.rb +64 -0
  274. data/lib/multimedia_paradise/toplevel_methods/return_data_from_video_collection_file_for_this_entry.rb +38 -0
  275. data/lib/multimedia_paradise/toplevel_methods/return_duration_of_this_multimedia_file.rb +27 -0
  276. data/lib/multimedia_paradise/toplevel_methods/return_full_name_for_video_at_this_position.rb +54 -0
  277. data/lib/multimedia_paradise/toplevel_methods/return_path_to_random_simpsons_video_file.rb +43 -0
  278. data/lib/multimedia_paradise/toplevel_methods/return_random_video_file_from_the_video_collection.rb +73 -0
  279. data/lib/multimedia_paradise/toplevel_methods/return_screen_resolution.rb +24 -0
  280. data/lib/multimedia_paradise/toplevel_methods/run_sys_command.rb +30 -0
  281. data/lib/multimedia_paradise/toplevel_methods/scale_video.rb +27 -0
  282. data/lib/multimedia_paradise/toplevel_methods/set_title_of.rb +65 -0
  283. data/lib/multimedia_paradise/toplevel_methods/slow_down_this_video_file.rb +33 -0
  284. data/lib/multimedia_paradise/toplevel_methods/start_screencast.rb +70 -0
  285. data/lib/multimedia_paradise/toplevel_methods/subtitles.rb +59 -0
  286. data/lib/multimedia_paradise/toplevel_methods/to_flac.rb +30 -0
  287. data/lib/multimedia_paradise/toplevel_methods/to_mp4.rb +24 -0
  288. data/lib/multimedia_paradise/toplevel_methods/total_duration.rb +35 -0
  289. data/lib/multimedia_paradise/toplevel_methods/use_lame_codec.rb +32 -0
  290. data/lib/multimedia_paradise/toplevel_methods/video_dataset.rb +76 -0
  291. data/lib/multimedia_paradise/version/version.rb +28 -0
  292. data/lib/multimedia_paradise/video/all_videos.rb +101 -0
  293. data/lib/multimedia_paradise/video/capture_screen.rb +285 -0
  294. data/lib/multimedia_paradise/video/check_numbers.rb +215 -0
  295. data/lib/multimedia_paradise/video/columbo/columbo.rb +139 -0
  296. data/lib/multimedia_paradise/video/copy_missing_video_files.rb +293 -0
  297. data/lib/multimedia_paradise/video/copy_random_video.rb +98 -0
  298. data/lib/multimedia_paradise/video/correct_video_numbers.rb +278 -0
  299. data/lib/multimedia_paradise/video/create_dvd.rb +50 -0
  300. data/lib/multimedia_paradise/video/encode_video.rb +81 -0
  301. data/lib/multimedia_paradise/video/ffmpeg_options.rb +156 -0
  302. data/lib/multimedia_paradise/video/find_video/constants.rb +23 -0
  303. data/lib/multimedia_paradise/video/find_video/find_video.rb +493 -0
  304. data/lib/multimedia_paradise/video/fix_married_with_children_videos.rb +70 -0
  305. data/lib/multimedia_paradise/video/guess_video_name.rb +189 -0
  306. data/lib/multimedia_paradise/video/imdb_rating/imdb_rating.rb +141 -0
  307. data/lib/multimedia_paradise/video/mike_hammer/mike_hammer.rb +74 -0
  308. data/lib/multimedia_paradise/video/missing_video_files/missing_video_files.rb +286 -0
  309. data/lib/multimedia_paradise/video/movie_searcher.rb +281 -0
  310. data/lib/multimedia_paradise/video/mplayer_wrapper.rb +504 -0
  311. data/lib/multimedia_paradise/video/play_random_file.rb +91 -0
  312. data/lib/multimedia_paradise/video/play_random_realvideo.rb +87 -0
  313. data/lib/multimedia_paradise/video/prepare_video_lecture.rb +272 -0
  314. data/lib/multimedia_paradise/video/random_video.rb +310 -0
  315. data/lib/multimedia_paradise/video/registered_video_file.rb +131 -0
  316. data/lib/multimedia_paradise/video/remove_metadata.rb +52 -0
  317. data/lib/multimedia_paradise/video/rename_video_file.rb +149 -0
  318. data/lib/multimedia_paradise/video/report_local_videos.rb +106 -0
  319. data/lib/multimedia_paradise/video/report_missing_videos_in_the_yaml_file.rb +107 -0
  320. data/lib/multimedia_paradise/video/resolution.rb +159 -0
  321. data/lib/multimedia_paradise/video/simpsons.rb +129 -0
  322. data/lib/multimedia_paradise/video/speed_up_video.rb +135 -0
  323. data/lib/multimedia_paradise/video/split_this_video.rb +126 -0
  324. data/lib/multimedia_paradise/video/srt_regex.rb +211 -0
  325. data/lib/multimedia_paradise/video/store_available_video_files.rb +138 -0
  326. data/lib/multimedia_paradise/video/the_simpsons/README.md +9 -0
  327. data/lib/multimedia_paradise/video/the_simpsons/good_the_simpsons_episodes.rb +107 -0
  328. data/lib/multimedia_paradise/video/the_simpsons/the_simpsons.rb +82 -0
  329. data/lib/multimedia_paradise/video/video.rb +14 -0
  330. data/lib/multimedia_paradise/video/video_encoding_settings.rb +57 -0
  331. data/lib/multimedia_paradise/video/video_genres.rb +337 -0
  332. data/lib/multimedia_paradise/video/video_information.rb +443 -0
  333. data/lib/multimedia_paradise/video/video_metadata.rb +132 -0
  334. data/lib/multimedia_paradise/video/video_player.rb +581 -0
  335. data/lib/multimedia_paradise/video/video_renamer.rb +160 -0
  336. data/lib/multimedia_paradise/video/watermark.rb +290 -0
  337. data/lib/multimedia_paradise/video/youtube/youtube.rb +17 -0
  338. data/lib/multimedia_paradise/video/youtube_embedder.rb +235 -0
  339. data/lib/multimedia_paradise/www/GIS/GIS.cgi +147 -0
  340. data/lib/multimedia_paradise/www/HDMI/HDMI.cgi +34 -0
  341. data/lib/multimedia_paradise/www/TALES_FROM_THE_CRYPT.html +71 -0
  342. data/lib/multimedia_paradise/www/alsa/alsa.cgi +7 -0
  343. data/lib/multimedia_paradise/www/alsa/alsa.rb +309 -0
  344. data/lib/multimedia_paradise/www/alsa/alsa.sinatra +56 -0
  345. data/lib/multimedia_paradise/www/audacity.cgi +30 -0
  346. data/lib/multimedia_paradise/www/audio/audio.cgi +9 -0
  347. data/lib/multimedia_paradise/www/audio/audio.rb +2739 -0
  348. data/lib/multimedia_paradise/www/audio/audio.sinatra +56 -0
  349. data/lib/multimedia_paradise/www/avisynth/avisynth.cgi +172 -0
  350. data/lib/multimedia_paradise/www/best_voices/best_voices.cgi +60 -0
  351. data/lib/multimedia_paradise/www/cassette/cassette.cgi +723 -0
  352. data/lib/multimedia_paradise/www/codecs/codecs.cgi +95 -0
  353. data/lib/multimedia_paradise/www/componists/vivaldi.cgi +218 -0
  354. data/lib/multimedia_paradise/www/decibel.cgi +79 -0
  355. data/lib/multimedia_paradise/www/ffmpeg/ffmpeg.cgi +439 -0
  356. data/lib/multimedia_paradise/www/lame/lame.cgi +7 -0
  357. data/lib/multimedia_paradise/www/lame/lame.rb +101 -0
  358. data/lib/multimedia_paradise/www/lame/lame.sinatra +56 -0
  359. data/lib/multimedia_paradise/www/lilypond.cgi +96 -0
  360. data/lib/multimedia_paradise/www/lyrics/lyrics.cgi +49 -0
  361. data/lib/multimedia_paradise/www/midi/al_adagi.mid +0 -0
  362. data/lib/multimedia_paradise/www/play_songs.cgi +102 -0
  363. data/lib/multimedia_paradise/www/play_this_video_file.cgi +100 -0
  364. data/lib/multimedia_paradise/www/pulseaudio/pulseaudio.cgi +7 -0
  365. data/lib/multimedia_paradise/www/pulseaudio/pulseaudio.rb +168 -0
  366. data/lib/multimedia_paradise/www/pulseaudio/pulseaudio.sinatra +56 -0
  367. data/lib/multimedia_paradise/www/rhythmbox/rhythmbox.cgi +120 -0
  368. data/lib/multimedia_paradise/www/sound_theory.cgi +163 -0
  369. data/lib/multimedia_paradise/www/tv/tv.cgi +182 -0
  370. data/lib/multimedia_paradise/www/video/video.cgi +7 -0
  371. data/lib/multimedia_paradise/www/video/video.rb +7709 -0
  372. data/lib/multimedia_paradise/www/video/video.sinatra +52 -0
  373. data/lib/multimedia_paradise/www/web_streams.cgi +58 -0
  374. data/lib/multimedia_paradise/yaml/audio_formats.yml +14 -0
  375. data/lib/multimedia_paradise/yaml/best_songs_in_an_era/eurodance/top20.yml +28 -0
  376. data/lib/multimedia_paradise/yaml/game_shows/ruck_zuck/ruck_zuck.yml +25 -0
  377. data/lib/multimedia_paradise/yaml/genres/1980s.yml +198 -0
  378. data/lib/multimedia_paradise/yaml/genres/README.md +5 -0
  379. data/lib/multimedia_paradise/yaml/genres/boogie.yml +68 -0
  380. data/lib/multimedia_paradise/yaml/genres/concerts.yml +29 -0
  381. data/lib/multimedia_paradise/yaml/genres/eurodance.yml +456 -0
  382. data/lib/multimedia_paradise/yaml/genres/hip_hop.yml +49 -0
  383. data/lib/multimedia_paradise/yaml/genres/italian_songs.yml +53 -0
  384. data/lib/multimedia_paradise/yaml/genres/trance.yml +167 -0
  385. data/lib/multimedia_paradise/yaml/good_horror_movies/good_horror_movies.yml +12 -0
  386. data/lib/multimedia_paradise/yaml/good_movie_actors/good_movie_actors.yml +6 -0
  387. data/lib/multimedia_paradise/yaml/image_formats.yml +8 -0
  388. data/lib/multimedia_paradise/yaml/internal/README.md +2 -0
  389. data/lib/multimedia_paradise/yaml/internal/installed_binaries.yml +31 -0
  390. data/lib/multimedia_paradise/yaml/lyrics.yml +6275 -0
  391. data/lib/multimedia_paradise/yaml/movie_reviews/the_hateful_eight_september_2016.md +305 -0
  392. data/lib/multimedia_paradise/yaml/music_genres.yml +51 -0
  393. data/lib/multimedia_paradise/yaml/playlist.yml +127 -0
  394. data/lib/multimedia_paradise/yaml/radio/README.md +5 -0
  395. data/lib/multimedia_paradise/yaml/radio/radio_stations.yml +359 -0
  396. data/lib/multimedia_paradise/yaml/song_tags.yml +815 -0
  397. data/lib/multimedia_paradise/yaml/tales_from_the_crypt/tales_from_the_crypt.yml +418 -0
  398. data/lib/multimedia_paradise/yaml/tom_and_jerry/README.md +2 -0
  399. data/lib/multimedia_paradise/yaml/tom_and_jerry/tom_and_jerry_episodes.yml +27 -0
  400. data/lib/multimedia_paradise/yaml/tv_channels/tv_channels.yml +46 -0
  401. data/lib/multimedia_paradise/yaml/use_this_video_player.yml +1 -0
  402. data/lib/multimedia_paradise/yaml/video/video.yml +26 -0
  403. data/lib/multimedia_paradise/yaml/video_collection/video_collection.yml +1933 -0
  404. data/lib/multimedia_paradise/yaml/video_encoding_settings.yml +62 -0
  405. data/lib/multimedia_paradise/yaml/video_filter_aliases.yml +221 -0
  406. data/lib/multimedia_paradise/yaml/youtube/alltagsgeschichte/alltagsgeschichte.yml +172 -0
  407. data/lib/multimedia_paradise/yaml/youtube/songs/README.md +3 -0
  408. data/lib/multimedia_paradise/yaml/youtube/songs/songs.yml +6 -0
  409. data/lib/multimedia_paradise/yaml/youtube_playlist/youtube_playlist.yml +6 -0
  410. data/lib/multimedia_paradise.rb +5 -0
  411. data/multimedia_paradise.gemspec +76 -0
  412. data/test/testing_audio_player.rb +15 -0
  413. data/test/testing_ffmpeg_options.rb +14 -0
  414. data/test/testing_file_duration.rb +17 -0
  415. data/test/testing_modify_year_of_audio_file.rb +14 -0
  416. data/test/testing_multimedia_paradise_project.rb +151 -0
  417. metadata +581 -0
@@ -0,0 +1,2017 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === MultimediaParadise::CutMultimedia
6
+ #
7
+ # This class can be used to cut audio and video files, and merge the
8
+ # newly created files together.
9
+ #
10
+ # This is mostly a standalone class and thus you can require it in a
11
+ # special way:
12
+ #
13
+ # require 'multimedia_paradise/toplevel_cut_multimedia'
14
+ #
15
+ # Note that this class can operate in two ways:
16
+ #
17
+ # - from the commandline, without interactive questions
18
+ # - in an interactive manner, with the user typing in
19
+ # instructions that will be evaluated (thus the REPL
20
+ # mode)
21
+ #
22
+ # See to the end of this file for specific usage examples.
23
+ #
24
+ # Usage examples in Ruby Code:
25
+ #
26
+ # MultimediaParadise::CutMultimedia.new
27
+ # MultimediaParadise::CutMultimedia.new(ARGV)
28
+ # MultimediaParadise::CutMultimedia.new("foo.mp3")
29
+ # cut_multimedia = MultimediaParadise::CutMultimedia.new("foo.mp3", :do_not_run_yet)
30
+ #
31
+ # =========================================================================== #
32
+ # require 'multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb'
33
+ # MultimediaParadise::CutMultimedia.new(ARGV) { :gui }
34
+ # =========================================================================== #
35
+ require 'multimedia_paradise/multimedia/base.rb'
36
+ require 'multimedia_paradise/multimedia/cut_multimedia/interactive_menu.rb'
37
+
38
+ module MultimediaParadise
39
+
40
+ class CutMultimedia < ::MultimediaParadise::MultimediaBase # === MultimediaParadise::CutMultimedia
41
+
42
+ begin
43
+ require 'hours_to_seconds/hours_to_seconds.rb'
44
+ rescue LoadError; end
45
+
46
+ begin # Try to use the KdeKonsole if it is available.
47
+ require 'roebe/requires/require_kde_konsole.rb'
48
+ rescue LoadError; end
49
+
50
+ require 'multimedia_paradise/toplevel_methods/chop_into_segments_of_n_seconds_size.rb'
51
+ require 'multimedia_paradise/audio/file_duration/file_duration.rb'
52
+
53
+ # ========================================================================= #
54
+ # === NAMESPACE
55
+ # ========================================================================= #
56
+ NAMESPACE = inspect
57
+
58
+ # ========================================================================= #
59
+ # === Determine whether Readline is available or whether it is not
60
+ #
61
+ # If readline is available then we will try to use it.
62
+ # ========================================================================= #
63
+ begin
64
+ require 'readline'
65
+ IS_READLINE_AVAILABLE = true
66
+ rescue LoadError
67
+ IS_READLINE_AVAILABLE = false
68
+ end
69
+
70
+ # ========================================================================= #
71
+ # === DEFAULT_INPUT_FILE
72
+ # ========================================================================= #
73
+ DEFAULT_INPUT_FILE =
74
+ '/home/x/songs/Womack_and_Womack_Teardrops.mp3'
75
+
76
+ # ========================================================================= #
77
+ # === FILE_LAST_USED
78
+ # ========================================================================= #
79
+ FILE_LAST_USED =
80
+ "#{MultimediaParadise.log_dir?}cut_audio_last_file_used.yml"
81
+
82
+ # ========================================================================= #
83
+ # === CREATE_A_LOG_FILE
84
+ #
85
+ # If this constant is true then we will create a log file.
86
+ # ========================================================================= #
87
+ CREATE_A_LOG_FILE = false
88
+
89
+ # ========================================================================= #
90
+ # === PROMPT_TO_USE
91
+ # ========================================================================= #
92
+ PROMPT_TO_USE = '> '
93
+
94
+ require 'multimedia_paradise/toplevel_methods/player_in_use.rb'
95
+ # ========================================================================= #
96
+ # === USE_THIS_PLAYER
97
+ #
98
+ # Which audio/video player to use for audio-playback.
99
+ #
100
+ # By default we will use the player set on the toplevel MultimediaParadise
101
+ # namespace.
102
+ #
103
+ # This constant will then return e. g. a String such as "mpv".
104
+ # ========================================================================= #
105
+ USE_THIS_PLAYER = MultimediaParadise.player?
106
+
107
+ # ========================================================================= #
108
+ # === ARRAY_LOCATIONS_TO_CHECK_FOR_FFMPEG
109
+ #
110
+ # The following constant defines where to check for ffmpeg.
111
+ #
112
+ # This may be necessary so that we can determine whether the user
113
+ # has ffmpg installed.
114
+ # ========================================================================= #
115
+ array = %w(
116
+ /usr/bin/
117
+ c:\usr\bin
118
+ ) # Build-up our Array here.
119
+ array << '/usr/local/bin/'
120
+ array << ENV['MY_SYSBIN'].to_s+'/' if ENV['MY_SYSBIN']
121
+ # ========================================================================= #
122
+ # Append the locations found in the PATH variable next.
123
+ # ========================================================================= #
124
+ if ENV['PATH']
125
+ array << ENV['PATH'].to_s.split(':') # Also add the PATH variable.
126
+ end
127
+ ARRAY_LOCATIONS_TO_CHECK_FOR_FFMPEG = array.flatten.uniq # Set it here.
128
+
129
+ # ========================================================================= #
130
+ # === initialize
131
+ #
132
+ # The very first argument to this class should be location to the
133
+ # file that you may want to edit.
134
+ # ========================================================================= #
135
+ def initialize(
136
+ commandline_arguments = nil,
137
+ run_already = true
138
+ )
139
+ register_sigint
140
+ reset
141
+ # ======================================================================= #
142
+ # First handle special Symbols given to this class.
143
+ # ======================================================================= #
144
+ case commandline_arguments
145
+ when :interactive,
146
+ :run_interactive
147
+ set_interactive_mode_then_enter_interactive_mode
148
+ end
149
+ if commandline_arguments and commandline_arguments.is_a?(Array) and
150
+ commandline_arguments.empty?
151
+ commandline_arguments << DEFAULT_INPUT_FILE
152
+ end
153
+ set_commandline_arguments(
154
+ commandline_arguments
155
+ )
156
+ # ======================================================================= #
157
+ # === Handle blocks next
158
+ # ======================================================================= #
159
+ if block_given?
160
+ yielded = yield
161
+ case yielded
162
+ # ===================================================================== #
163
+ # === :gui
164
+ # ===================================================================== #
165
+ when :gui
166
+ @usage_mode = :gui
167
+ end
168
+ end
169
+ # ======================================================================= #
170
+ # Next check whether a file exists, before we enter the interactive
171
+ # part potentially.
172
+ # ======================================================================= #
173
+ check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file
174
+ # ======================================================================= #
175
+ # The following check must happen before we invoke set_file()
176
+ # because set_file may also exit the program. This is not
177
+ # deserved when we run the program in interactive mode.
178
+ # ======================================================================= #
179
+ case run_already
180
+ # ======================================================================= #
181
+ # === :dont_run_yet
182
+ # ======================================================================= #
183
+ when :dont_run_yet,
184
+ :do_not_run_yet
185
+ run_already = false
186
+ # ======================================================================= #
187
+ # === :interactive
188
+ # ======================================================================= #
189
+ when :interactive,
190
+ :run_interactive
191
+ set_interactive_mode_then_enter_interactive_mode
192
+ run_already = false
193
+ end
194
+ run if run_already
195
+ end
196
+
197
+ # ========================================================================= #
198
+ # === reset (reset tag)
199
+ # ========================================================================= #
200
+ def reset
201
+ super()
202
+ # ======================================================================= #
203
+ # === @namespace
204
+ # ======================================================================= #
205
+ @namespace = NAMESPACE
206
+ # ======================================================================= #
207
+ # === @toggle
208
+ # ======================================================================= #
209
+ @toggle = false
210
+ # ======================================================================= #
211
+ # === @user_input
212
+ #
213
+ # Set the user input nil on startup.
214
+ # ======================================================================= #
215
+ @user_input = nil
216
+ # ======================================================================= #
217
+ # === @array_input_history
218
+ #
219
+ # Keep the input-history stored in the following Array.
220
+ # ======================================================================= #
221
+ @array_input_history = []
222
+ # ======================================================================= #
223
+ # === @we_are_allowed_to_run_system_command
224
+ # ======================================================================= #
225
+ @we_are_allowed_to_run_system_command = true
226
+ # ======================================================================= #
227
+ # === @work_on_this_file
228
+ #
229
+ # This variable will keep track on which file (audio or video) we
230
+ # will work on for the running instance. It will, once set,
231
+ # contain the path (a String) to the local file.
232
+ # ======================================================================= #
233
+ @work_on_this_file = nil
234
+ # ======================================================================= #
235
+ # === @output_file
236
+ #
237
+ # We keep track of the output file, so that any possible GUI we may
238
+ # use also benefits from this.
239
+ # ======================================================================= #
240
+ @output_file = nil
241
+ # ======================================================================= #
242
+ # === @may_we_exit
243
+ # ======================================================================= #
244
+ @may_we_exit = false
245
+ # ======================================================================= #
246
+ # === @array_all_start_positions
247
+ # ======================================================================= #
248
+ @array_all_start_positions = []
249
+ # ======================================================================= #
250
+ # === @create_a_log_file
251
+ #
252
+ # Next determine whether we will create a log file or whether we
253
+ # will not.
254
+ # ======================================================================= #
255
+ @create_a_log_file = CREATE_A_LOG_FILE
256
+ # ======================================================================= #
257
+ # === @t
258
+ # ======================================================================= #
259
+ @t = nil
260
+ # ======================================================================= #
261
+ # === @usage_mode
262
+ #
263
+ # This variable can have the following modes:
264
+ #
265
+ # :interactive
266
+ # :gui
267
+ #
268
+ # ======================================================================= #
269
+ @usage_mode = :interactive
270
+ # ======================================================================= #
271
+ # Re-set the two main Arrays that keep track of start and end positions
272
+ # on the assigned main file.
273
+ # ======================================================================= #
274
+ clear_setpoints
275
+ initialize_twentyfour_hours_notation_object
276
+ end
277
+
278
+ # ========================================================================= #
279
+ # === in_commandline_mode?
280
+ # ========================================================================= #
281
+ def in_commandline_mode?
282
+ @usage_mode == :interactive
283
+ end
284
+
285
+ # ========================================================================= #
286
+ # === start_position?
287
+ #
288
+ # This method depends on the method called array_all_start_positions?.
289
+ # ========================================================================= #
290
+ def start_position?
291
+ start_positions?.first # For now, always use the first entry.
292
+ end; alias start_position start_position? # === start_position
293
+ alias starting_position? start_position? # === starting_position?
294
+
295
+ # ========================================================================= #
296
+ # === modify_the_main_file_by_prepending_the_upcased_string_done_to_it
297
+ #
298
+ # The point of this method is to mark an audio file as "done".
299
+ # ========================================================================= #
300
+ def modify_the_main_file_by_prepending_the_upcased_string_done_to_it(
301
+ from = @work_on_this_file,
302
+ to = "DONE_#{@work_on_this_file}"
303
+ )
304
+ if from.include? '/'
305
+ # ===================================================================== #
306
+ # In this case, the above won't work, so we must use another approach.
307
+ # ===================================================================== #
308
+ splitted = from.split('/')
309
+ splitted.last.prepend('DONE_')
310
+ to = splitted.join('/')
311
+ end
312
+ opne "Now renaming #{sfile(from)} to #{sfile(to)}."
313
+ File.rename(from, to)
314
+ set_work_on_this_file(to)
315
+ end
316
+
317
+ # ========================================================================= #
318
+ # === start_position=
319
+ # ========================================================================= #
320
+ def start_position=(i) # This will always set to the first entry point of our array.
321
+ all_start_positions?[0,0] = i.to_i
322
+ end
323
+
324
+ # ========================================================================= #
325
+ # === emphasis
326
+ #
327
+ # Internal emphasis.
328
+ # ========================================================================= #
329
+ def emphasis(i)
330
+ orange(i)
331
+ end
332
+
333
+ # ========================================================================= #
334
+ # === ensure_that_array_cut_end_is_valid
335
+ #
336
+ # The end positions should always be valid.
337
+ # ========================================================================= #
338
+ def ensure_that_array_cut_end_is_valid(i = duration?)
339
+ if end_positions?.empty? # We must ensure that it has the length.
340
+ set_length(i)
341
+ end
342
+ end
343
+
344
+ # ========================================================================= #
345
+ # === array_all_end_positions?
346
+ # ========================================================================= #
347
+ def array_all_end_positions?
348
+ @array_all_end_positions
349
+ end; alias end_positions? array_all_end_positions? # === end_positions?
350
+ alias end_position? array_all_end_positions? # === end_positions?
351
+ alias all_end_positions? array_all_end_positions? # === all_end_positions?
352
+
353
+ # ========================================================================= #
354
+ # === feedback_all_end_points
355
+ # ========================================================================= #
356
+ def feedback_all_end_points(
357
+ i = all_end_positions?
358
+ )
359
+ e "Feedbacking all #{emphasis('end-points')} next."
360
+ pp i
361
+ end
362
+
363
+ # ========================================================================= #
364
+ # === sanitize
365
+ #
366
+ # This method will sanitize the input that represents time. We want
367
+ # a number to mean "n seconds".
368
+ # ========================================================================= #
369
+ def sanitize(i)
370
+ # ======================================================================= #
371
+ # Simply replace all ',' with '.', in the event the user typed these.
372
+ # ======================================================================= #
373
+ i.tr!(',','.') if i.include? ','
374
+ # ======================================================================= #
375
+ # Since as of Dec 2015 we will also check for the input containing
376
+ # ':' tokens. If so then we assume that the user wants to use
377
+ # the 24 hours notation such as 05:30, which would mean 5 minutes
378
+ # and 30 seconds.
379
+ # ======================================================================= #
380
+ if i.include? ':'
381
+ i[0,1] = '' if i.start_with? 'e' # Chop off leading 'e' parts.
382
+ # ===================================================================== #
383
+ # The following code will also work for .mp3 files that are longer
384
+ # than 59:59 seconds.
385
+ # ===================================================================== #
386
+ splitted = i.split(':') # Split on all ':'
387
+ if splitted.size < 3
388
+ # =================================================================== #
389
+ # Prepend 00 in this case.
390
+ # =================================================================== #
391
+ splitted[0,0] = '00'
392
+ end
393
+ i = splitted.join(':')
394
+ # ===================================================================== #
395
+ # Next, convert it into the amount o seconds.
396
+ # ===================================================================== #
397
+ i = HoursToSeconds[i, :be_quiet]
398
+ end
399
+ return i.to_s # This must always return a String.
400
+ end
401
+
402
+ # ========================================================================= #
403
+ # === display_the_prompt_in_use_to_the_user
404
+ # ========================================================================= #
405
+ def display_the_prompt_in_use_to_the_user
406
+ print PROMPT_TO_USE
407
+ end
408
+
409
+ # ========================================================================= #
410
+ # === obtain_user_input
411
+ #
412
+ # This method will designate @user_input - in other words it will obtain
413
+ # the user input.
414
+ # ========================================================================= #
415
+ def obtain_user_input
416
+ if use_readline?
417
+ @user_input = Readline.readline('', true)
418
+ else
419
+ @user_input = $stdin.gets.chomp
420
+ end
421
+ end
422
+
423
+ # ========================================================================= #
424
+ # === determine_the_duration
425
+ #
426
+ # Set @duration here.
427
+ # ========================================================================= #
428
+ def determine_the_duration(
429
+ i = main_file?
430
+ ) # This will determine the ivar @duration.
431
+ @duration = MultimediaParadise::FileDuration.new(i) { :be_quiet } # Also get the duration of the file here.
432
+ return @duration.duration? # This should return the duration in question, as a Float.
433
+ end; alias determine_duration determine_the_duration # === determine_duration
434
+
435
+ # ========================================================================= #
436
+ # === overwrite_old_file
437
+ #
438
+ # Note that when we overwrite the old file, we must re-assign the
439
+ # main file to that file again.
440
+ # ========================================================================= #
441
+ def overwrite_old_file(
442
+ optional_argument_be_verbose = false
443
+ )
444
+ old_file = output_file?
445
+ case optional_argument_be_verbose
446
+ when :be_verbose
447
+ optional_argument_be_verbose = true
448
+ end
449
+ if optional_argument_be_verbose
450
+ e 'Now overwriting the file `'+sfile(old_file)+'`.'
451
+ end
452
+ new_file = input_file?
453
+ mv(old_file, new_file)
454
+ assign_file(new_file) # Assign the new file again here.
455
+ end
456
+
457
+ # ========================================================================= #
458
+ # === editor?
459
+ # ========================================================================= #
460
+ def editor?
461
+ ::MultimediaParadise::YOUR_EDITOR
462
+ end
463
+
464
+ # ========================================================================= #
465
+ # === report_half_the_duration
466
+ # ========================================================================= #
467
+ def report_half_the_duration
468
+ e rev+'Half the duration, in seconds, is:'
469
+ e
470
+ e simp(' '+(duration?/2.0).to_s)
471
+ e
472
+ end
473
+
474
+ # ========================================================================= #
475
+ # === end?
476
+ #
477
+ # Only return the very last entry here, from all stored end positions.
478
+ # ========================================================================= #
479
+ def end?
480
+ all_end_positions?.last
481
+ end
482
+
483
+ # ========================================================================= #
484
+ # === start_point_was_defined_yet?
485
+ # ========================================================================= #
486
+ def start_point_was_defined_yet?
487
+ !all_start_positions?.empty?
488
+ end
489
+
490
+ # ========================================================================= #
491
+ # === no_start_point_was_defined_yet?
492
+ # ========================================================================= #
493
+ def no_start_point_was_defined_yet?
494
+ all_start_positions?.empty?
495
+ end
496
+
497
+ # ========================================================================= #
498
+ # === end_point_was_defined_yet?
499
+ # ========================================================================= #
500
+ def end_point_was_defined_yet?
501
+ !all_end_positions?.empty?
502
+ end
503
+
504
+ # ========================================================================= #
505
+ # === no_end_point_was_defined_yet?
506
+ # ========================================================================= #
507
+ def no_end_point_was_defined_yet?
508
+ !end_point_was_defined_yet?
509
+ end
510
+
511
+ # ========================================================================= #
512
+ # === user_did_input_only_numbers
513
+ #
514
+ # Simplified start an end point notation.
515
+ # ========================================================================= #
516
+ def user_did_input_only_numbers(i)
517
+ @toggle = !@toggle # Toggle it here.
518
+ case @toggle
519
+ when true
520
+ set_start(i)
521
+ when false
522
+ set_end(i)
523
+ end
524
+ end
525
+
526
+ # ========================================================================= #
527
+ # === show_output_files
528
+ # ========================================================================= #
529
+ def show_output_files(
530
+ i = @array_output_files
531
+ )
532
+ unless i.empty?
533
+ e N+'We created these output files:'
534
+ e
535
+ end
536
+ i.each_with_index {|entry, index|
537
+ entry = entry.to_s
538
+ index += 1
539
+ index = ('('+index.to_s + ')').rjust(4)
540
+ if entry.start_with? '"' and entry.end_with? '"'
541
+ entry = entry[1..-2]
542
+ end
543
+ e ' '+index+' '+sfancy(entry)
544
+ }; e
545
+ end
546
+
547
+ # ========================================================================= #
548
+ # === set_start_and_end_position
549
+ #
550
+ # This variant combines set_start() with set_end().
551
+ # ========================================================================= #
552
+ def set_start_and_end_position(i)
553
+ splitted = i.split('-')
554
+ set_start(splitted.first)
555
+ set_end(splitted[1])
556
+ end
557
+
558
+ # ========================================================================= #
559
+ # === play_the_audio_file
560
+ # ========================================================================= #
561
+ def play_the_audio_file(i = file?)
562
+ if i
563
+ e "#{Colours.rev}Now playing the assigned "\
564
+ "file `#{sfile(i.to_s)}`."
565
+ esystem("#{MultimediaParadise.player?} #{i}")
566
+ else
567
+ e 'No file was found.'
568
+ end
569
+ end
570
+
571
+ # ========================================================================= #
572
+ # === feedback_start_cutting_at
573
+ # ========================================================================= #
574
+ def feedback_start_cutting_at
575
+ here = all_start_positions?
576
+ if here.empty?
577
+ e 'No start positions have been determined yet.'
578
+ else
579
+ e 'We will start cutting at '+
580
+ simp(here.first.to_s)+' seconds.'
581
+ end
582
+ end
583
+
584
+ # ========================================================================= #
585
+ # === register_sigint
586
+ # ========================================================================= #
587
+ def register_sigint
588
+ Signal.trap('SIGINT') {
589
+ exit_properly
590
+ }
591
+ end
592
+
593
+ # ========================================================================= #
594
+ # === do_general_exit_actions (exit tag)
595
+ # ========================================================================= #
596
+ def do_general_exit_actions
597
+ try_to_rename_kde_konsole_tab('_')
598
+ :exit
599
+ end
600
+
601
+ # ========================================================================= #
602
+ # === green_colour
603
+ # ========================================================================= #
604
+ def green_colour
605
+ if use_colours?
606
+ ::Colours::CGREEN
607
+ else
608
+ ''.dup
609
+ end
610
+ end
611
+
612
+ # ========================================================================= #
613
+ # === try_to_use_the_last_file
614
+ #
615
+ # This method can be used to re-use the last used file from a prior
616
+ # run.
617
+ # ========================================================================= #
618
+ def try_to_use_the_last_file(
619
+ i = FILE_LAST_USED
620
+ )
621
+ if File.exist? i
622
+ set_file(
623
+ YAML.load_file(i).strip,
624
+ :do_not_keep_track # <- So to not save into a local .yml file.
625
+ )
626
+ else
627
+ opnn; no_file_exists_at(i)
628
+ end
629
+ end
630
+
631
+ # ========================================================================= #
632
+ # === report_duration_of_multimedia_file
633
+ #
634
+ # This method will report the duration of the multimedia file.
635
+ #
636
+ # There exists an optional argument called `this_file`. If this argument
637
+ # is used, then we will report the duration of that file instead.
638
+ #
639
+ # feedback_duration is an alias to this method.
640
+ # ========================================================================= #
641
+ def report_duration_of_multimedia_file(
642
+ this_file = nil
643
+ )
644
+ use_this_file = file? # Default assignment.
645
+ use_this_file = this_file if this_file
646
+ duration = duration?
647
+ if use_this_file and File.exist?(use_this_file.to_s) # Handle alternative duration.
648
+ duration = determine_duration(use_this_file) # Calculate the new duration of that file.
649
+ if duration
650
+ long_form = '('+Time.at(duration).utc.strftime('%H:%M:%S').to_s+')'
651
+ e
652
+ e 'The duration of the file '+sfile(use_this_file)+' is: '
653
+ e
654
+ e simp(" #{duration} seconds #{long_form}")
655
+ e
656
+ end
657
+ else
658
+ report_no_file_is_assigned
659
+ end
660
+ end; alias feedback_duration report_duration_of_multimedia_file # === feedback_duration
661
+ alias report_duration_of_this_file report_duration_of_multimedia_file # === report_duration_of_this_file
662
+ alias report_length report_duration_of_multimedia_file # === report_length
663
+
664
+ # ========================================================================= #
665
+ # === report_status
666
+ # ========================================================================= #
667
+ def report_status
668
+ report_duration_of_multimedia_file
669
+ report_points
670
+ end
671
+
672
+ # ========================================================================= #
673
+ # === show_history
674
+ #
675
+ # This method will show the input-history used for CutMultimedia.
676
+ # ========================================================================= #
677
+ def show_history(
678
+ i = @array_input_history
679
+ )
680
+ e; i.each_with_index {|command, index|
681
+ index += 1
682
+ e index.to_s.rjust(3)+' '+sfancy(command)
683
+ }; e
684
+ end
685
+
686
+ # ========================================================================= #
687
+ # === intersect
688
+ #
689
+ # This method will cut out some middle/central part from a .mp3 file.
690
+ #
691
+ # Usage example:
692
+ #
693
+ # intersect 29:23-29:45
694
+ # intersect 11:20-15:45
695
+ #
696
+ # ========================================================================= #
697
+ def intersect(i)
698
+ i = i.first if i.is_a? Array
699
+ unless main_file?
700
+ opne 'Please assign a valid, existing file.'
701
+ return
702
+ end
703
+ if i.include? '-' # Ok, then we can split there.
704
+ splitted = i.split '-'
705
+ first, last = *splitted
706
+ # ===================================================================== #
707
+ # Next, we must convert these numbers into seconds, if it includes
708
+ # at least one ':' character.
709
+ # ===================================================================== #
710
+ if first.include? ':'
711
+ first.prepend '00:' if first.count(':') == 1
712
+ first = HoursToSeconds[first, :be_silent].to_s
713
+ last.prepend '00:' if last.count(':') == 1
714
+ last = HoursToSeconds[last, :be_silent].to_s
715
+ end
716
+ # ===================================================================== #
717
+ # === Operate on the leading segment first:
718
+ # ===================================================================== #
719
+ e '(1) We will next chop out the leading segment:'
720
+ clear_setpoints
721
+ set_start(0)
722
+ set_end(first)
723
+ do_cut
724
+ clear_setpoints
725
+ # ===================================================================== #
726
+ # === Operater on the trailing segment next:
727
+ # ===================================================================== #
728
+ e '(2) We will next chop out the trailing segment:'
729
+ set_start(last)
730
+ set_end(return_end_of_file_in_seconds)
731
+ do_cut
732
+ clear_setpoints
733
+ end
734
+ store_here = "MERGED_FILES_#{input_file?}" # Where to store the merged files.
735
+ merge(
736
+ output_files?, store_here
737
+ )
738
+ if File.exist? store_here
739
+ opne "The file should now exist at #{sfile(store_here)}."
740
+ remove(output_files?)
741
+ end
742
+ end
743
+
744
+ # ========================================================================= #
745
+ # === report_that_we_are_finished_now
746
+ #
747
+ # This method will notify the user that we have finished cutting our
748
+ # audio files.
749
+ # ========================================================================= #
750
+ def report_that_we_are_finished_now(
751
+ shall_we_report_errors = true
752
+ )
753
+ case shall_we_report_errors
754
+ when :no_error_reporting
755
+ shall_we_report_errors = false
756
+ end
757
+ e 'We have finished cutting our audio files now.'
758
+ e
759
+ _ = output_file?
760
+ if _.nil?
761
+ e 'No output file was assigned.'
762
+ return
763
+ end
764
+ if _.include?(' ') # Handle ' ' characters.
765
+ if _.start_with? '"' and _.end_with? '"'
766
+ _ = _[1..-2]
767
+ end
768
+ end
769
+ if File.exist?(_) and !File.zero?(_)
770
+ output_files = [output_files?].flatten.compact
771
+ if output_files.size > 1
772
+ e 'The output files should now be available at:'
773
+ output_files.each {|file|
774
+ e " #{sfile(file)}"
775
+ }
776
+ e 'If you want to merge these above-listed files together, '\
777
+ 'input "merge".'
778
+ else # Else just one file.
779
+ # =================================================================== #
780
+ # Report the duration of that new file.
781
+ # =================================================================== #
782
+ report_duration_of_this_file(_)
783
+ e 'The output file should now be available at:'
784
+ e
785
+ e " #{sfile(_)}"
786
+ e
787
+ end
788
+ else
789
+ if shall_we_report_errors
790
+ e 'It seems as if something has failed. Please check the '\
791
+ 'above output from ffmpeg,'
792
+ e 'it may be that ffmpeg faced a problem such as missing '\
793
+ '.mp3 support.'
794
+ end
795
+ end
796
+ end
797
+
798
+ # ========================================================================= #
799
+ # === report_points
800
+ #
801
+ # This method can be used to report all start and end positions.
802
+ # ========================================================================= #
803
+ def report_points
804
+ unless all_start_positions?.empty?
805
+ e simp('Startpoints')+' for cutting:'
806
+ print ' '; pp all_start_positions?
807
+ end
808
+ unless all_end_positions?.empty?
809
+ e simp('Endpoints')+' for cutting:'
810
+ print ' '; pp all_end_positions?
811
+ end
812
+ # ======================================================================= #
813
+ # Next check whether both are empty.
814
+ # ======================================================================= #
815
+ if all_end_positions?.empty? and
816
+ all_start_positions?.empty?
817
+ e 'It seems as if you have not yet determined any boundaries '\
818
+ 'as to where to cut at, yet.'
819
+ end
820
+ end
821
+
822
+ # ========================================================================= #
823
+ # === feedback_cutting
824
+ # ========================================================================= #
825
+ def feedback_cutting # the verbose variant.
826
+ e 'We will cut the file '+sfile(work_on_which_file?)+'.'
827
+ start_cutting_when = 'We will start cutting at '+
828
+ sfancy(all_start_positions?.first.to_s)+' seconds.'
829
+ if all_start_positions?.size > 1
830
+ start_cutting_when << ' Additionally we found entries at '+
831
+ sfancy(all_start_positions?[1..-1].join(', '))+'.'
832
+ end
833
+ e start_cutting_when
834
+ if !all_end_positions?.empty?
835
+ end_cutting_when = 'We will end the cutting at '+
836
+ sfancy(all_end_positions?.first.to_s)+
837
+ ' seconds. '
838
+ if all_end_positions?.size > 1
839
+ end_cutting_when << ' Additionally we found entries at '+
840
+ sfancy(all_end_positions?[1..-1].join(', '))+'.'
841
+ end
842
+ e end_cutting_when
843
+ else
844
+ e 'We have not yet defined an end position for our file.'
845
+ e 'You can do this with the command '+sfancy('cut_end')+'.'
846
+ end
847
+ duration = all_end_positions?.first.to_i - all_start_positions?.first.to_i
848
+ e 'The duration of our new file will be '+sfancy(
849
+ duration.to_s)+' seconds.' if duration?
850
+ end; private :feedback_cutting
851
+
852
+ # ========================================================================= #
853
+ # === show_invocation_usage
854
+ # ========================================================================= #
855
+ def show_invocation_usage
856
+ if in_commandline_mode?
857
+ cliner
858
+ e 'Usage from the commandline:'
859
+ e
860
+ e ' cut_multimedia name_of_audio_file_goes_here'
861
+ e ' cut_multimedia name_of_video_file_goes_here'
862
+ e
863
+ cliner
864
+ end
865
+ end
866
+
867
+ # ========================================================================= #
868
+ # === append_the_user_input_onto_the_history
869
+ # ========================================================================= #
870
+ def append_the_user_input_onto_the_history(
871
+ i = @user_input
872
+ )
873
+ # ======================================================================= #
874
+ # Keep track of the input-history next.
875
+ # ======================================================================= #
876
+ @array_input_history << i if i
877
+ end
878
+
879
+ # ========================================================================= #
880
+ # === report_which_player_we_will_use
881
+ # ========================================================================= #
882
+ def report_which_player_we_will_use
883
+ e "#{rev}We will use `#{sfancy(MultimediaParadise.player?)}` "\
884
+ "to play multimedia files."
885
+ end
886
+
887
+ # ========================================================================= #
888
+ # === report_no_file_is_assigned
889
+ # ========================================================================= #
890
+ def report_no_file_is_assigned
891
+ opne 'No file is assigned.'
892
+ end
893
+
894
+ # ========================================================================= #
895
+ # === report_does_the_main_file_exist?
896
+ #
897
+ # Notify us whether the main file exists or whether it does not.
898
+ # ========================================================================= #
899
+ def report_does_the_main_file_exist?
900
+ e 'Does the main file exist? '+sfancy(
901
+ verbose_truth(File.exist?(main_file?.to_s).to_s)
902
+ )
903
+ end
904
+
905
+ # ========================================================================= #
906
+ # === create_a_log_file?
907
+ # ========================================================================= #
908
+ def create_a_log_file?
909
+ @create_a_log_file
910
+ end; alias create_log_file? create_a_log_file? # === create_log_file?
911
+
912
+ # ========================================================================= #
913
+ # === duration?
914
+ # ========================================================================= #
915
+ def duration?
916
+ if @work_on_this_file
917
+ @duration.n_seconds?
918
+ else
919
+ report_no_file_is_assigned
920
+ 0 # 0 seconds in this case.
921
+ end
922
+ end
923
+
924
+ # ========================================================================= #
925
+ # === use_readline?
926
+ # ========================================================================= #
927
+ def use_readline?
928
+ IS_READLINE_AVAILABLE
929
+ end; private :use_readline?
930
+
931
+ # ========================================================================= #
932
+ # === show_audio_files
933
+ # ========================================================================= #
934
+ def show_audio_files
935
+ Dir['*'].each {|entry|
936
+ if is_an_audio_file?(entry)
937
+ e sfile(entry)
938
+ end
939
+ }
940
+ end
941
+
942
+ # ========================================================================= #
943
+ # === open_this_file_in_editor
944
+ # ========================================================================= #
945
+ def open_this_file_in_editor
946
+ _ = editor?+' '+__FILE__
947
+ esystem _
948
+ end; private :open_this_file_in_editor
949
+
950
+ # ========================================================================= #
951
+ # === esystem
952
+ # ========================================================================= #
953
+ def esystem(i)
954
+ e " #{teal(i)}"
955
+ system(i) if @we_are_allowed_to_run_system_command
956
+ end
957
+
958
+ # ========================================================================= #
959
+ # === delete_audio_file
960
+ # ========================================================================= #
961
+ def delete_audio_file(
962
+ i = main_file?
963
+ )
964
+ File.delete(i) if File.exist? i
965
+ end; private :delete_audio_file
966
+
967
+ # ========================================================================= #
968
+ # === return_end_of_file_in_seconds
969
+ #
970
+ # Will always return a String.
971
+ # ========================================================================= #
972
+ def return_end_of_file_in_seconds
973
+ duration?.to_s
974
+ end; alias length_of_audio_file return_end_of_file_in_seconds # === length_of_audio_file
975
+ alias length_of_audio_file? return_end_of_file_in_seconds # === length_of_audio_file?
976
+
977
+ # ========================================================================= #
978
+ # === show_help (help tag, usage tag)
979
+ #
980
+ # This method will show the help-options for this class.
981
+ #
982
+ # To invoke this from the commandline, try:
983
+ #
984
+ # cut_audio --help
985
+ #
986
+ # ========================================================================= #
987
+ def show_help(
988
+ i = main_file?,
989
+ shall_we_exit = :do_not_exit
990
+ )
991
+ case shall_we_exit
992
+ when :then_exit
993
+ shall_we_exit = true
994
+ else
995
+ shall_we_exit = false
996
+ end
997
+ report_status if File.exist? i.to_s
998
+ show_invocation_usage
999
+ e "#{N}The available options for the #{sfancy('CutMultimedia class')}"\
1000
+ " are:#{green_colour}#{N}#{N}"
1001
+ e
1002
+ eparse ' trim # this will trim from the left-hand '\
1003
+ 'side of the multimedia-file'
1004
+ eparse ' # ^^^ also known as left-chop or just lchop'
1005
+ eparse ' show_audio_files # show the local audio files'
1006
+ eparse ' report_half_the_duration # report the half-duration of a song'
1007
+ eparse ' report_which_player_we_will_use # report which multimedia-player is in use'
1008
+ eparse ' play # play the currently active song/video file'
1009
+ eparse ' q # q for quit, to exit. Or '\
1010
+ 'just use "exit" or "quit".'
1011
+ eparse ' feedback # provide some general '\
1012
+ 'information about this class'
1013
+ eparse ' cut # do the actual cutting'
1014
+ eparse ' disable # dont run system '\
1015
+ 'command (in case you have to debug something)'
1016
+ eparse ' duration? # show the duration '\
1017
+ 'of the file in question'
1018
+ eparse ' s[number] # start to cut at this '\
1019
+ 'start-position in seconds - example: s5'
1020
+ eparse ' e[number] # stop to cut at this end-position'
1021
+ eparse ' play # to use mplayer to '\
1022
+ 'play that file; p is a shorter alias to it'
1023
+ eparse ' merge # merge the cutted audio files together'
1024
+ eparse ' --last-file # re-use the last file that was used '\
1025
+ 'in a prior run'
1026
+ eparse ' open # open the file cut_audio.rb in your editor'
1027
+ eparse ' overwrite # overwrite the old file, with the new file'
1028
+ eparse ' points? # feedback all start and end points'
1029
+ eparse ' split # split an audio file into half'
1030
+ eparse ' chop # to chop off some seconds '\
1031
+ 'from the .mp3 file'
1032
+ eparse ' gui # start the ruby-gtk3 '\
1033
+ 'widget, a graphical user interface'
1034
+ e
1035
+ e
1036
+ cliner
1037
+ exit_properly if shall_we_exit
1038
+ end; alias show_usage show_help # === show_usage
1039
+
1040
+ # ========================================================================= #
1041
+ # === log_cut_action
1042
+ #
1043
+ # We will only create a log file if @create_log_file is true.
1044
+ #
1045
+ # This method requires four arguments.
1046
+ # ========================================================================= #
1047
+ def log_cut_action(
1048
+ start_position,
1049
+ end_position,
1050
+ command_that_was_used,
1051
+ output_file
1052
+ )
1053
+ append_what_into(
1054
+ 'Start position: '+start_position.to_s+N,
1055
+ output_file)
1056
+ append_what_into(
1057
+ 'End position: '+end_position.to_s+N,
1058
+ output_file)
1059
+ append_what_into(
1060
+ 'Command that was used:'+N+' '+command_that_was_used.to_s+N,
1061
+ output_file)
1062
+ end
1063
+
1064
+ # ========================================================================= #
1065
+ # === clear_setpoints
1066
+ #
1067
+ # This method will clear all setpoints, both the beginning and
1068
+ # the end array.
1069
+ # ========================================================================= #
1070
+ def clear_setpoints
1071
+ @array_all_start_positions = []
1072
+ @array_all_end_positions = []
1073
+ end
1074
+
1075
+ # ========================================================================= #
1076
+ # === do_use_mpv
1077
+ # ========================================================================= #
1078
+ def do_use_mpv
1079
+ e 'We will try to use mpv.'
1080
+ MultimediaParadise.set_use_this_multimedia_player(:mpv)
1081
+ end
1082
+
1083
+ # ========================================================================= #
1084
+ # === do_use_mplayer
1085
+ # ========================================================================= #
1086
+ def do_use_mplayer
1087
+ e 'We will try to use mplayer.'
1088
+ MultimediaParadise.set_use_this_multimedia_player(:mplayer)
1089
+ end
1090
+
1091
+ # ========================================================================= #
1092
+ # === do_reset_all_values_to_their_default_values
1093
+ # ========================================================================= #
1094
+ def do_reset_all_values_to_their_default_values
1095
+ opne 'Resetting all values to their defaults again.'
1096
+ _ = file? # Obtain a reference to the old file.
1097
+ reset # Then reset it.
1098
+ set_file(_)
1099
+ end
1100
+
1101
+ # ========================================================================= #
1102
+ # === array_all_start_positions?
1103
+ # ========================================================================= #
1104
+ def array_all_start_positions?
1105
+ @array_all_start_positions
1106
+ end; alias start_positions? array_all_start_positions? # === start_positions?
1107
+ alias all_start_positions? array_all_start_positions? # === all_start_positions?
1108
+
1109
+ # ========================================================================= #
1110
+ # === end_position= (end tag)
1111
+ #
1112
+ # Usage example:
1113
+ #
1114
+ # self.end_position = 5
1115
+ #
1116
+ # ========================================================================= #
1117
+ def end_position=(i = 1000)
1118
+ case i
1119
+ when :end # special instruction then
1120
+ i = duration?.to_f
1121
+ end
1122
+ all_end_positions?[0,0] = i.to_i
1123
+ end; alias set_length end_position= # === set_length
1124
+
1125
+ # ========================================================================= #
1126
+ # === delete_individual_audio_files
1127
+ #
1128
+ # This will delete
1129
+ # ========================================================================= #
1130
+ def delete_individual_audio_files
1131
+ _ = output_file?
1132
+ if _.empty?
1133
+ opne 'Nothing to delete.'
1134
+ else
1135
+ _ = _.join(', ') if _.is_a? Array
1136
+ if File.exist? _
1137
+ opne "Next deleting the file `#{sfile(_)}`."
1138
+ delete(_)
1139
+ else
1140
+ opnn; no_file_exists_at(_)
1141
+ end
1142
+ end
1143
+ end
1144
+
1145
+ # ========================================================================= #
1146
+ # === merge_these_files (merge tag)
1147
+ # ========================================================================= #
1148
+ def merge_these_files(
1149
+ array = @array_output_files,
1150
+ output_file = nil
1151
+ )
1152
+ if array.respond_to? :join
1153
+ array = array.join('\|')
1154
+ output_file = 'GENERIC_OUTPUT_FILE_'+input? if output_file.nil?
1155
+ cmd = 'ffmpeg -i concat:'+array+' -acodec copy '+output_file.to_s
1156
+ esystem cmd
1157
+ else
1158
+ e 'The input to the method merge_these_files() was not correct.'
1159
+ e 'Its class is: '+sfancy(array.class)
1160
+ end
1161
+ end; alias merge merge_these_files # === merge
1162
+
1163
+ # ========================================================================= #
1164
+ # === set_output_file
1165
+ # ========================================================================= #
1166
+ def set_output_file(i)
1167
+ i = i.to_s.dup
1168
+ # file_exists = false
1169
+ # file_exists = true if File.exist? i # Check whether the file exists.
1170
+ i = '"'+i+'"' if i.include? ' '
1171
+ @output_file = i
1172
+ end
1173
+
1174
+ # ========================================================================= #
1175
+ # === merge_created_files (merge tag)
1176
+ #
1177
+ # This will merge the various audio files.
1178
+ # ========================================================================= #
1179
+ def merge_created_files
1180
+ if output_files?.size > 1
1181
+ output_file = 'merged_audio_files_'+
1182
+ output_file?.
1183
+ sub(/\.mp3$/,'')+'.mp3'
1184
+ e 'Next merging the '+sfancy(output_files?.size.to_s)+
1185
+ ' files into '+sfile(output_file)+'.'
1186
+ merge_these_files(@array_output_files, output_file)
1187
+ if File.exist? output_file
1188
+ e; cliner {
1189
+ e 'We created a new file at `'+sfile(output_file)+'`.'
1190
+ e 'You can input the command "'+simp('mpl')+'" or "'+
1191
+ simp('play')+'" to play this new file.'
1192
+ set_main_file(output_file)
1193
+ }; e
1194
+ else
1195
+ e 'The file at `'+sfile(output_file)+'` does not exist.'
1196
+ end
1197
+ else
1198
+ e 'You seem to have specified only one file ('+sfile(file?)+').'
1199
+ e 'We need at least two files for the merge action though.'
1200
+ end
1201
+ end
1202
+
1203
+ # ========================================================================= #
1204
+ # === do_the_cutting
1205
+ #
1206
+ # This will cut our audio file.
1207
+ # ========================================================================= #
1208
+ def do_the_cutting(optional_input = nil)
1209
+ build_ffmpeg_command
1210
+ end; alias cut do_the_cutting # === cut (cut tag)
1211
+ alias start_cutting do_the_cutting # === start_cutting
1212
+
1213
+ # ========================================================================= #
1214
+ # === output_file?
1215
+ #
1216
+ # This refers to the file that will be created.
1217
+ # ========================================================================= #
1218
+ def output_file?
1219
+ @output_file
1220
+ end; alias output_files? output_file? # === output_files?
1221
+
1222
+ # ========================================================================= #
1223
+ # === chop_off_the_first_n_minutes
1224
+ #
1225
+ # This method can be used to chop away the first n minutes of an audio
1226
+ # track. This may be useful if you have some audio-recording of a
1227
+ # lecture, and you already know the beginning part, so you quickly
1228
+ # chop it away.
1229
+ #
1230
+ # Invocation examples:
1231
+ #
1232
+ # 7min
1233
+ # 13min
1234
+ #
1235
+ # ========================================================================= #
1236
+ def chop_off_the_first_n_minutes(
1237
+ n_minutes = 5
1238
+ )
1239
+ n_seconds = n_minutes.to_f * 60
1240
+ set_start_point(n_seconds)
1241
+ set_end_point(:to_the_end)
1242
+ do_cut_the_multimedia_file
1243
+ end
1244
+
1245
+ # ========================================================================= #
1246
+ # === calculate
1247
+ #
1248
+ # Calculcate how many seconds are here.
1249
+ # ========================================================================= #
1250
+ def calculate(
1251
+ n_seconds
1252
+ )
1253
+ n_minutes, n_seconds = n_seconds.to_s.split(':')
1254
+ return ((n_minutes.to_i * 60).to_i + n_seconds.to_i).to_s
1255
+ end
1256
+
1257
+ # ========================================================================= #
1258
+ # === delete_the_original_file
1259
+ #
1260
+ # This method will remove the original file.
1261
+ # ========================================================================= #
1262
+ def delete_the_original_file(
1263
+ i = work_on_which_file?
1264
+ )
1265
+ unless i
1266
+ opnn; no_file_exists
1267
+ return
1268
+ end
1269
+ _ = File.basename(i) if i
1270
+ if i and File.exist?(_)
1271
+ opne 'Now deleting the original file at '+sfile(_)+'.'
1272
+ remove_file(_)
1273
+ else
1274
+ opnn; no_file_exists_at(_)
1275
+ end
1276
+ end
1277
+
1278
+ # ========================================================================= #
1279
+ # === is_interactive?
1280
+ # ========================================================================= #
1281
+ def is_interactive?
1282
+ @usage_mode == :interactive
1283
+ end
1284
+
1285
+ # ========================================================================= #
1286
+ # === we_may_quit
1287
+ # ========================================================================= #
1288
+ def we_may_quit
1289
+ @may_we_exit = true
1290
+ end
1291
+
1292
+ # ========================================================================= #
1293
+ # === chop_off
1294
+ #
1295
+ # Use this method if you want to chop off some seconds from a song,
1296
+ # for instance, to get rid of the last 3 seconds of a song.
1297
+ #
1298
+ # The argument passed will be assumed to be the number of seconds that
1299
+ # you wish to chop off from an audio file - starting from the end.
1300
+ #
1301
+ # So, chop_off(3) simply means to chop off the last 3 seconds.
1302
+ #
1303
+ # Usage example:
1304
+ #
1305
+ # chop off 3 seconds
1306
+ # chop_off 3
1307
+ #
1308
+ # ========================================================================= #
1309
+ def chop_off(i = 1)
1310
+ if i.is_a? Array
1311
+ i << 1 if i.empty?
1312
+ i = i.join(' ')
1313
+ end
1314
+ i = i.to_s.strip.to_f # We need to strip the input here. And use a Float.
1315
+ # ======================================================================= #
1316
+ # Deduct the input from the end position. We either use the
1317
+ # duration, or the last entry.
1318
+ # ======================================================================= #
1319
+ if duration?
1320
+ if end_position? and end_position?.empty?
1321
+ the_end_position = duration?.to_f - i
1322
+ else # else it is not empty
1323
+ last_position = end_positions?.pop.to_f
1324
+ the_end_position = last_position - i
1325
+ end
1326
+ if no_start_point_was_defined_yet?
1327
+ set_start(0, :be_silent) # Only set a start point if we do not have defined one yet.
1328
+ end
1329
+ set_end(the_end_position, :be_silent)
1330
+ e "We will chop off the last #{simp(i.to_s)} seconds."
1331
+ notify_user_that_he_could_commit_now
1332
+ else
1333
+ e 'No duration was set. Can not chop off anything.'
1334
+ end
1335
+ end
1336
+
1337
+ # ========================================================================= #
1338
+ # === notify_user_that_he_could_commit_now
1339
+ # ========================================================================= #
1340
+ def notify_user_that_he_could_commit_now
1341
+ e 'You could now "'+sfancy('commit')+
1342
+ '" to cut the audio file.'
1343
+ end
1344
+
1345
+ # ========================================================================= #
1346
+ # === chop_into_segments_of_n_seconds_size
1347
+ #
1348
+ # Use this method if you wish to chop the input into different sizes,
1349
+ # based on seconds.
1350
+ #
1351
+ # Invocation example:
1352
+ #
1353
+ # chop 300
1354
+ #
1355
+ # ========================================================================= #
1356
+ def chop_into_segments_of_n_seconds_size(n_seconds = 60) # 60 seconds by default.
1357
+ n_seconds = n_seconds.first.to_f if n_seconds.is_a? Array
1358
+ e "Now chopping up into segments of `#{sfancy(n_seconds.to_s)}"\
1359
+ "` seconds duration."
1360
+ ::MultimediaParadise.chop_into_segments_of_n_seconds_size(
1361
+ main_file?, n_seconds
1362
+ )
1363
+ end
1364
+
1365
+ # ========================================================================= #
1366
+ # === left_chop_off
1367
+ #
1368
+ # This method will chop off to the left side of an audio file.
1369
+ # ========================================================================= #
1370
+ def left_chop_off(i)
1371
+ i = i.join(' ').to_s.strip if i.is_a? Array
1372
+ set_start(i)
1373
+ if no_end_point_was_defined_yet?
1374
+ set_end(duration?, :be_silent) # Only set a start point if we do not have defined one yet.
1375
+ end
1376
+ notify_user_that_he_could_commit_now
1377
+ end
1378
+
1379
+ # ========================================================================= #
1380
+ # === notify_the_user_that_interactive_mode_is_ready_now
1381
+ # ========================================================================= #
1382
+ def notify_the_user_that_interactive_mode_is_ready_now(
1383
+ this_file = File.basename(work_on_which_file?.to_s)
1384
+ )
1385
+ # ======================================================================= #
1386
+ # Build up the intro-string.
1387
+ # ======================================================================= #
1388
+ intro = rev+'We are in interactive mode'.dup
1389
+ if File.exist? this_file
1390
+ intro << ', for the file `'+sfile(this_file)+'`.'
1391
+ else
1392
+ intro << '. No file has yet been assigned to work on.'+N
1393
+ intro << 'Use "assign" to assign to a file to work with.'
1394
+ end
1395
+ e intro
1396
+ e
1397
+ e 'You can now start to assign start and end positions'
1398
+ e 'of your file in question. When you are '\
1399
+ 'done, input '+sfancy('run')
1400
+ e 'to start the cutting. (Remember: Start positions are '\
1401
+ 'like '+sfancy('s1')+', end'
1402
+ e 'positions are like '+sfancy('e40')+'.)'+N+N
1403
+ e 'You can also use some extra commands, like "'+
1404
+ simp(:length).to_s+'".'
1405
+ e 'Use "help" to display the help menu.'
1406
+ e N+simp('Hint:').to_s+' You can use '+simp('s11')+
1407
+ ' and '+simp('e22').to_s+' to denote a start time'
1408
+ e ' at position '+simp('11').to_s+' seconds and an end '\
1409
+ 'time at position '+simp('22').to_s+' seconds.'
1410
+ e
1411
+ e
1412
+ e 'Input your command next or type "help" for help.'
1413
+ end
1414
+
1415
+ # ========================================================================= #
1416
+ # === show_how_to_use_intersect
1417
+ #
1418
+ # This method will give the user some hints how to use the intersect
1419
+ # part. The intersect part allows us to cut out a middle segment
1420
+ # from a .mp3 file.
1421
+ # ========================================================================= #
1422
+ def show_how_to_use_intersect
1423
+ e 'intersect can be used to chop out middle-segments from an '\
1424
+ 'audio file.'
1425
+ e
1426
+ e 'The format should be something exactly like this:'
1427
+ e
1428
+ e simp(' intersect 29:23-29:45')
1429
+ e
1430
+ end
1431
+
1432
+ # ========================================================================= #
1433
+ # === enter_the_main_loop
1434
+ #
1435
+ # The main loop is only to be entered if we are in interactive mode.
1436
+ # The GUI in ruby-gtk3 will handle a loop on its own.
1437
+ # ========================================================================= #
1438
+ def enter_the_main_loop
1439
+ loop {
1440
+ display_the_prompt_in_use_to_the_user
1441
+ obtain_user_input
1442
+ append_the_user_input_onto_the_history
1443
+ interactive_menu # Feed the input in the interactive menu here.
1444
+ break if @may_we_exit
1445
+ }
1446
+ end
1447
+
1448
+ # ========================================================================= #
1449
+ # === set_interactive_mode_then_enter_interactive_mode
1450
+ # ========================================================================= #
1451
+ def set_interactive_mode_then_enter_interactive_mode
1452
+ @usage_mode = :interactive
1453
+ enter_interactive_mode
1454
+ end
1455
+
1456
+ # ========================================================================= #
1457
+ # === MultimediaParadise::CutMultimedia[]
1458
+ #
1459
+ # This class-method also allows some extra instructions such as to
1460
+ # limit the duration.
1461
+ #
1462
+ # Example:
1463
+ #
1464
+ # MultimediaParadise::CutMultimedia['*.mp3', '60 seconds']
1465
+ #
1466
+ # This will fetch all .mp3 files.
1467
+ # ========================================================================= #
1468
+ def self.[](
1469
+ i, optional_limitation_of_duration = nil
1470
+ )
1471
+ if i.is_a? String and i.include?('*')
1472
+ i = Dir[i] # This performs a glob, essentially.
1473
+ end
1474
+ if i.is_a? Array
1475
+ # ===================================================================== #
1476
+ # Work in batch-processing mode in this case.
1477
+ # ===================================================================== #
1478
+ if optional_limitation_of_duration and
1479
+ optional_limitation_of_duration.include?('seconds')
1480
+ i.each {|entry|
1481
+ _ = self.new(entry, :do_not_run_yet)
1482
+ _.set_start_at 0
1483
+ _.set_end_at(
1484
+ optional_limitation_of_duration.to_s.gsub(/seconds/,'').strip.to_f
1485
+ )
1486
+ _.cut
1487
+ }
1488
+ end
1489
+ else
1490
+ new(i, :run_interactive)
1491
+ end
1492
+ end
1493
+
1494
+ # ========================================================================= #
1495
+ # === split_audio_file_in_half
1496
+ #
1497
+ # This method will simply split the audio file in half.
1498
+ #
1499
+ # To invoke this method, try this command:
1500
+ #
1501
+ # split_audio_file_in_half
1502
+ #
1503
+ # ========================================================================= #
1504
+ def split_audio_file_in_half(
1505
+ i = main_file?
1506
+ )
1507
+ if File.exist? i
1508
+ e 'We will next split the audio file `'+sfile(i)+'` in '\
1509
+ 'half, thus, into two parts.'
1510
+ set_start 0
1511
+ set_end '50%'
1512
+ cut # Perform the first cut operation here.
1513
+ set_start '50%'
1514
+ set_end '100%'
1515
+ cut # Perform the second cut operation there.
1516
+ # delete_audio_file # Not sure if we should delete it.
1517
+ e 'The audio was split in two equal parts.'
1518
+ else
1519
+ e 'No file called `'+sfile(i)+'` exists.'
1520
+ end
1521
+ end
1522
+
1523
+ # ========================================================================= #
1524
+ # === start_the_graphical_user_interface
1525
+ # ========================================================================= #
1526
+ def start_the_graphical_user_interface
1527
+ require 'multimedia_paradise/gui/gtk3/cut_multimedia/cut_multimedia.rb'
1528
+ ::MultimediaParadise::GUI::Gtk::CutMultimedia.run
1529
+ end
1530
+
1531
+ # ========================================================================= #
1532
+ # === check_whether_ffmpeg_is_installed
1533
+ #
1534
+ # We have to check whether the user has ffmpeg installed. Because if
1535
+ # ffmpeg is unavailable, then cut_audio will not work.
1536
+ # ========================================================================= #
1537
+ def check_whether_ffmpeg_is_installed
1538
+ _ = ARRAY_LOCATIONS_TO_CHECK_FOR_FFMPEG
1539
+ is_ffmpeg_installed = false
1540
+ _.each {|path|
1541
+ is_ffmpeg_installed = true if File.exist? path+'ffmpeg'
1542
+ }
1543
+ unless is_ffmpeg_installed
1544
+ opnn { :no_trailing_colon }; e
1545
+ e
1546
+ e ' FFmpeg is not installed or could not be found. Please '\
1547
+ 'install it.'
1548
+ e
1549
+ e ' The class CutMultimedia, part of the MultimediaParadise namespace,'
1550
+ e ' currently requires that ffmpeg is installed.'
1551
+ e
1552
+ e ' The following paths were checked for the availability of ffmpeg:'
1553
+ e
1554
+ _.each {|this_path|
1555
+ e " #{sfancy(this_path)}"
1556
+ }
1557
+ # exit_properly
1558
+ end
1559
+ return is_ffmpeg_installed
1560
+ end
1561
+
1562
+ # ========================================================================= #
1563
+ # === build_ffmpeg_command
1564
+ #
1565
+ # This method will build the proper ffmpeg command.
1566
+ # ========================================================================= #
1567
+ def build_ffmpeg_command( # Assemble the FFMPEG main string here.
1568
+ this_file = main_file?,
1569
+ duration = duration?
1570
+ )
1571
+ ensure_that_there_is_at_least_one_end_position
1572
+ # ======================================================================= #
1573
+ # Next, we must ensure that the @array_all_end_positions is never nil.
1574
+ # ======================================================================= #
1575
+ ensure_that_array_cut_end_is_valid
1576
+ # ======================================================================= #
1577
+ # Merge it all into one Array.
1578
+ # ======================================================================= #
1579
+ merged_array = all_start_positions?.zip(all_end_positions?)
1580
+ # ======================================================================= #
1581
+ # Iterate over that Array next.
1582
+ # ======================================================================= #
1583
+ merged_array.each {|entry|
1584
+ the_start_position = entry.first # Grab the first entry.
1585
+ the_end_position = entry[1] # Grab the second entry.
1586
+ the_end_position = duration.to_f if the_end_position.to_f > duration.to_f
1587
+ # ===================================================================== #
1588
+ # the_end position should never be nil at this point.
1589
+ # ===================================================================== #
1590
+ @t.set_start_position = the_start_position
1591
+ @t.set_end_position = the_end_position
1592
+ e 'Now cutting multimedia-file '+sfancy('`'+this_file+'`')+
1593
+ ', starting at'
1594
+ e "position #{simp(the_start_position.to_s)} and ending at "\
1595
+ "position #{simp(the_end_position.to_s)}:"
1596
+ e
1597
+ # ===================================================================== #
1598
+ # Label our output file properly, by prepending the word "cutted_",
1599
+ # the start position and the end position.
1600
+ # ===================================================================== #
1601
+ output_file = 'cutted_'+the_start_position.to_s+
1602
+ '-'+the_end_position.to_s+'_seconds_'+
1603
+ File.basename(this_file)
1604
+ set_output_file(output_file)
1605
+ # ===================================================================== #
1606
+ # === Does the output file exist
1607
+ #
1608
+ # Check whether the output file exists or whether it does not.
1609
+ # ===================================================================== #
1610
+ if File.exist? output_file?.to_s
1611
+ e "File `#{sfile(output_file?)}` already exists."
1612
+ e 'We will remove it before continuing.'
1613
+ remove(output_file?)
1614
+ end
1615
+ # ===================================================================== #
1616
+ # Next, build up the ffmpeg command.
1617
+ # ===================================================================== #
1618
+ if this_file.include? ' '
1619
+ this_file = '"'+this_file+'"'
1620
+ end
1621
+ difference_in_seconds = the_end_position.to_f - the_start_position.to_f
1622
+ the_start_position = @t.convert_to_long_format(the_start_position)
1623
+ # ===================================================================== #
1624
+ # Ok, here we start the real ffmpeg command.
1625
+ # ===================================================================== #
1626
+ _ = 'ffmpeg -i '.dup
1627
+ _ << this_file+' '
1628
+ _ << '-acodec copy ' # This will copy. See Stackoverflow here: http://stackoverflow.com/a/44032/722915
1629
+ if is_video_file?(this_file)
1630
+ _ << '-vcodec copy '
1631
+ end
1632
+ _ << '-ss '+
1633
+ the_start_position
1634
+ _ << ' -t '+
1635
+ @t.convert_to_long_format(difference_in_seconds)+
1636
+ ' '+output_file?.to_s # Relies on ffmpeg.
1637
+ # ===================================================================== #
1638
+ # Next, determine whether we will log into a text file or whether
1639
+ # we will not.
1640
+ # ===================================================================== #
1641
+ if create_log_file?
1642
+ output_file = output_file.dup if output_file.frozen?
1643
+ output_file << '.md'
1644
+ log_cut_action(@t.start?, @t.end?, _, output_file)
1645
+ end
1646
+ cliner
1647
+ e
1648
+ e steelblue(_) # Feedback the command we will use to the user here.
1649
+ e
1650
+ cliner
1651
+ e # And a newline too.
1652
+ system _
1653
+ }
1654
+ end
1655
+
1656
+ # ========================================================================= #
1657
+ # === initialize_twentyfour_hours_notation_object
1658
+ # ========================================================================= #
1659
+ def initialize_twentyfour_hours_notation_object
1660
+ begin
1661
+ require 'roebe/classes/twentyfour_hours_notation.rb'
1662
+ rescue LoadError; end
1663
+ if Object.const_defined?(:Roebe) and Roebe.const_defined?(:TwentyfourHoursNotation)
1664
+ @t = Roebe::TwentyfourHoursNotation.new # bl $RUBY_TIME/twentyfour_hours_notation.rb
1665
+ else
1666
+ e 'The twentyfour_hours_notation class, part of the roebe gem, '\
1667
+ 'appears to be unavailable.'
1668
+ e
1669
+ e 'Please consider installing it, such as via:'
1670
+ e
1671
+ e ' gem install roebe'
1672
+ e
1673
+ end
1674
+ end
1675
+
1676
+ # ========================================================================= #
1677
+ # === set_work_on_this_file
1678
+ # ========================================================================= #
1679
+ def set_work_on_this_file(
1680
+ i = :default,
1681
+ also_keep_track_of_which_file_we_will_use = true
1682
+ )
1683
+ i = i.first if i.is_a? Array # For now we use only the first entry of an Array.
1684
+ case also_keep_track_of_which_file_we_will_use
1685
+ when :do_not_keep_track
1686
+ also_keep_track_of_which_file_we_will_use = false
1687
+ end
1688
+ case i
1689
+ # ======================================================================= #
1690
+ # === --help
1691
+ # ======================================================================= #
1692
+ when /-?-?help/i
1693
+ show_help :then_exit
1694
+ # ======================================================================= #
1695
+ # === :default
1696
+ #
1697
+ # This entry point will cover :default as well as nil-values.
1698
+ # ======================================================================= #
1699
+ when :default,
1700
+ nil
1701
+ i = DEFAULT_INPUT_FILE
1702
+ end
1703
+ # ======================================================================= #
1704
+ # === Make use of the absolute path, if possible
1705
+ # ======================================================================= #
1706
+ unless i.include? '/'
1707
+ i = File.absolute_path(i)
1708
+ end
1709
+ if i and File.file?(i)
1710
+ @work_on_this_file = i
1711
+ # ===================================================================== #
1712
+ # Always set the duration upon assigning a new file to work with.
1713
+ # ===================================================================== #
1714
+ determine_the_duration(i) if File.exist? i
1715
+ # ===================================================================== #
1716
+ # And also always determine the proper output file.
1717
+ # ===================================================================== #
1718
+ determine_the_output_file
1719
+ if also_keep_track_of_which_file_we_will_use and
1720
+ File.exist?(i)
1721
+ # =================================================================== #
1722
+ # We will also keep track of this file in the local filesystem,
1723
+ # if the output directory has been set.
1724
+ # =================================================================== #
1725
+ _ = ::MultimediaParadise.output_directory?
1726
+ unless File.directory? _
1727
+ mkdir(_)
1728
+ end
1729
+ if _ and File.directory?(_)
1730
+ into = FILE_LAST_USED
1731
+ if is_on_roebe?
1732
+ opne 'Keeping track of the main file in'
1733
+ opne '`'+sfile(into)+'`.'
1734
+ end
1735
+ # =================================================================== #
1736
+ # We must rescue the YAML.dump operation, as it may fail otherwise
1737
+ # sometimes, e. g. via:
1738
+ #
1739
+ # invalid byte sequence in US-ASCII (ArgumentError)
1740
+ #
1741
+ # =================================================================== #
1742
+ begin
1743
+ what = YAML.dump(@work_on_this_file)
1744
+ write_what_into(
1745
+ what, into
1746
+ )
1747
+ rescue ArgumentError => error
1748
+ pp error
1749
+ pp error.class
1750
+ end
1751
+ end
1752
+ else
1753
+ opne 'File '+sfile(i)+' does not exist.'
1754
+ end
1755
+ end
1756
+ end; alias set_main_file set_work_on_this_file # === set_main_file
1757
+ alias set_file set_work_on_this_file # === set_file
1758
+ alias assign_file set_work_on_this_file # === assign_file
1759
+ alias assign set_work_on_this_file # === assign (assign tag)
1760
+ alias assign_this_file set_work_on_this_file # === assign_this_file
1761
+
1762
+ # ========================================================================= #
1763
+ # === absolute_path_of_the_output_file?
1764
+ # ========================================================================= #
1765
+ def absolute_path_of_the_output_file?(
1766
+ output_file = output_file?
1767
+ )
1768
+ File.absolute_path(output_file) if output_file
1769
+ end
1770
+
1771
+ # ========================================================================= #
1772
+ # === ensure_that_there_is_at_least_one_end_position
1773
+ #
1774
+ # This method will make sure that the end-array has at least one
1775
+ # entry.
1776
+ # ========================================================================= #
1777
+ def ensure_that_there_is_at_least_one_end_position
1778
+ if end_positions?.empty?
1779
+ e 'Note that there is no end position designated yet for '\
1780
+ 'this file. We will thus set'
1781
+ e 'one to the end position of the audio file.'
1782
+ set_end :end_of_the_file
1783
+ end
1784
+ end
1785
+
1786
+ # ========================================================================= #
1787
+ # === define_start_point (set_start tag)
1788
+ #
1789
+ # This method will define a start position, at which we will start to
1790
+ # cut an audio file.
1791
+ #
1792
+ # set_start is an alias to this method.
1793
+ # ========================================================================= #
1794
+ def define_start_point(
1795
+ i, be_verbose = true
1796
+ )
1797
+ case be_verbose
1798
+ when :be_silent
1799
+ be_verbose = false
1800
+ end
1801
+ i = i.first if i.is_a? Array
1802
+ i = i.to_s.strip
1803
+ i[0,5] = '' if i.start_with? 'start'
1804
+ i[0,1] = '' if i.start_with? 's'
1805
+ i = sanitize(i)
1806
+ if i.empty?
1807
+ e "Won't append empty start points."
1808
+ elsif i.include? '%' # User requested percentage-based manipulation here.
1809
+ i = ((duration? * (i.delete('%').to_i)) / 100)
1810
+ define_start_point(i) # Call itself again.
1811
+ else
1812
+ # ===================================================================== #
1813
+ # Simply append to our main Array.
1814
+ # ===================================================================== #
1815
+ @array_all_start_positions << i.to_f # Store as float.
1816
+ if be_verbose
1817
+ e "#{rev}Setting a start point at: #{simp(i)}"
1818
+ feedback_all_start_points
1819
+ end
1820
+ end
1821
+ end; alias set_start define_start_point # === set_start
1822
+ alias set_start_at define_start_point # === set_start_at
1823
+ alias set_start_point define_start_point # === set_start_point
1824
+ alias determine_start_position define_start_point # === determine_start_position
1825
+ alias set_start_position define_start_point # === set_start_position
1826
+
1827
+ # ========================================================================= #
1828
+ # === define_end_point
1829
+ #
1830
+ # This method can be used to set the end point of an audio file, as to
1831
+ # where we will stop to cut. For example, an end point of "5" is assumed
1832
+ # to mean a cut point at 5 seconds.
1833
+ #
1834
+ # set_end() is an alias to this method.
1835
+ # ========================================================================= #
1836
+ def define_end_point(
1837
+ i, be_verbose = true
1838
+ )
1839
+ be_verbose = false if be_verbose == :be_silent
1840
+ i = i.first if i.is_a? Array
1841
+ if i.is_a? Symbol
1842
+ case i
1843
+ when :end_of_the_file,
1844
+ :to_the_end
1845
+ i = length_of_audio_file?
1846
+ end
1847
+ end
1848
+ i = i.to_s.strip # We require a String past this point here.
1849
+ i[0,3] = '' if i.start_with? 'end'
1850
+ i[0,1] = '' if i.start_with? 'e'
1851
+ i = sanitize(i)
1852
+ if i.empty?
1853
+ e "Won't append empty end points."
1854
+ elsif i.include? '%' # User requested percentage-based manipulation.
1855
+ i = ((duration? * (i.delete('%').to_i)) / 100)
1856
+ define_end_point(i) # Recursive call again.
1857
+ else
1858
+ # ===================================================================== #
1859
+ # Convert into seconds if it includes a ':'.
1860
+ # ===================================================================== #
1861
+ if i.include?(':') and Object.const_defined?(:HoursToSeconds)
1862
+ i = HoursToSeconds[i, :be_quiet]
1863
+ end
1864
+ # ===================================================================== #
1865
+ # Until 19.04.2019 we had the following code to detect a logic error,
1866
+ # but it was then realized that not all numbers constitute a logic
1867
+ # error, so this was removed again.
1868
+ #
1869
+ # if i.to_f < starting_position?.to_f
1870
+ # e 'This input ('+sfancy(i.to_s)+') must be invalid because '\
1871
+ # 'it is'
1872
+ # e 'smaller than the starting position.'
1873
+ # return
1874
+ # end
1875
+ # ===================================================================== #
1876
+ # ===================================================================== #
1877
+ # === Check for too long size given
1878
+ #
1879
+ # The following code has been added at 31.08.2019. If i is larger
1880
+ # than the length of the audio file then we will notify the user
1881
+ # about it, then set it to the maximum length instead.
1882
+ #
1883
+ # This, however had, only makes sense if the length is larger
1884
+ # than 0, hence the double-check below.
1885
+ # ===================================================================== #
1886
+ length_of_audio_file = length_of_audio_file?.to_f
1887
+ if (length_of_audio_file.to_f > 0) and (i.to_f > length_of_audio_file.to_f)
1888
+ e "Note that #{sfancy(i)} is larger than the length of the audio file."
1889
+ e "This is of little practical use, so the input here been reset"
1890
+ e "to the maximum length instead (#{length_of_audio_file} seconds)."
1891
+ i = length_of_audio_file.to_f
1892
+ end
1893
+ end_positions? << i
1894
+ if be_verbose
1895
+ e "Setting an end point at: #{simp(i)}"
1896
+ feedback_all_end_points
1897
+ end
1898
+ end
1899
+ end; alias set_end define_end_point # === set_end
1900
+ alias set_end_at define_end_point # === set_end_at
1901
+ alias set_end_point define_end_point # === set_end_point
1902
+ alias set_end_position define_end_point # === set_end_position
1903
+
1904
+ # ========================================================================= #
1905
+ # === determine_the_output_file
1906
+ #
1907
+ # This method will determine the output file based on the input file.
1908
+ # ========================================================================= #
1909
+ def determine_the_output_file(
1910
+ i = input_file?
1911
+ )
1912
+ i = File.basename(i).dup
1913
+ i.prepend('OUTPUT_FILE_') unless i.start_with?('OUTPUT_FILE_')
1914
+ i = File.absolute_path(i)
1915
+ set_output_file(i)
1916
+ end
1917
+
1918
+ # ========================================================================= #
1919
+ # === work_on_this_file? (file tag)
1920
+ # ========================================================================= #
1921
+ def work_on_this_file?
1922
+ @work_on_this_file
1923
+ end; alias main_file? work_on_this_file? # === main_file?
1924
+ alias work_on_which_file? work_on_this_file? # === work_on_which_file?
1925
+ alias file? work_on_this_file? # === file?
1926
+ alias input_file? work_on_this_file? # === input_file?
1927
+
1928
+ # ========================================================================= #
1929
+ # === exit_properly
1930
+ # ========================================================================= #
1931
+ def exit_properly
1932
+ do_general_exit_actions
1933
+ exit # unless is_interactive?
1934
+ end
1935
+
1936
+ # ========================================================================= #
1937
+ # === check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file
1938
+ # ========================================================================= #
1939
+ def check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file(
1940
+ i = commandline_arguments?
1941
+ )
1942
+ if i.is_a? Array
1943
+ i.each {|entry| check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file(entry) }
1944
+ else
1945
+ if i and File.exist?(i)
1946
+ # =================================================================== #
1947
+ # Designate this as the new file to work with, on startup of
1948
+ # this class.
1949
+ # =================================================================== #
1950
+ set_work_on_this_file(i)
1951
+ end
1952
+ end
1953
+ end
1954
+
1955
+ # ========================================================================= #
1956
+ # === run_in_interactive_mode
1957
+ # ========================================================================= #
1958
+ def run_in_interactive_mode
1959
+ try_to_rename_kde_konsole_tab(work_on_which_file?)
1960
+ notify_the_user_that_interactive_mode_is_ready_now
1961
+ enter_the_main_loop
1962
+ end; alias enter_interactive_mode run_in_interactive_mode # === enter_interactive_mode
1963
+ alias run_interactively run_in_interactive_mode # === run_interactively
1964
+
1965
+ # ========================================================================= #
1966
+ # === run (run tag)
1967
+ # ========================================================================= #
1968
+ def run
1969
+ check_whether_ffmpeg_is_installed # After this point we know that ffmpeg is installed.
1970
+ if File.exist? work_on_which_file?.to_s
1971
+ feedback_duration
1972
+ end
1973
+ # ======================================================================= #
1974
+ # Check against the usage mode.
1975
+ # ======================================================================= #
1976
+ case @usage_mode
1977
+ when :interactive,
1978
+ :default
1979
+ run_in_interactive_mode
1980
+ exit 0 # Signal normal exit.
1981
+ when :gui
1982
+ # Do nothing for now in this event.
1983
+ end
1984
+ end
1985
+
1986
+ # ========================================================================= #
1987
+ # === feedback_all_start_points
1988
+ # ========================================================================= #
1989
+ def feedback_all_start_points(
1990
+ i = start_positions?
1991
+ )
1992
+ e "Feedbacking all #{emphasis('start-points')} next."
1993
+ pp i
1994
+ end
1995
+
1996
+ # ========================================================================= #
1997
+ # === do_cut_the_multimedia_file
1998
+ # ========================================================================= #
1999
+ def do_cut_the_multimedia_file
2000
+ start_cutting
2001
+ report_that_we_are_finished_now
2002
+ return absolute_path_of_the_output_file?
2003
+ end; alias do_cut do_cut_the_multimedia_file # === do_cut
2004
+
2005
+ end
2006
+
2007
+ # =========================================================================== #
2008
+ # Add two aliases next.
2009
+ # =========================================================================== #
2010
+ CutAudio = CutMultimedia
2011
+ CutVideo = CutMultimedia
2012
+
2013
+ end
2014
+
2015
+ if __FILE__ == $PROGRAM_NAME
2016
+ MultimediaParadise::CutMultimedia.new(ARGV)
2017
+ end # cutmultimedia