content-editing-movie-player 0.38.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitmodules +3 -0
- data/.rvmrc +1 -0
- data/LICENSE.TXT +20 -0
- data/README.TXT +225 -0
- data/Rakefile +206 -0
- data/TODO +740 -0
- data/VERSION +1 -0
- data/_DO_NOT_RUN_IT_FROM_HERE_DOWNLOAD_THE_RELEASE_ZIP_FROM_SOURCEFORGE_INSTEAD +0 -0
- data/bin/sensible-cinema +60 -0
- data/bin/sensible-cinema-cli +161 -0
- data/business_ideas.txt +21 -0
- data/change_log_with_feature_list.txt +952 -0
- data/documentation/DOCUMENTATION_README.TXT +44 -0
- data/documentation/how_to_get_files_from_dvd.txt +30 -0
- data/documentation/is_it_legal_to_copy_dvds.txt +97 -0
- data/documentation/troubleshooting.txt +30 -0
- data/documentation/upconversion.txt +4 -0
- data/experimental_online_player_ocr_readme.txt +45 -0
- data/go +1 -0
- data/go.bat +2 -0
- data/go.sh +1 -0
- data/go_ocr_tracker.bat +1 -0
- data/goc +1 -0
- data/goc.bat +1 -0
- data/goc.sh +1 -0
- data/gpl-2.0.txt +339 -0
- data/gplv3.txt +219 -0
- data/history_and_related_works_list.txt +108 -0
- data/inventionzy_files/cone.png +0 -0
- data/inventionzy_files/md5s.txt +53 -0
- data/inventionzy_files/play_with_inserted_scene.bat +8 -0
- data/inventionzy_files/play_with_overlay.bat +24 -0
- data/inventionzy_files/transcript_mute_vlc.txt +117 -0
- data/legal_draft +23 -0
- data/lib/add_any_bundled_gems_to_load_path.rb +32 -0
- data/lib/auto_window_finder.rb +41 -0
- data/lib/blanker.rb +104 -0
- data/lib/check_installed_mac.rb +34 -0
- data/lib/convert_thirty_fps.rb +20 -0
- data/lib/edl_parser.rb +387 -0
- data/lib/eight_three.rb +28 -0
- data/lib/extract/dumpstream.bat +1 -0
- data/lib/extract/get_init.bat +3 -0
- data/lib/extract/pause_early.rb +13 -0
- data/lib/fake_blanker.rb +35 -0
- data/lib/frame_accurate.rb +3 -0
- data/lib/gui/base.rb +748 -0
- data/lib/gui/create-file.rb +24 -0
- data/lib/gui/create.rb +581 -0
- data/lib/gui/dependencies.rb +219 -0
- data/lib/gui/normal.rb +123 -0
- data/lib/gui/upconvert.rb +284 -0
- data/lib/keyboard_input.rb +60 -0
- data/lib/media_info_parser.rb +27 -0
- data/lib/mouse_forever.rb +19 -0
- data/lib/movie_hasher.rb +27 -0
- data/lib/mplayer_edl.rb +42 -0
- data/lib/muter.rb +87 -0
- data/lib/ocr.rb +125 -0
- data/lib/ocr_seed/netflix_b9.bmp +0 -0
- data/lib/overlayer.rb +373 -0
- data/lib/screen_tracker.rb +269 -0
- data/lib/subtitle_profanity_finder.rb +294 -0
- data/lib/vlc_programmer.rb +112 -0
- data/lib/zoom_player_max_edl.rb +50 -0
- data/never_do +40 -0
- data/notes_for_potential_developers.txt +46 -0
- data/preamble +17 -0
- data/roadmap_possibilities +12 -0
- data/spec/arse.srt +41 -0
- data/spec/auto_window_finder.spec.rb +65 -0
- data/spec/bad_beginning.srt +3778 -0
- data/spec/blanker.spec.rb +60 -0
- data/spec/common.rb +81 -0
- data/spec/convert_image.rb +25 -0
- data/spec/deity_end.srt +11 -0
- data/spec/dragon.srt +34 -0
- data/spec/edl_parser.spec.rb +270 -0
- data/spec/frame_accurate.spec.rb +71 -0
- data/spec/keyboard_input.spec.rb +73 -0
- data/spec/media_info_parser.spec.rb +29 -0
- data/spec/mplayer_edl.spec.rb +100 -0
- data/spec/muter.spec.rb +50 -0
- data/spec/notes +4996 -0
- data/spec/ocr.spec.rb +119 -0
- data/spec/overlayer.spec.rb +440 -0
- data/spec/screen_tracker.spec.rb +318 -0
- data/spec/sensible_cinema_gui.spec.rb +452 -0
- data/spec/subtitle_profanity_finder.spec.rb +224 -0
- data/spec/test_yaml.yml +4 -0
- data/spec/tsmuxer.output +33 -0
- data/spec/vlc_programmer.spec.rb +124 -0
- data/spec/youtube_edl.spec.rb +28 -0
- data/spec/zoom_player_max_edl.spec.rb +29 -0
- data/template_bats/README_DISTRO.TXT +8 -0
- data/template_bats/RUN SENSIBLE CINEMA CLICK HERE WINDOWS.bat +25 -0
- data/template_bats/_DO_NOT_RUN_IT_FROM_HERE_DOWNLOAD_THE_RELEASE_ZIP_FROM_SOURCEFORGE_INSTEAD +0 -0
- data/template_bats/mac/RUN SENSIBLE CINEMA CLICK HERE.command +5 -0
- data/template_bats/mac/advanced--create or edit sensible cinema edit list files.command +3 -0
- data/template_bats/mac/advanced--run-upconverting-video-player.command +3 -0
- data/template_bats/pc/advanced--create or edit sensible cinema edit list files.bat +2 -0
- data/template_bats/pc/advanced--run-upconverting-video-player.bat +2 -0
- data/todo.build_library.txt +11 -0
- data/todo.inventionzy.txt +162 -0
- data/todo.open_edl_list_org.txt +169 -0
- data/todo.propaganda +107 -0
- data/todo.subtitle +17 -0
- data/todo.upconvert +53 -0
- data/upconvert.bat +1 -0
- data/upconvert_from_screen/go_upscaling.bat +12 -0
- data/upconvert_from_screen/go_upscaling_works +0 -0
- data/upconvert_from_screen/old/latest2/combine_video.avs +23 -0
- data/upconvert_from_screen/old/latest2/go_no_upscaling.bat +1 -0
- data/upconvert_from_screen/old/latest2/go_upscaling.bat +12 -0
- data/upconvert_from_screen/old/latest2/push2.GRF +0 -0
- data/upconvert_from_screen/old/latest2/push3.grf +0 -0
- data/upconvert_from_screen/old/latest2/setup_capture_coords.rb +27 -0
- data/upconvert_from_screen/old/latest2/setup_directshow_filter_params.rb +29 -0
- data/upconvert_from_screen/old/latest2/upconvert_from_screen_me2.avs +19 -0
- data/upconvert_from_screen/old/latest_now_possibly_oudated/push2.GRF +0 -0
- data/upconvert_from_screen/old/latest_now_possibly_oudated/upconvert_from_screen_me2.avs +18 -0
- data/upconvert_from_screen/old/position_window.png +0 -0
- data/upconvert_from_screen/old/push_source_desktop.GRF +0 -0
- data/upconvert_from_screen/old/record_screen/record.bat +2 -0
- data/upconvert_from_screen/old/upconvert_from_screen.avs +21 -0
- data/upconvert_from_screen/old/upconvert_from_screen_me.avs +21 -0
- data/upconvert_from_screen/old/upconvert_from_screen_me2.avs +3 -0
- data/upconvert_from_screen/old/upconvert_from_screen_me_push_source.avs +3 -0
- data/upconvert_from_screen/old/uscreen.GRF +0 -0
- data/upconvert_from_screen/old/uscreen_me.GRF +0 -0
- data/upconvert_from_screen/push3.grf +0 -0
- data/upconvert_from_screen/upconvert_from_screen_me2.avs +19 -0
- data/vendor/movie-content-editor-read-only/.metadata/.lock +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.mylyn/.tasks.xml.zip +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.mylyn/repositories.xml.zip +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.mylyn/tasks.xml.zip +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version +1 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version +1 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/2.tree +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs +3 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs +14 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs +3 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs +5 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs +3 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml +2 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml +2 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml +10 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml +11 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml +4 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml +10 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml +232 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml +4 -0
- data/vendor/movie-content-editor-read-only/.metadata/version.ini +1 -0
- data/vendor/movie-content-editor-read-only/.project +17 -0
- data/vendor/movie-content-editor-read-only/.pydevproject +11 -0
- data/vendor/movie-content-editor-read-only/.settings/org.eclipse.core.resources.prefs +6 -0
- data/vendor/movie-content-editor-read-only/SubIt.py +171 -0
- data/vendor/movie-content-editor-read-only/VLCMacVideo.py +257 -0
- data/vendor/movie-content-editor-read-only/VideoMac.ui +102 -0
- data/vendor/movie-content-editor-read-only/badwords.txt +4 -0
- data/vendor/movie-content-editor-read-only/blank.srt +4 -0
- data/vendor/movie-content-editor-read-only/edit.py +197 -0
- data/vendor/movie-content-editor-read-only/mergeCommands.py +73 -0
- data/vendor/movie-content-editor-read-only/mute.txt +5 -0
- data/vendor/movie-content-editor-read-only/panda.srt +4235 -0
- data/vendor/movie-content-editor-read-only/panda_custom.txt +3 -0
- data/vendor/movie-content-editor-read-only/panda_edit.srt +4235 -0
- data/vendor/movie-content-editor-read-only/subtitle.py +90 -0
- data/vendor/movie-content-editor-read-only/vlc.py +5579 -0
- data/vendor/movie-content-editor-read-only/vlcwidget.py +154 -0
- data/vendor/mplayer_patches/how_to_doze.bat +6 -0
- data/vendor/mplayer_patches/port_dir/PortIndex.quick +2 -0
- data/vendor/mplayer_patches/port_dir/how_to +20 -0
- data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/Portfile +285 -0
- data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/files/configure.x11.patch +20 -0
- data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/files/llvm-gcc-workaround.patch +11 -0
- data/vendor/mplayer_patches/port_dir/multimedia/rdp-projects/Portfile +43 -0
- data/vendor/mplayer_patches/port_dir_is_for_mac +0 -0
- data/www/content_editor.html +92 -0
- data/www/index.html +47 -0
- data/www/upconverting_movie_player.html +62 -0
- data/www/video reel.jpg +0 -0
- data/www/youtube_edl/.htaccess +44 -0
- data/www/youtube_edl/control_youtube.rhtml +141 -0
- data/www/youtube_edl/dispatch.fcgi +25 -0
- data/www/youtube_edl/render_edited.rb +25 -0
- data/www/youtube_edl/server_this_dir.rb +6 -0
- data/www/youtube_edl/todo +23 -0
- data/www/zoomplayer_max.png +0 -0
- data/zamples/edit_decision_lists/dvds/Harry Potter 2 chamber of secrets.txt +22 -0
- data/zamples/edit_decision_lists/dvds/aa_example_delete_list_that_has_no_cuts_in_it.txt +10 -0
- data/zamples/edit_decision_lists/dvds/aladdin.txt +30 -0
- data/zamples/edit_decision_lists/dvds/bambi.txt +17 -0
- data/zamples/edit_decision_lists/dvds/big_buck_bunny_dvd.txt +23 -0
- data/zamples/edit_decision_lists/dvds/bob the builder pets in a pickle.txt +10 -0
- data/zamples/edit_decision_lists/dvds/bobs_big_plan.txt +10 -0
- data/zamples/edit_decision_lists/dvds/cars_2.txt +26 -0
- data/zamples/edit_decision_lists/dvds/cars_disney.txt +40 -0
- data/zamples/edit_decision_lists/dvds/condor_man_widescreen.txt +22 -0
- data/zamples/edit_decision_lists/dvds/cool runnings.txt +53 -0
- data/zamples/edit_decision_lists/dvds/court_jester.txt +24 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/amazing_grace.txt +49 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/father_goose.txt +41 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/harry_potter_and_the_goblet_of_fire.txt +45 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/hugo.txt +31 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/making_marriage_work.txt +15 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/national_treasure.txt +26 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/percy_jackson_lightening_thief.txt +40 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/percy_jackson_lightening_thief_mute_scary.txt +23 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/prince_of_egypt.txt +28 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/puss_in_boots.txt +33 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/ratatouille.txt +35 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/rio.txt +24 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/test_delete_list_for_experimenting_with.txt +10 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/the_explorers.txt +49 -0
- data/zamples/edit_decision_lists/dvds/finding_neverland.txt +32 -0
- data/zamples/edit_decision_lists/dvds/flight_of_the_navigator.txt +40 -0
- data/zamples/edit_decision_lists/dvds/happiest baby on the block.txt +9 -0
- data/zamples/edit_decision_lists/dvds/harry_potter_3_prisoner_of_azkaban.txt +37 -0
- data/zamples/edit_decision_lists/dvds/hitchhiker's_guide_to_the_galaxy.txt +32 -0
- data/zamples/edit_decision_lists/dvds/how_to_train_your_dragon.txt +25 -0
- data/zamples/edit_decision_lists/dvds/if_a_man_answers.txt +43 -0
- data/zamples/edit_decision_lists/dvds/innerspace.txt +77 -0
- data/zamples/edit_decision_lists/dvds/iq.txt +32 -0
- data/zamples/edit_decision_lists/dvds/king_of_kings.txt +28 -0
- data/zamples/edit_decision_lists/dvds/kung_fu_panda_1.txt +17 -0
- data/zamples/edit_decision_lists/dvds/legend_of_the_guardians_the_owls_of_gahoole.txt +18 -0
- data/zamples/edit_decision_lists/dvds/monsters_vs_aliens.txt +41 -0
- data/zamples/edit_decision_lists/dvds/muppet_treasure_island.txt +21 -0
- data/zamples/edit_decision_lists/dvds/nanny_mcphee.txt +31 -0
- data/zamples/edit_decision_lists/dvds/narnia_voyage_of_the_dawn_treader.txt +16 -0
- data/zamples/edit_decision_lists/dvds/pack_jackson_wedding_2007-03-03.txt +31 -0
- data/zamples/edit_decision_lists/dvds/peter_pan.txt +29 -0
- data/zamples/edit_decision_lists/dvds/remember_the_titans.txt +35 -0
- data/zamples/edit_decision_lists/dvds/sintel_open_source_blender_ntsc_dvd.txt +22 -0
- data/zamples/edit_decision_lists/dvds/snow_white_and_the_7_dwarfs_1937.txt +19 -0
- data/zamples/edit_decision_lists/dvds/speed_racer.txt +47 -0
- data/zamples/edit_decision_lists/dvds/tangled.txt +21 -0
- data/zamples/edit_decision_lists/dvds/tron_legacy.txt +29 -0
- data/zamples/edit_decision_lists/dvds/turn_around_alma_younger.txt +17 -0
- data/zamples/edit_decision_lists/files/conference_music_video.txt +10 -0
- data/zamples/edit_decision_lists/netflix_instant/avatar-last-air-bender-movie.txt +13 -0
- data/zamples/edit_decision_lists/netflix_instant/avatar-last-airbender-series.txt +1 -0
- data/zamples/edit_decision_lists/netflix_instant/greatest_story_ever_told_netflix.txt +10 -0
- data/zamples/edit_decision_lists/netflix_instant/wrinkle-in-time.txt +23 -0
- data/zamples/edit_decision_lists/notes_on_movies_without_edls_yet/tron.txt +10 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/White Christmas.txt +15 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/all_dogs_go_to_heaven.txt +9 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/cars_disney.txt +24 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/happy_feet.txt +12 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/labyrinth.txt +17 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/star_trek_generations_hulu.txt +8 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/example_edit_decision_list.txt +14 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/youtube/gummy_bear_song_youtube.txt +9 -0
- data/zamples/edit_decision_lists/youtube/demo_mutes.txt +12 -0
- data/zamples/edit_decision_lists/youtube/nuki_song_youtube.txt +14 -0
- data/zamples/edit_decision_lists/youtube/nuki_song_youtube_pointer.txt +3 -0
- data/zamples/players/how_to_create_more_players.txt +24 -0
- data/zamples/players/hulu/total_length_over_an_hour.txt +25 -0
- data/zamples/players/netflix/netflix_firefox_non_maximized.txt +25 -0
- data/zamples/players/vlc/full_screened_total_length_over_an_hour.txt +27 -0
- data/zamples/players/vlc/windowed_total_length_over_an_hour.txt +26 -0
- data/zamples/players/vlc/windowed_total_length_under_an_hour.txt +22 -0
- data/zamples/players/youtube/full_screened_1024x768.txt +20 -0
- data/zamples/players/youtube/full_screened_1152x864.txt +20 -0
- data/zamples/players/youtube/full_screened_1680x1050.txt +20 -0
- data/zamples/players/youtube/normal_in_youtube.com.chrome.txt +23 -0
- data/zamples/players/youtube/note_these_assume_less_than_10_minutes_length.txt +2 -0
- metadata +483 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2010, Roger Pack
|
3
|
+
This file is part of Sensible Cinema.
|
4
|
+
|
5
|
+
Sensible Cinema is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
Sensible Cinema is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
require 'Win32API'
|
19
|
+
|
20
|
+
# does the jruby check inline
|
21
|
+
|
22
|
+
class KeyboardInput
|
23
|
+
|
24
|
+
def initialize fella
|
25
|
+
@fella = fella
|
26
|
+
end
|
27
|
+
|
28
|
+
def start_thread
|
29
|
+
Thread.new { loop {
|
30
|
+
print get_line_printout
|
31
|
+
sleep 0.1
|
32
|
+
} }
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_line_printout
|
36
|
+
status = @fella.status
|
37
|
+
# some scary hard coded values here...LODO curses?
|
38
|
+
" " * 20 + "\b"*150 + status
|
39
|
+
end
|
40
|
+
|
41
|
+
def getch
|
42
|
+
@getch ||= Win32API.new('crtdll', '_getch', [], 'L')
|
43
|
+
@getch.call
|
44
|
+
end
|
45
|
+
|
46
|
+
def handle_keystrokes_forever
|
47
|
+
raise 'only jruby supported, as it looks just too messy in normal ruby' unless OS.java?
|
48
|
+
while(ch = getch)
|
49
|
+
exit if ch == 3 # ctrl+c
|
50
|
+
# lodo handle arrow keys, too, which is a bit more complicated...
|
51
|
+
handle_keystroke ch
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def handle_keystroke ch
|
56
|
+
string = "" << ch
|
57
|
+
@fella.keyboard_input(string)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module MediaInfoParser
|
2
|
+
def self.parse_with_convert_command media_info, filename
|
3
|
+
video = audio = nil
|
4
|
+
media_info.split("Track ID").each{ |section|
|
5
|
+
section =~ /:(\W+)(\d+)/
|
6
|
+
id = $2
|
7
|
+
section =~ /Stream ID: (\S+)/ # like V_MPEG-2
|
8
|
+
stream_type = $1
|
9
|
+
if stream_type
|
10
|
+
raise unless id
|
11
|
+
if section =~ /Frame rate/ && !video
|
12
|
+
section =~ /Frame rate: ([\d\.]+)/
|
13
|
+
fps = $1
|
14
|
+
raise unless fps
|
15
|
+
raise unless section =~ /lang: eng/ # expect...
|
16
|
+
video = "#{stream_type}, \"#{filename}\", fps=#{fps}, track=#{id}, lang=eng"
|
17
|
+
elsif section =~ /Channels:/ && !audio
|
18
|
+
raise unless section =~ /lang: eng/ # hope english audio track comes first...
|
19
|
+
# A_AC3, "G:\Video\Sintel_NTSC\title01.mkv", track=2, lang=eng
|
20
|
+
audio = "#{stream_type}, \"#{filename}\", track=#{id}, lang=eng"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
}
|
24
|
+
raise unless video && audio
|
25
|
+
return "MUXOPT --no-pcr-on-video-pid --new-audio-pes --vbr --vbv-len=500\n#{video}\n#{audio}"
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2010, Roger Pack
|
3
|
+
This file is part of Sensible Cinema.
|
4
|
+
|
5
|
+
Sensible Cinema is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
Sensible Cinema is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
require './../lib/mouse.rb'
|
19
|
+
Mouse::jitter_forever_in_own_thread.join
|
data/lib/movie_hasher.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module MovieHasher
|
2
|
+
|
3
|
+
CHUNK_SIZE = 64 * 1024 # in bytes
|
4
|
+
|
5
|
+
def self.compute_hash(filename)
|
6
|
+
filesize = File.size(filename)
|
7
|
+
hash = filesize
|
8
|
+
|
9
|
+
# Read 64 kbytes, divide up into 64 bits and add each
|
10
|
+
# to hash. Do for beginning and end of file.
|
11
|
+
File.open(filename, 'rb') do |f|
|
12
|
+
# Q = unsigned long long = 64 bit
|
13
|
+
f.read(CHUNK_SIZE).unpack("Q*").each do |n|
|
14
|
+
hash = hash + n & 0xffffffffffffffff # to remain as 64 bit number
|
15
|
+
end
|
16
|
+
|
17
|
+
f.seek([0, filesize - CHUNK_SIZE].max, IO::SEEK_SET)
|
18
|
+
|
19
|
+
# And again for the end of the file
|
20
|
+
f.read(CHUNK_SIZE).unpack("Q*").each do |n|
|
21
|
+
hash = hash + n & 0xffffffffffffffff
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
sprintf("%016x", hash)
|
26
|
+
end
|
27
|
+
end
|
data/lib/mplayer_edl.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2010, Roger Pack
|
3
|
+
This file is part of Sensible Cinema.
|
4
|
+
|
5
|
+
Sensible Cinema is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
Sensible Cinema is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
|
19
|
+
require_relative 'edl_parser'
|
20
|
+
|
21
|
+
class MplayerEdl
|
22
|
+
|
23
|
+
def self.convert_to_edl specs, add_this_many_to_end = 0, add_this_many_to_beginning = 0, splits = [], extra_time_to_all = 0.0, use_english_timestamps = false
|
24
|
+
|
25
|
+
# simple re-map to EDL style output
|
26
|
+
combined = EdlParser.convert_incoming_to_split_sectors specs, add_this_many_to_end, add_this_many_to_beginning, splits
|
27
|
+
|
28
|
+
out = ''
|
29
|
+
map = {:mute => 1, :blank => 0}
|
30
|
+
for start, endy, type in combined
|
31
|
+
start += extra_time_to_all
|
32
|
+
endy += extra_time_to_all
|
33
|
+
if use_english_timestamps
|
34
|
+
start = EdlParser.translate_time_to_human_readable start
|
35
|
+
endy = EdlParser.translate_time_to_human_readable endy
|
36
|
+
end
|
37
|
+
out += "#{start} #{endy} #{map[type]}\n"
|
38
|
+
end
|
39
|
+
out
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/muter.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2010, Roger Pack
|
3
|
+
This file is part of Sensible Cinema.
|
4
|
+
|
5
|
+
Sensible Cinema is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
Sensible Cinema is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
require 'rubygems' # ugh
|
19
|
+
require 'ffi'
|
20
|
+
require 'sane'
|
21
|
+
require_relative 'jruby-swing-helpers/mouse'
|
22
|
+
require_relative 'jruby-swing-helpers/play_audio'
|
23
|
+
|
24
|
+
module Muter
|
25
|
+
# from msdn on keybd_event ...
|
26
|
+
|
27
|
+
VK_VOLUME_DOWN = 0xAE
|
28
|
+
VK_VOLUME_UP = 0xAF
|
29
|
+
VK_VOLUME_MUTE = 0xAD
|
30
|
+
KEYEVENTF_KEYUP = 2
|
31
|
+
|
32
|
+
extend FFI::Library
|
33
|
+
ffi_lib 'user32'
|
34
|
+
ffi_convention :stdcall
|
35
|
+
|
36
|
+
attach_function :keybd_event, [ :uchar, :uchar, :int, :pointer ], :void
|
37
|
+
|
38
|
+
def hit_mute_key
|
39
|
+
# simulate pressing the mute key
|
40
|
+
keybd_event(VK_VOLUME_MUTE, 0, 0, nil)
|
41
|
+
keybd_event(VK_VOLUME_MUTE, 0, KEYEVENTF_KEYUP, nil)
|
42
|
+
end
|
43
|
+
|
44
|
+
def hit_volume_up_key
|
45
|
+
p 'hitting up volume key'
|
46
|
+
keybd_event(VK_VOLUME_UP, 0, 0, nil)
|
47
|
+
keybd_event(VK_VOLUME_UP, 0, KEYEVENTF_KEYUP, nil)
|
48
|
+
end
|
49
|
+
|
50
|
+
def hit_volume_down_key
|
51
|
+
p 'hitting down volume key'
|
52
|
+
keybd_event(VK_VOLUME_DOWN, 0, 0, nil)
|
53
|
+
keybd_event(VK_VOLUME_DOWN, 0, KEYEVENTF_KEYUP, nil)
|
54
|
+
end
|
55
|
+
|
56
|
+
def mute!
|
57
|
+
#unmute! # just in case...somehow this was causing problems...windows 7 perhaps? VLC?
|
58
|
+
# anyway we just use a toggle for now...dangerous but works hopefully...
|
59
|
+
if @@use_mouse_click
|
60
|
+
Mouse.single_click_left_mouse_button
|
61
|
+
else
|
62
|
+
hit_mute_key
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
@@use_mouse_click = true
|
67
|
+
|
68
|
+
# LODO better for doze 7/xp
|
69
|
+
def unmute!
|
70
|
+
if @@use_mouse_click
|
71
|
+
Mouse.single_click_left_mouse_button
|
72
|
+
elsif @@use_static_on_top
|
73
|
+
stop_playing_static
|
74
|
+
elsif @@use_down_volume_button
|
75
|
+
@@use_down_volume_button_number.times { hit_volume_up_key }
|
76
|
+
else
|
77
|
+
hit_mute_key # Windows XP...
|
78
|
+
hit_volume_down_key
|
79
|
+
hit_volume_up_key
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# allow for Muter.xxx
|
85
|
+
extend self
|
86
|
+
|
87
|
+
end
|
data/lib/ocr.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2010, Roger Pack
|
3
|
+
This file is part of Sensible Cinema.
|
4
|
+
|
5
|
+
Sensible Cinema is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
Sensible Cinema is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
require 'sane' # gem
|
19
|
+
require 'whichr' # gem
|
20
|
+
|
21
|
+
# not a dependency yet, so I don't have to bundle it...
|
22
|
+
# im_path = File.expand_path(File.dirname(__FILE__) + "/../vendor/cache/imagemagick") # convert.exe wants to only be chosen from here...
|
23
|
+
# ENV['PATH'] = im_path.gsub('/', "\\") + ';' + ENV['PATH']
|
24
|
+
|
25
|
+
if RubyWhich.new.which('identify').length == 0 || RubyWhich.new.which('convert').length == 0
|
26
|
+
puts 'appears you do not have imagemagick installed (or not in your path) -- please download and install it first! http://www.imagemagick.org/script/binary-releases.php'
|
27
|
+
raise
|
28
|
+
end
|
29
|
+
|
30
|
+
# helper for OCR'ing single digits that were screen captured
|
31
|
+
module OCR
|
32
|
+
if OS.windows?
|
33
|
+
GOCR = File.expand_path(File.dirname(__FILE__) + "/../vendor/gocr049.exe -C 0-9:/ ")
|
34
|
+
else
|
35
|
+
require_relative 'check_installed_mac'
|
36
|
+
exit 1 unless CheckInstalledMac.check_for_installed 'gocr'
|
37
|
+
GOCR = "gocr"
|
38
|
+
end
|
39
|
+
|
40
|
+
CACHE = {}
|
41
|
+
|
42
|
+
# options are :might_be_colon, :should_invert
|
43
|
+
def identify_digit memory_bitmap, options = {}
|
44
|
+
require 'mini_magick' # here because of installation woe, but actually not a big slowdown
|
45
|
+
|
46
|
+
if CACHE.has_key?(memory_bitmap)
|
47
|
+
return CACHE[memory_bitmap] unless (defined?($OCR_NO_CACHE) && $OCR_NO_CACHE)
|
48
|
+
else
|
49
|
+
puts 'cache miss' if $DEBUG && $VERBOSE
|
50
|
+
end
|
51
|
+
|
52
|
+
if options[:might_be_colon]
|
53
|
+
# do special processing <sigh>
|
54
|
+
total = (memory_bitmap.scan(/\x00{5}+/)).length
|
55
|
+
if total >= 3 # really should be 4 for VLC
|
56
|
+
# it had some darkness...therefore have been a colon!
|
57
|
+
CACHE[memory_bitmap] = ":"
|
58
|
+
return ":"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
image = MiniMagick::Image.read(memory_bitmap)
|
62
|
+
# any operation on image is expensive, requires convert.exe in path...
|
63
|
+
if options[:should_invert]
|
64
|
+
# hulu wants negate
|
65
|
+
# but doesn't want sharpen, for whatever reason...
|
66
|
+
# mogrify calls it negate...
|
67
|
+
image.negate
|
68
|
+
end
|
69
|
+
|
70
|
+
image.format(:pnm)
|
71
|
+
# I think it's VLC full screen that wants sharpening...
|
72
|
+
image.sharpen(2) if options[:sharpen] # hulu does *not* want sharpen, though I haven't checked it too closely...
|
73
|
+
|
74
|
+
previous = nil
|
75
|
+
p options if $DEBUG
|
76
|
+
raise 'you must pass in OCR levels in the player description' unless options[:levels]
|
77
|
+
for level in options[:levels]
|
78
|
+
command = "#{GOCR} -l #{level} #{image.path} 2>NUL"
|
79
|
+
a = `#{command}`
|
80
|
+
if a =~ /[0-9]/
|
81
|
+
# it might be funky like "_1_\n"
|
82
|
+
a.strip!
|
83
|
+
a.gsub!('_', '')
|
84
|
+
a = a.to_i
|
85
|
+
return CACHE[memory_bitmap] = a
|
86
|
+
end
|
87
|
+
end
|
88
|
+
# cache failures here, for VLC's hour clock' sake
|
89
|
+
CACHE[memory_bitmap] = nil
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
def version
|
94
|
+
`#{GOCR} -h 2>&1`
|
95
|
+
end
|
96
|
+
|
97
|
+
def clear_cache!
|
98
|
+
CACHE.clear
|
99
|
+
File.delete CACHE_FILE if File.exist?(CACHE_FILE)
|
100
|
+
end
|
101
|
+
|
102
|
+
CACHE_FILE = File.expand_path('~/.sensible-cinema-ocr.marshal')
|
103
|
+
|
104
|
+
def serialize_cache_to_disk
|
105
|
+
File.binwrite(CACHE_FILE, Marshal.dump(CACHE))
|
106
|
+
end
|
107
|
+
|
108
|
+
def unserialize_cache_from_disk
|
109
|
+
if File.exist? CACHE_FILE
|
110
|
+
CACHE.merge!(Marshal.load(File.binread(CACHE_FILE)))
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def load_from_ocr_seed
|
115
|
+
for file in Dir[__DIR__ + "/ocr_seed/*.bmp"]
|
116
|
+
file =~ /(\d+)\.bmp/i
|
117
|
+
digit = $1.to_i
|
118
|
+
raise unless digit < 10
|
119
|
+
CACHE[File.binread(file)] = digit
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
extend self
|
124
|
+
|
125
|
+
end
|
Binary file
|
data/lib/overlayer.rb
ADDED
@@ -0,0 +1,373 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2010, Roger Pack
|
3
|
+
This file is part of Sensible Cinema.
|
4
|
+
|
5
|
+
Sensible Cinema is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
Sensible Cinema is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
|
19
|
+
require 'sane'
|
20
|
+
require 'thread'
|
21
|
+
require 'timeout'
|
22
|
+
require 'yaml'
|
23
|
+
require_relative 'muter'
|
24
|
+
require_relative 'blanker'
|
25
|
+
require_relative 'edl_parser'
|
26
|
+
|
27
|
+
require 'pp' # for pretty_inspect
|
28
|
+
|
29
|
+
class OverLayer
|
30
|
+
|
31
|
+
def muted?
|
32
|
+
@am_muted
|
33
|
+
end
|
34
|
+
|
35
|
+
def blank?
|
36
|
+
@am_blanked
|
37
|
+
end
|
38
|
+
|
39
|
+
def mute!
|
40
|
+
@am_muted = true
|
41
|
+
puts 'muting!' if $VERBOSE
|
42
|
+
Muter.mute! unless defined?($AM_IN_UNIT_TEST)
|
43
|
+
end
|
44
|
+
|
45
|
+
def unmute!
|
46
|
+
@am_muted = false
|
47
|
+
puts 'unmuting!' if $VERBOSE
|
48
|
+
Muter.unmute! unless defined?($AM_IN_UNIT_TEST)
|
49
|
+
end
|
50
|
+
|
51
|
+
def blank! seconds
|
52
|
+
@am_blanked = true
|
53
|
+
Blanker.blank_full_screen! seconds
|
54
|
+
end
|
55
|
+
|
56
|
+
def unblank!
|
57
|
+
@just_unblanked = true
|
58
|
+
@am_blanked = false
|
59
|
+
Blanker.unblank_full_screen!
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_reload_yaml
|
63
|
+
current_mtime = File.stat(@filename).mtime
|
64
|
+
if @file_mtime != current_mtime
|
65
|
+
reload_yaml!
|
66
|
+
@file_mtime = current_mtime
|
67
|
+
else
|
68
|
+
#p 'same mtime:', @file_mtime if $DEBUG && $VERBOSE
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
attr_accessor :all_sequences
|
73
|
+
|
74
|
+
def reload_yaml!
|
75
|
+
@all_sequences = OverLayer.translate_file(@filename)
|
76
|
+
puts '(re) loaded mute sequences from ' + File.basename(@filename) + ' as', pretty_sequences.pretty_inspect, "" unless defined?($AM_IN_UNIT_TEST)
|
77
|
+
signal_change
|
78
|
+
end
|
79
|
+
|
80
|
+
def pretty_sequences
|
81
|
+
new_sequences = {}
|
82
|
+
@all_sequences.each{|type, values|
|
83
|
+
if values.is_a? Array
|
84
|
+
new_sequences[type] = values.map{|s, f|
|
85
|
+
[EdlParser.translate_time_to_human_readable(s), EdlParser.translate_time_to_human_readable(f)]
|
86
|
+
}
|
87
|
+
else
|
88
|
+
new_sequences[type] = values
|
89
|
+
end
|
90
|
+
}
|
91
|
+
new_sequences
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.new_raw ruby_hash
|
95
|
+
File.write 'temp.yml', YAML.dump(ruby_hash)
|
96
|
+
OverLayer.new('temp.yml')
|
97
|
+
end
|
98
|
+
|
99
|
+
def initialize filename
|
100
|
+
@filename = filename
|
101
|
+
@am_muted = false
|
102
|
+
@am_blanked = false
|
103
|
+
@mutex = Mutex.new
|
104
|
+
@cv = ConditionVariable.new
|
105
|
+
@file_mtime = nil
|
106
|
+
check_reload_yaml
|
107
|
+
@just_unblanked = false
|
108
|
+
@start_time = Time.now_f # assume they want to start immediately...
|
109
|
+
end
|
110
|
+
|
111
|
+
# note this is actually deprecated and won't work anymore <sigh> and needs to be updated.
|
112
|
+
def self.translate_file filename
|
113
|
+
begin
|
114
|
+
all = EdlParser.parse_file(filename)
|
115
|
+
rescue NoMethodError, ArgumentError => e
|
116
|
+
p 'appears your file has a syntax error in it--perhaps missing quotation marks?', e.to_s
|
117
|
+
raise e # hope this is ok...
|
118
|
+
end
|
119
|
+
|
120
|
+
# now it's like {:mutes => {"1:02.0" => "1:3.0"}}
|
121
|
+
# translate to floats like 62.0 => 63.0
|
122
|
+
|
123
|
+
for type in [:mutes, :blank_outs] # LODO standardize these :mutes and :blank_outs somewhere...scary to have them repeated *everywhere*
|
124
|
+
maps = all[type] || all[type.to_s] || {}
|
125
|
+
new = {}
|
126
|
+
maps.each{|start,endy|
|
127
|
+
# both are like 1:02.0
|
128
|
+
start2 = EdlParser.translate_string_to_seconds(start) if start
|
129
|
+
endy2 = EdlParser.translate_string_to_seconds(endy) if endy
|
130
|
+
if start2 == 0 || endy2 == 0 || start == nil || endy == nil
|
131
|
+
p 'warning--possible error in the Edit Decision List file some line not parsed! (NB if you want one to start at time 0 please use 0.0001)', start, endy unless $AM_IN_UNIT_TEST
|
132
|
+
# drop this line into the bitbucket...
|
133
|
+
next
|
134
|
+
end
|
135
|
+
|
136
|
+
if start2 == endy2 || endy2 < start2
|
137
|
+
p 'warning--found a line that had poor interval', start, endy, type unless defined?($AM_IN_UNIT_TEST)
|
138
|
+
next
|
139
|
+
end
|
140
|
+
if(endy2 > 60*60*3)
|
141
|
+
p 'warning--found setting past 3 hours [?]', start, endy, type unless defined?($AM_IN_UNIT_TEST)
|
142
|
+
end
|
143
|
+
new[start2] = endy2
|
144
|
+
}
|
145
|
+
all.delete(type.to_s) # cleanup
|
146
|
+
all[type] = new.sort
|
147
|
+
end
|
148
|
+
all
|
149
|
+
end
|
150
|
+
|
151
|
+
def timestamp_changed to_this_exact_string_might_be_nil, delta
|
152
|
+
if @just_unblanked
|
153
|
+
# ignore it, since it was probably just caused by the screen blipping
|
154
|
+
# at worse this will put us 1s behind...hmm.
|
155
|
+
@just_unblanked = false
|
156
|
+
p 'ignoring timestamp update ' + to_this_exact_string_might_be_nil.to_s if $VERBOSE
|
157
|
+
else
|
158
|
+
set_seconds EdlParser.translate_string_to_seconds(to_this_exact_string_might_be_nil) + delta if to_this_exact_string_might_be_nil
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
# returns seconds it's at currently...
|
164
|
+
def cur_time
|
165
|
+
Time.now_f - @start_time
|
166
|
+
end
|
167
|
+
|
168
|
+
def cur_english_time
|
169
|
+
EdlParser.translate_time_to_human_readable(cur_time)
|
170
|
+
end
|
171
|
+
|
172
|
+
def status
|
173
|
+
time = cur_english_time
|
174
|
+
begin
|
175
|
+
mute, blank, next_sig = get_current_state
|
176
|
+
if next_sig == :done
|
177
|
+
state = " no more after this point..."
|
178
|
+
else
|
179
|
+
state = " next will be at #{EdlParser.translate_time_to_human_readable next_sig}s "
|
180
|
+
end
|
181
|
+
if blank? or muted?
|
182
|
+
state += "(" + [muted? ? "muted" : nil, blank? ? "blanked" : nil ].compact.join(' ') + ") "
|
183
|
+
end
|
184
|
+
end
|
185
|
+
check_reload_yaml
|
186
|
+
time + state + "(r [ctrl+c or q to quit]): "
|
187
|
+
end
|
188
|
+
|
189
|
+
def keyboard_input char
|
190
|
+
delta = case char
|
191
|
+
when 'h' then 60*60
|
192
|
+
when 'H' then -60*60
|
193
|
+
when 'm' then 60
|
194
|
+
when 'M' then -60
|
195
|
+
when 's' then 1
|
196
|
+
when 'S' then -1
|
197
|
+
when 't' then 0.1
|
198
|
+
when 'q' then
|
199
|
+
puts '','quitting'
|
200
|
+
exit(1)
|
201
|
+
when 'T' then -0.1
|
202
|
+
when 'v' then
|
203
|
+
$VERBOSE = !$VERBOSE
|
204
|
+
p 'set verbose to ', $VERBOSE
|
205
|
+
return
|
206
|
+
when 'd'
|
207
|
+
$DEBUG = !$DEBUG
|
208
|
+
p 'set debug to', $DEBUG
|
209
|
+
return
|
210
|
+
when ' ' then
|
211
|
+
puts 'timestamp:' + cur_english_time
|
212
|
+
return
|
213
|
+
when 'r' then
|
214
|
+
reload_yaml!
|
215
|
+
puts
|
216
|
+
return
|
217
|
+
else nil
|
218
|
+
end
|
219
|
+
if delta
|
220
|
+
set_seconds(cur_time + delta)
|
221
|
+
else
|
222
|
+
puts 'invalid char: [' + char + ']'
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# sets it to a new set of seconds...
|
227
|
+
def set_seconds seconds
|
228
|
+
seconds = [seconds, 0].max
|
229
|
+
@mutex.synchronize {
|
230
|
+
@start_time = Time.now_f - seconds
|
231
|
+
}
|
232
|
+
signal_change
|
233
|
+
end
|
234
|
+
|
235
|
+
def signal_change
|
236
|
+
@mutex.synchronize {
|
237
|
+
# tell the driver thread to wake up and re-check state.
|
238
|
+
# We're not super thread friendly but good enough for having two contact each other...
|
239
|
+
@cv.signal
|
240
|
+
}
|
241
|
+
end
|
242
|
+
|
243
|
+
# we have a single scheduler thread, that is notified when the time may have changed
|
244
|
+
# like
|
245
|
+
# def restart new_time
|
246
|
+
# @current_time = xxx
|
247
|
+
# broadcast # things have changed
|
248
|
+
# end
|
249
|
+
|
250
|
+
def start_thread continue_forever = false
|
251
|
+
@thread = Thread.new { continue_until_past_all continue_forever }
|
252
|
+
end
|
253
|
+
|
254
|
+
def kill_thread!
|
255
|
+
@thread.kill
|
256
|
+
end
|
257
|
+
|
258
|
+
# returns [start, end, active|:done]
|
259
|
+
def discover_state type, cur_time
|
260
|
+
for start, endy in @all_sequences[type]
|
261
|
+
if cur_time < endy
|
262
|
+
# first one that we haven't passed the *end* of yet
|
263
|
+
if(cur_time >= start)
|
264
|
+
return [start, endy, true]
|
265
|
+
else
|
266
|
+
return [start, endy, false]
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
return [nil, nil, :done]
|
272
|
+
end
|
273
|
+
|
274
|
+
#
|
275
|
+
# returns [true, false, next_moment_of_importance|:done] ( true, false for if it should be currently muted, blanked )
|
276
|
+
#
|
277
|
+
def get_current_state
|
278
|
+
all = []
|
279
|
+
time = cur_time
|
280
|
+
for type in [:mutes, :blank_outs] do
|
281
|
+
all << discover_state(type, time)
|
282
|
+
end
|
283
|
+
output = []
|
284
|
+
# all is [[start, end, active]...] or [:done, :done]
|
285
|
+
earliest_moment = 1_000_000
|
286
|
+
all.each{|start, endy, active|
|
287
|
+
if active == :done
|
288
|
+
output << false
|
289
|
+
next
|
290
|
+
else
|
291
|
+
output << active
|
292
|
+
end
|
293
|
+
if active
|
294
|
+
earliest_moment = [earliest_moment, endy].min
|
295
|
+
else
|
296
|
+
earliest_moment = [earliest_moment, start].min
|
297
|
+
end
|
298
|
+
}
|
299
|
+
if earliest_moment == 1_000_000
|
300
|
+
output << :done
|
301
|
+
else
|
302
|
+
output << earliest_moment
|
303
|
+
end
|
304
|
+
output
|
305
|
+
end
|
306
|
+
|
307
|
+
def continue_until_past_all continue_forever
|
308
|
+
if RUBY_VERSION < '1.9.2'
|
309
|
+
raise 'need 1.9.2+ for MRI for the mutex stuff' unless RUBY_PLATFORM =~ /java/
|
310
|
+
end
|
311
|
+
|
312
|
+
@mutex.synchronize {
|
313
|
+
loop {
|
314
|
+
muted, blanked, next_point = get_current_state
|
315
|
+
if next_point == :done
|
316
|
+
if continue_forever
|
317
|
+
time_till_next_mute_starts = 1_000_000
|
318
|
+
else
|
319
|
+
#set_states! # for the unit tests' sake
|
320
|
+
return
|
321
|
+
end
|
322
|
+
else
|
323
|
+
time_till_next_mute_starts = next_point - cur_time
|
324
|
+
end
|
325
|
+
|
326
|
+
# pps 'sleeping until next action (%s) begins in %fs (%f) %f' % [next_point, time_till_next_mute_starts, Time.now_f, cur_time] if $VERBOSE
|
327
|
+
|
328
|
+
@cv.wait(@mutex, time_till_next_mute_starts) if time_till_next_mute_starts > 0
|
329
|
+
set_states!
|
330
|
+
}
|
331
|
+
}
|
332
|
+
end
|
333
|
+
|
334
|
+
def display_change change
|
335
|
+
puts '' unless defined?($AM_IN_UNIT_TEST)
|
336
|
+
if $VERBOSE
|
337
|
+
puts change + ' at ' + cur_english_time
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def set_states!
|
342
|
+
should_be_muted, should_be_blank, next_point = get_current_state
|
343
|
+
|
344
|
+
if should_be_muted && !muted?
|
345
|
+
mute!
|
346
|
+
display_change 'muted'
|
347
|
+
end
|
348
|
+
|
349
|
+
if !should_be_muted && muted?
|
350
|
+
unmute!
|
351
|
+
display_change 'unmuted'
|
352
|
+
end
|
353
|
+
|
354
|
+
if should_be_blank && !blank?
|
355
|
+
blank! "%.02f" % (next_point - cur_time)
|
356
|
+
mute! # mute with blanks currently...
|
357
|
+
display_change 'blanked'
|
358
|
+
end
|
359
|
+
|
360
|
+
if !should_be_blank && blank?
|
361
|
+
unblank!
|
362
|
+
display_change 'unblanked'
|
363
|
+
end
|
364
|
+
|
365
|
+
end
|
366
|
+
|
367
|
+
end
|
368
|
+
|
369
|
+
class Time
|
370
|
+
def self.now_f
|
371
|
+
now.to_f
|
372
|
+
end
|
373
|
+
end
|