module AdventureRL # This is an abstract class, which is inherited by # - ClipPlayer # - AudioPlayer # At its core, it takes a FileGroup in its #play method, # and "plays" it. class FileGroupPlayer include Helpers::Error # Pass settings Hash or Settings as argument. # Supersedes the child class' DEFAULT_SETTINGS. def initialize settings = {} @settings = get_default_settings.merge settings @playing = false @speed = @settings.get(:speed) @filegroup_index = 0 @filegroup = nil @current_file = nil @current_time = 0.0 @last_current_time = 0.0 @target_frame_delay = 1.0 / 24.0 # Default, will be overwritten in #play @deltatime = Deltatime.new end # Returns the settings as AdventureRL::Settings, # unless *keys are given, then it returns the value of # @settings.get(*keys). def get_settings *keys return @settings if (keys.empty?) return @settings.get(*keys) end # Returns the currently set FileGroup. def get_filegroup return @filegroup end # Returns the current playback time in seconds. def get_current_time return @current_time end alias_method :get_time, :get_current_time # Set a new current playback time in seconds. def set_current_time seconds error( "Passed seconds must be an Integer or Float,", "but got #{seconds.inspect}:#{seconds.class.name}" ) unless ([Integer, Float].include? seconds.class) @current_time = seconds end alias_method :set_time, :set_current_time # Increase (or decrease) current_time. def increase_current_time seconds error( "Passed seconds must be an Integer or Float,", "but got #{seconds.inspect}:#{seconds.class.name}" ) unless ([Integer, Float].include? seconds.class) @current_time += seconds end alias_method :increase_time, :increase_current_time alias_method :seek, :increase_current_time # Returns the current playback speed multiplier. def get_speed return @speed end # Set playback speed multiplier. def set_speed speed error( "Argument passed to #set_speed must be a Float or Integer, but got", "#{speed.inspect}:#{speed.class.name}" ) unless ([Float, Integer].include? speed.class) @speed = speed end # Increment (or decrement) the speed value by amount. def increase_speed amount error( "Argument passed to #increment_speed must be a Float or Integer, but got", "#{seconds.inspect}:#{amount.class.name}" ) unless ([Float, Integer].include? amount.class) @speed += amount end # Start playing FileGroup filegroup. def play filegroup load_filegroup filegroup @playing = true reset end # Load a FileGroup as active FileGroup. def load_filegroup filegroup error( "Passed argument must be an instance of FileGroup, but got", "#{filegroup.inspect}:#{filegroup.class.name}." ) unless (filegroup.is_a? FileGroup) set_filegroup filegroup @target_frame_delay = 1.0 / get_filegroup.get_settings(:fps).to_f end # Pause the currently playing FileGroup. def pause @playing = false end # Resumes playing paused FileGroup. def resume return unless (has_filegroup?) @playing = true @deltatime.reset end # Returns true if there is a currently active FileGroup. def has_filegroup? return !!get_filegroup end # Stop playing and clear active FileGroup. # Cannot call #resume after this, # before calling #play again. def stop @filegroup = nil @playing = false end # Calls #resume if is paused, # or calls #pause if is playing. def toggle if (is_playing?) pause elsif (has_filegroup?) resume end end # Reset the current playback. # Start playing from the start again. def reset @deltatime.reset @current_time = 0.0 @filegroup_index = 0 set_file end # Returns true if is currently _playing_, # and false if is _paused_ or _stopped_. def is_playing? return @playing end # Check which file from FileGroup is supposed to be played. # This should be called every frame. def update return unless (is_playing?) set_filegroup_index update_timing end private # This method should be overwritten by the child class, # and return their specific DEFAULT_SETTINGS. def get_default_settings return {} end def set_filegroup filegroup @filegroup_index = 0 @filegroup = filegroup set_file end def set_file filegroup = get_filegroup return if ( !filegroup || !filegroup.has_index?(get_filegroup_index) ) load_file filegroup.get_file(get_filegroup_index).to_s end # This method should be overwritten by the child class. # It is passed the filepath file. def load_file file end def get_filegroup_index return @filegroup_index end alias_method :get_index, :get_filegroup_index def set_filegroup_index previous_index = get_filegroup_index index = (get_current_time / @target_frame_delay).floor return if (previous_index == index) @filegroup_index = index filegroup = get_filegroup unless (filegroup.has_index? get_filegroup_index) if (get_settings(:loop)) reset else stop end return end set_file end def update_timing @current_time += @deltatime.dt * @speed @deltatime.update end def get_current_file return @current_file end def set_current_file new_file @current_file = new_file end end end