From 9dca962baf1ca3f9b0e9935db8e24017a7fe93d6 Mon Sep 17 00:00:00 2001 From: Doug Anarino Date: Tue, 18 Nov 2014 08:30:19 -0500 Subject: [PATCH] Docker integration, Gem loading --- .dockerignore | 8 + .gitignore | 1 + Dockerfile | 162 +++ Documentation.md | 45 + Gemfile | 31 +- README.md | 178 ++- README/README-short.txt | 1 + README/logo.png | Bin 0 -> 33736 bytes Rakefile.rb | 4 +- bin/wav2png/Makefile | 20 + bin/wav2png/anyoption.cpp | 1184 +++++++++++++++++ bin/wav2png/anyoption.h | 261 ++++ bin/wav2png/gpl.txt | 339 +++++ bin/wav2png/main.cpp | 813 +++++++++++ config/{ => aws}/moviemasher.banner | 0 config/{ => aws}/moviemasher.upstart | 0 config/config.yml | 26 +- config/docker/config.yml | 7 + config/docker/entrypoint.rb | 23 + doc/{README_md.html => Documentation_md.html} | 202 +-- doc/LICENSE.html | 571 -------- doc/MovieMasher.html | 277 ++-- doc/MovieMasher/AV.html | 16 +- doc/MovieMasher/Callback.html | 10 +- doc/MovieMasher/Chain.html | 10 +- doc/MovieMasher/ChainEffects.html | 10 +- doc/MovieMasher/ChainModule.html | 10 +- doc/MovieMasher/ChainOverlay.html | 10 +- doc/MovieMasher/ChainScaler.html | 10 +- .../{TypeTransfer.html => Configuration.html} | 49 +- doc/MovieMasher/Defaults.html | 14 +- doc/MovieMasher/Destination.html | 297 ----- doc/MovieMasher/Error.html | 16 +- doc/MovieMasher/Error/Configuration.html | 12 +- doc/MovieMasher/Error/Critical.html | 12 +- doc/MovieMasher/Error/Job.html | 12 +- doc/MovieMasher/Error/JobInput.html | 12 +- doc/MovieMasher/Error/JobOutput.html | 12 +- doc/MovieMasher/Error/JobRender.html | 14 +- doc/MovieMasher/Error/JobSource.html | 12 +- doc/MovieMasher/Error/JobUpload.html | 12 +- doc/MovieMasher/Error/Object.html | 12 +- doc/MovieMasher/Error/Parameter.html | 12 +- doc/MovieMasher/Error/Runtime.html | 16 +- doc/MovieMasher/Error/State.html | 12 +- doc/MovieMasher/Error/Todo.html | 12 +- doc/MovieMasher/Evaluate.html | 18 +- doc/MovieMasher/Fill.html | 12 +- doc/MovieMasher/Filter.html | 10 +- doc/MovieMasher/FilterEvaluated.html | 10 +- doc/MovieMasher/FilterHash.html | 10 +- doc/MovieMasher/FilterHelpers.html | 38 +- doc/MovieMasher/FilterSetpts.html | 10 +- doc/MovieMasher/FilterSource.html | 10 +- doc/MovieMasher/FilterSourceColor.html | 10 +- doc/MovieMasher/FilterSourceMovie.html | 10 +- doc/MovieMasher/Float.html | 618 --------- doc/MovieMasher/FloatUtil.html | 30 +- doc/MovieMasher/FrameRange.html | 910 ------------- doc/MovieMasher/FrameTime.html | 1182 ---------------- doc/MovieMasher/Gain.html | 12 +- doc/MovieMasher/Graph.html | 10 +- doc/MovieMasher/GraphMash.html | 10 +- doc/MovieMasher/GraphRaw.html | 10 +- .../{JobHash.html => Hashable.html} | 102 +- doc/MovieMasher/Info.html | 12 +- doc/MovieMasher/Input.html | 16 +- doc/MovieMasher/Intermediate.html | 12 +- doc/MovieMasher/Job.html | 187 ++- doc/MovieMasher/Layer.html | 10 +- doc/MovieMasher/LayerColor.html | 10 +- doc/MovieMasher/LayerModule.html | 10 +- doc/MovieMasher/LayerRaw.html | 10 +- doc/MovieMasher/LayerRawImage.html | 10 +- doc/MovieMasher/LayerRawVideo.html | 10 +- doc/MovieMasher/LayerTheme.html | 10 +- doc/MovieMasher/LayerTransition.html | 10 +- doc/MovieMasher/Mash.html | 14 +- doc/MovieMasher/Method.html | 12 +- doc/MovieMasher/Output.html | 12 +- doc/MovieMasher/Path.html | 26 +- doc/MovieMasher/Set.html | 455 ------- doc/MovieMasher/Source.html | 10 +- doc/MovieMasher/SourceRelative.html | 316 ----- doc/MovieMasher/TimeRange.html | 42 +- doc/MovieMasher/Transfer.html | 12 +- doc/created.rid | 46 +- doc/index.html | 189 +-- doc/js/search_index.js | 2 +- doc/table_of_contents.html | 179 +-- lib/{constants => constant}/av.rb | 0 lib/constant/configuration.rb | 167 +++ lib/{constants => constant}/defaults.rb | 2 +- lib/{constants => constant}/error.rb | 0 lib/{constants => constant}/fill.rb | 0 lib/{constants => constant}/gain.rb | 0 lib/{constants => constant}/info.rb | 0 lib/{constants => constant}/intermediate.rb | 0 lib/{constants => constant}/method.rb | 0 lib/input.rb | 2 +- lib/job.rb | 110 +- lib/mash.rb | 2 +- lib/moviemasher.rb | 154 ++- lib/output.rb | 2 +- lib/transfer.rb | 2 +- lib/{utils => util}/eval.rb | 2 +- lib/{utils => util}/filter_helpers.rb | 0 lib/{utils => util}/float_util.rb | 0 lib/{job_hash.rb => util/hashable.rb} | 10 +- lib/{utils => util}/path.rb | 0 lib/{utils => util}/time_range.rb | 0 lib/version.rb | 3 + spec/aws_spec.rb | 42 + {spec_aws => spec}/helpers/clientside_aws.rb | 20 +- spec/helpers/config.yml | 4 +- spec/helpers/media/json/inputs/image_url.json | 2 +- spec/helpers/spec_helper.rb | 44 +- spec_aws/README.txt | 8 - spec_aws/aws_spec.rb | 49 - 119 files changed, 4391 insertions(+), 5645 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 Documentation.md create mode 100644 README/README-short.txt create mode 100644 README/logo.png create mode 100644 bin/wav2png/Makefile create mode 100755 bin/wav2png/anyoption.cpp create mode 100755 bin/wav2png/anyoption.h create mode 100644 bin/wav2png/gpl.txt create mode 100644 bin/wav2png/main.cpp rename config/{ => aws}/moviemasher.banner (100%) rename config/{ => aws}/moviemasher.upstart (100%) create mode 100644 config/docker/config.yml create mode 100755 config/docker/entrypoint.rb rename doc/{README_md.html => Documentation_md.html} (60%) delete mode 100644 doc/LICENSE.html rename doc/MovieMasher/{TypeTransfer.html => Configuration.html} (87%) delete mode 100644 doc/MovieMasher/Destination.html delete mode 100644 doc/MovieMasher/Float.html delete mode 100644 doc/MovieMasher/FrameRange.html delete mode 100644 doc/MovieMasher/FrameTime.html rename doc/MovieMasher/{JobHash.html => Hashable.html} (83%) delete mode 100644 doc/MovieMasher/Set.html delete mode 100644 doc/MovieMasher/SourceRelative.html rename lib/{constants => constant}/av.rb (100%) create mode 100644 lib/constant/configuration.rb rename lib/{constants => constant}/defaults.rb (93%) rename lib/{constants => constant}/error.rb (100%) rename lib/{constants => constant}/fill.rb (100%) rename lib/{constants => constant}/gain.rb (100%) rename lib/{constants => constant}/info.rb (100%) rename lib/{constants => constant}/intermediate.rb (100%) rename lib/{constants => constant}/method.rb (100%) rename lib/{utils => util}/eval.rb (92%) rename lib/{utils => util}/filter_helpers.rb (100%) rename lib/{utils => util}/float_util.rb (100%) rename lib/{job_hash.rb => util/hashable.rb} (88%) rename lib/{utils => util}/path.rb (100%) rename lib/{utils => util}/time_range.rb (100%) create mode 100755 lib/version.rb create mode 100644 spec/aws_spec.rb rename {spec_aws => spec}/helpers/clientside_aws.rb (56%) delete mode 100644 spec_aws/README.txt delete mode 100644 spec_aws/aws_spec.rb diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2c3c794 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +.DS_Store +log/* +tmp/* +doc/* +spec/* +spec_aws/* +.git/* +.bundle* diff --git a/.gitignore b/.gitignore index 4ec7bfc..ae99157 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ log/* tmp/* Gemfile.lock spec/helpers/media/video/* +.bundle* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2b51a5f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,162 @@ +FROM ruby +MAINTAINER Movie Masher + +ENV HOME /root + +# install tools and helpers +RUN apt-get update && apt-get install -y \ + apt-utils \ + build-essential \ + checkinstall \ + cmake \ + git \ + subversion \ + wget \ + yasm + +# install video libs and plugins +RUN apt-get update && apt-get install -y \ + libdirac-dev \ + libfontconfig-dev \ + libfribidi-dev \ + libgd-dev \ + libvpx-dev \ + libxvidcore-dev \ + frei0r-plugins-dev + +# install audio libs and apps +RUN apt-get update && apt-get install -y \ + libmp3lame-dev \ + libogg-dev \ + libopencore-amrnb-dev \ + libopencore-amrwb-dev \ + libsamplerate-dev \ + libsndfile-dev \ + libsox-dev \ + libspeex-dev \ + libtheora-dev \ + libvorbis-dev \ + sox \ + ecasound + +# clean up apt and temporary directories +RUN apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# ffmpeg prefers openjpeg 1.5.x, so we compile it from source - 11/15/2014 +WORKDIR /data +RUN \ + wget https://downloads.sourceforge.net/project/openjpeg.mirror/1.5.2/openjpeg-1.5.2.tar.gz; \ + tar -xzvf openjpeg-1.5.2.tar.gz; \ + cd /data/openjpeg-1.5.2; \ + cmake .; \ + make; \ + make install; \ + cd /data; \ + rm -R /data/openjpeg-1.5.2 + +# pull, configure, make and install x264 +WORKDIR /data +RUN \ + git clone git://git.videolan.org/x264.git; \ + cd /data/x264; \ + ./configure --prefix=/usr --enable-shared; \ + make; \ + make install; \ + cd /data; \ + rm -R /data/x264 + +# pull, configure, make and install ffmpeg +WORKDIR /data +RUN \ + git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg; \ + cd /data/ffmpeg; \ + ./configure \ + --enable-frei0r \ + --enable-gpl \ + --enable-libfontconfig \ + --enable-libfreetype \ + --enable-libfribidi \ + --enable-libmp3lame \ + --enable-libopencore-amrnb \ + --enable-libopencore-amrwb \ + --enable-libopenjpeg \ + --enable-libspeex \ + --enable-libtheora \ + --enable-libvorbis \ + --enable-libvpx \ + --enable-libx264 \ + --enable-libxvid \ + --enable-postproc \ + --enable-pthreads \ + --enable-version3 \ + --enable-zlib \ + --extra-cflags="-I/usr/local/include/openjpeg" \ + ; \ + make; \ + make install; \ + cd /data; \ + rm -R /data/ffmpeg + +# needed for binaries to find libraries +RUN ldconfig + +# install our production gems +COPY Gemfile /data/ +COPY Gemfile.lock /data/ +WORKDIR /data +RUN \ + bundle config --global frozen 1; \ + bundle install --without test development + +# copy, make and install wav2png +COPY bin/wav2png/* /data/wav2png/ +WORKDIR /data/wav2png +RUN \ + make; \ + mv wav2png /usr/bin/; \ + cd /data; \ + rm -R /data/wav2png + +# copy everything except what's caught by .dockerignore +COPY . /mnt/moviemasher.rb/ +WORKDIR /mnt/moviemasher.rb + +# install our entry point, with default command +CMD ["moviemasher"] +ENTRYPOINT ["config/docker/entrypoint.rb"] + +# expose all our configurable directories as potential mount points +VOLUME /mnt/queue +VOLUME /mnt/log +VOLUME /mnt/render +VOLUME /mnt/download +VOLUME /mnt/error + +# EVERYTHING BELOW CAN BE UNCOMMENTED TO PRODUCE DEV IMAGE +## +## # install redis for aws-sdk +## WORKDIR /data +## RUN \ +## wget "http://download.redis.io/releases/redis-2.8.17.tar.gz"; \ +## gunzip redis-2.8.17.tar.gz; \ +## tar -xvf redis-2.8.17.tar; \ +## cd /data/redis-2.8.17; \ +## ./configure; \ +## make; \ +## make install; \ +## cd /data; \ +## rm -R /data/redis-2.8.17 +## +## # install our test gems +## COPY Gemfile /data/ +## COPY Gemfile.lock /data/ +## RUN \ +## bundle config --global frozen 1; \ +## bundle install --without production +## WORKDIR /mnt/moviemasher.rb +## +## # add a mount point for angular-moviemasher for modular spec tests +## VOLUME /mnt/angular-moviemasher +## +## # add a mount point for the project itself (masking repo copied above) +## VOLUME /mnt/moviemasher.rb diff --git a/Documentation.md b/Documentation.md new file mode 100644 index 0000000..50b7113 --- /dev/null +++ b/Documentation.md @@ -0,0 +1,45 @@ +![Image](https://github.com/moviemasher/moviemasher.rb/raw/master/README/logo-120x60.png "MovieMasher.com") **[moviemasher.js](https://github.com/moviemasher/moviemasher.js "stands below angular-moviemasher, providing audiovisual playback handling and edit support in a web browser") | [angular-moviemasher](https://github.com/moviemasher/angular-moviemasher "sits between moviemasher.js and moviemasher.rb, providing an editing GUI and simple CMS middleware layer") | [moviemasher.rb](https://github.com/moviemasher/moviemasher.rb "sits behind angular-moviemasher, providing processor intensive video transcoding services through a simple API")** + +*Ruby library for mashing up video, images and audio utilizing FFmpeg and Ecasound* +# moviemasher.rb + +--- + +### RDoc Documentation + + +##### Core Classes/Modules + + +- MovieMasher +- MovieMasher::Job +- MovieMasher::Input +- MovieMasher::Output +- MovieMasher::Transfer +- MovieMasher::Callback + + +##### Core Usage + + + require_relative 'lib/moviemasher.rb' + job = { :inputs => [], :base_source => {}, :outputs => [], :destination => {} } + job[:base_source][:path] = job[:destination][:path] = '~/' + job[:inputs] << { :type => 'video', :source => 'input.mov', :fill => 'crop' } + job[:inputs] << { :type => 'image', :source => 'input.jpg', :length => 2 } + job[:inputs] << { :type => 'audio', :source => 'input.mp3', :offset => 10 } + job[:outputs] << { :type => 'video', :name => 'output.mp4' } + MovieMasher.process job + +When inputs use relative URLs like the example above then either the input or the job needs a `base_source` object to resolve them to absolute ones. Likewise, a `destination` object resolves the location of outputs and can be placed either in them or in the job in order to be available to all outputs. We've set them both to our home directory in this case so all files live there. + +Inputs are arranged consecutively one after the other - at least the visual ones. Audio inputs will by default start where the last audio or video with audio ends, so if the video input in our example has audio the audio input will start after it, otherwise they will begin at the same time. You can also explicitly play an audio track at any time by specify its `start` value. + +In addition to raw media (video, audio and images) it's also possible to output image sequences from video tracks and waveform graphics from audio tracks. In terms of inputs, it's also possible to provide a mash JSON payload like moviemasher.js creates. Within a mash input, visual elements can be composited together just like audio elements can in the job itself. + +The visual composition of inputs is controlled by *effect, scaler* and *merger* media, which are all arrangements of FFmpeg *filters*. Only a subset of filters and their parameters are supported at this time, but they include basics like crop, scale, fade and drawtext. That last one relies on *font* media, the last of the modular types. + + +**To regenerate this documentation `cd` to project directory and execute:** + + rdoc --visibility=public -o doc --main='Documentation.md' --fmt=darkfish --markup=tomdoc --tab-width=2 --no-dcov --exclude='/spec' --exclude='/log' --exclude='/Gemfile' --exclude='/tmp' --exclude='/config' --exclude='/index.rb' --exclude='/doc' --exclude='/bin' --exclude='/Rakefile' --exclude='/Docker' --exclude='/README' --exclude='/LICENSE' diff --git a/Gemfile b/Gemfile index 851a308..90ca794 100644 --- a/Gemfile +++ b/Gemfile @@ -1,24 +1,23 @@ source 'https://rubygems.org' source 'http://gems.github.com' -ruby '2.0.0' - -gem 'aws-sdk', '= 1.51.0' -gem 'builder', '= 3.1.0' -gem 'json', '= 1.7.7' +gem 'builder', '= 3.1.4' gem 'mime-types', '~> 2.3' gem 'require_all', '= 1.3.2' -gem 'uuid', '= 2.3.7' gem "multipart-post", "= 2.0.0" -gem "rake", "= 10.3.2" -# for spec tests in /spec -#gem "rack", "= 1.5.2" -#gem "rack-test", "= 0.5.7" -#gem 'rspec', '= 2.14.1' +group :production do + gem 'aws-sdk', '= 1.35.0' + gem 'uuid', '= 2.3.1' + gem 'json', '~> 1.4' +# gem "rake", "= 10.3.2" +end -# for spec tests in /spec_aws - see README there -gem 'redis', "3.0.1" -gem "hiredis", "0.4.5" -gem "httparty", "0.11.0" -gem "sinatra", "1.4.2" +group :test do + # for spec tests in /spec + gem 'clientside_aws', :git => 'https://github.com/perrystreetsoftware/clientside_aws.git' + gem "rack-test", "= 0.5.7" + gem 'rspec', '= 2.14.1' + gem "hiredis", "0.4.5" + gem "rmagick", :github => "gemhome/rmagick" +end diff --git a/README.md b/README.md index 3d34f27..01d350d 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,150 @@ -![Image](https://github.com/moviemasher/angular-moviemasher/raw/master/README/logo-120x60.png "MovieMasher.com") -**[moviemasher.js](https://github.com/moviemasher/moviemasher.js "stands below angular-moviemasher, providing audiovisual playback handling and edit support in a web browser") | [angular-moviemasher](https://github.com/moviemasher/angular-moviemasher "sits between moviemasher.js and moviemasher.rb, providing an editing GUI and simple CMS middleware layer") | moviemasher.rb** +[![Image](https://github.com/moviemasher/moviemasher.rb/raw/master/README/logo-120x60.png "MovieMasher.com")](https://www.moviemasher.com) **[moviemasher.js](https://github.com/moviemasher/moviemasher.js "stands below angular-moviemasher, providing audiovisual playback handling and edit support in a web browser") | [angular-moviemasher](https://github.com/moviemasher/angular-moviemasher "sits between moviemasher.js and moviemasher.rb, providing an editing GUI and simple CMS middleware layer") | moviemasher.rb** *Ruby library for mashing up video, images and audio utilizing FFmpeg and Ecasound* -#moviemasher.rb +# moviemasher.rb -Use moviemasher.rb to encode mashups of video, audio, and images from a JSON formatted job description. A job specifies multiple media inputs to be encoded together into one or more outputs, as well as where to find the inputs and where to place the outputs. +Use moviemasher.rb to encode mashups of video, audio, and images from simple *job* descriptions. A job specifies multiple media *inputs* to be encoded together into one or more *outputs*, as well as where to find source assets and place the final rendering. - **concatenate** files together sequentially with trimming - **mix** audio tracks together with variable fading - **composite** visual tracks together with transformations - **add** titling as an effect or theme with custom fonts -- **transfer** encoded files to remote hosts +- **transfer** media files to and from remote hosts - **specify** callbacks that alert your system of processing milestones -The project aims to take the complexity out of describing common audio/video editing operations to command line programs, which handle the low level transcoding operations. The MovieMasher class turns your job into a series of commands and then manages their execution. +### Overview +The project aims to simplify common audio/video editing operations by turning your job description into a series of shell commands, and then overseeing their execution. As part of job processing, media inputs can be downloaded from remote hosts and rendered outputs can be uploaded as well. Using the same request mechanisms, external systems can be alerted by *callbacks* triggered when a job is started, during its processing and/or when it's completed. -As part of job processing it can download media inputs from remote hosts and upload media outputs as well. Using the same mechanisms it can also trigger callbacks as a job is started, during its processing and when it's completed so that external systems can be alerted. +- **Documentation:** generated with RDoc from source [(HTML)](doc/index.html) +- **Docker Image:** `moviemasher/moviemasher.rb` [(Dockerfile)](Dockerfile) -The project includes a rake task that can be routinely called to watch a folder for job description files, as well as an example crontab entry that calls it. Recall that ruby scripts run from cron lack your user's environmental variables, so you'll probably need to edit the paths to binary directories in the entry to match your system. +In addition to the raw media assets (video, audio and images), jobs can contain *mash* inputs that describe more complex compositing, titling and other effects. The related [**moviemasher.js**](https://github.com/moviemasher/moviemasher.js) project can be used to generate and display JSON formatted mash descriptions within a web browser, and [**angular-moviemasher**](https://github.com/moviemasher/angular-moviemasher) can be used to package these into job descriptions. + +Jobs are provided to the system for processing in different ways, depending on how it's been configured and deployed. At the lowest level, the [MovieMasher.process](doc/MovieMasher.html#method-c-process) method is sent a job as a hash, a JSON/YAML formatted string or a local path to one. The [MovieMasher.process_queues](doc/MovieMasher.html#method-c-process_queues) method calls it with any jobs it finds while scanning a preconfigured watch folder or queue. This scanning can be done for a certain number of seconds, until no jobs are found, just once or forever. There are rake tasks for each of these methods, to simplify calling from shell scripts, cron jobs and other tasks. ### AWS Integration -There are optional configuration settings that support two specific Amazon Web Services offerings: S3 for media storage and SQS for job queueing. If set to use an SQS queue then it will be polled as part of the folder watching process for job files. The ruby aws-sdk is utilized to interface with SQS, so access key details can be provided in the configuration or environmental variables or in a role if deployed on an EC2 instance. +The system *optionally* supports [Amazon Web Services](http://aws.amazon.com) for media storage and job queueing, through the ruby [aws-sdk](https://github.com/aws/aws-sdk-ruby) gem. The following mechanisms are available through configuration or job options: -Similarly, aws-sdk is utilized for S3 interactions so if access key details are present then buckets can be used either as sources for media inputs or destinations for media outputs within job descriptions. These are authenticated requests, so the buckets do not have to be public. +- An [S3](http://aws.amazon.com/s3/) bucket can be a source for inputs or a destination for outputs +- An [SQS](http://aws.amazon.com/sqs/) queue can be polled and messages processed as jobs +- An access key id/secret can be passed to AWS.config for authentication +- Alternatively, environmental variables or an [EC2](http://aws.amazon.com/ec2/) role can authenticate -Additionally, the Movie Masher AMI is available in Marketplace and includes moviemasher.rb and all supporting applications. When launched it looks for user data supplied in JSON format and merges it into the default configuration, so it's possible to supply SQS options on startup. The cron job described above is installed, so a configured SQS queue will immediately start being polled for jobs. Otherwise the instance will start up apache to serve the angular-moviemasher project, preconfigured to utilize the local moviemasher.rb process (the instance id acts as a shared password). +Additionally, the Movie Masher AMI is launchable with OneClick in Marketplace as a deployment of all related projects and supporting applications. It includes an upstart task that executes `rake moviemasher:init` to merge any User Data supplied in JSON format into the configuration plus a cron job that continually executes `rake moviemasher:process_queues`, so it's possible to run in a headless mode polling an SQS queue for jobs. Without User Data, the instance will start up Apache and serve the angular-moviemasher project for demonstration - the instance id acts as a shared password. -### Basic Usage +### Docker Usage +The [`moviemasher/moviemasher.rb`](https://registry.hub.docker.com/u/moviemasher/moviemasher.rb/) image on [docker.com](https://docker.com) is based off the official [`ruby`](https://registry.hub.docker.com/_/ruby/) image, adding builds of [FFmpeg](http://www.ffmpeg.org), [Ecasound](http://eca.cx/ecasound/) and supporting audio/visual libraries. It can be used to process jobs supplied directly on the command line, or to grab them from a directory/queue - either approach supports running in interractive or daemon mode. The Dockerfile contains a **VOLUME** instruction for each directory it works with, including **queue_directory** so that job files residing on the host can be easily processed. - require_relative 'lib/moviemasher.rb' - job = { :inputs => [], :base_source => {}, :outputs => [], :destination => {} } - job[:base_source][:path] = job[:destination][:path] = '~/' - job[:inputs] << { :type => 'video', :source => 'input.mov', :fill => 'crop' } - job[:inputs] << { :type => 'image', :source => 'input.jpg', :length => 2 } - job[:inputs] << { :type => 'audio', :source => 'input.mp3', :offset => 10 } - job[:outputs] << { :type => 'video', :name => 'output.mp4' } - MovieMasher.process job +- To display documentation of configuration options: + + `docker run -it -rm moviemasher/moviemasher.rb moviemasher --help` + +- To process jobs directly from the command line: -When inputs use relative URLs like the example above then either the input or the job needs a `base_source` object to resolve them to absolute ones. Likewise, a `destination` object resolves the location of outputs and can be placed either in them or in the job in order to be available to all outputs. We've set them both to our home directory in this case so all files live there. + `docker run -it -rm moviemasher/moviemasher.rb process "JOB" "JOB"` + + JOB can be a JSON or YAML formatted string, or a path to one in the container. -Inputs are arranged consecutively one after the other - at least the visual ones. Audio inputs will by default start where the last audio or video with audio ends, so if the video input in our example has audio the audio input will start after it, otherwise they will begin at the same time. You can also explicitly play an audio track at any time by specify its `start` value. +- To process all jobs in directory 'my_jobs' residing on the host: -In addition to raw media (video, audio and images) it's also possible to output image sequences from video tracks and waveform graphics from audio tracks. In terms of inputs, it's also possible to provide a mash JSON payload like moviemasher.js creates. Within a mash input, visual elements can be composited together just like audio elements can in the job itself. + `docker run -it -rm -v my_jobs:/mnt/queue moviemasher/moviemasher.rb` + + Files can be in JSON or YAML format. + +- To continually process jobs in directory 'my_jobs' residing on the host in background: -The visual composition of inputs is controlled by *effect, scaler* and *merger* media, which are all arrangements of FFmpeg *filters*. Only a subset of filters and their parameters are supported at this time, but they include basics like crop, scale, fade and drawtext. That last one relies on *font* media, the last of the modular types. + `docker run -d --name moviemasher -v my_jobs:/mnt/queue moviemasher/moviemasher.rb process_loop` + + You'll need to subsequently execute `docker stop moviemasher` and `docker rm moviemasher` to stop processing and remove the container created. -### How to Install -1. install ffmpeg, ecasound, sox and du programs -2. install ruby and builder -3. `bundle install` in project directory installs required gems from Gemfile -4. edit config/config.yml configuration file to match paths on system and configure logging/debugging options -5. `rake moviemasher:process_queues` searches watch folder and optional SQS queue for jobs -6. optionally install calling crontab entry found at config/moviemasher.cron after checking binary paths in it +- To process a single job from an SQS queue: + + `docker run -it -rm moviemasher/moviemasher.rb process_one --queue_url=[URL] --aws_access_key_id=[ID] --aws_secret_access_key=[SECRET]` + + URL points to an existing SQS Queue that provides read/write access to the owner of the access key with ID and SECRET. Messages can be in JSON or YAML format. + +The last example demonstrates overriding the configuration with command line arguments - all commands support this. The **MOVIEMASHER_CONFIG** environmental variable can also be set to a configuration file residing on the container in JSON/YAML format, though arguments take precedence. + +When processing jobs in a directory or queue, the **process_seconds** configuration option ultimately controls how long polling continues and therefore how long the container runs. The following values are supported: + +- [N]: poll for N seconds, then exit +- 0: do not poll, just exit +- -1: process a single job if found, then exit +- -2: poll until no jobs remain, then exit +- -3: poll until container stopped + +The Dockerfile specifies an **ENTRYPOINT** that provides several convenience commands, but calls exec with any it doesn't recognize so that containers behave as expected. The following commands are supported: + +- moviemasher (default): call [MovieMasher.process_queues](doc/MovieMasher.html#method-c-process_queues) +- process_one: call [MovieMasher.process_queues](doc/MovieMasher.html#method-c-process_queues) with **process_seconds**=-1 +- process_all: call [MovieMasher.process_queues](doc/MovieMasher.html#method-c-process_queues) with **process_seconds**=-2 +- process_loop: call [MovieMasher.process_queues](doc/MovieMasher.html#method-c-process_queues) with **process_seconds**=-3 +- process: call [MovieMasher.process](doc/MovieMasher.html#method-c-process) for each supplied argument ### Requirements -- ffmpeg with ffprobe -- ecasound -- sox -- du -- builder gem -- require_all gem -- json gem -- uuid gem -- mime-types gem -- multipart-post gem -- rake gem -- rack gem -- aws-sdk gem - -### Developer Setup -1. uncomment entries in Gemfile related to spec tests -2. `bundle install` from project directory installs additional gems -3. `rspec spec` will run the core tests -4. The following with regenerate the doc directory: - rdoc --visibility=public --main='README.md' -o doc --fmt=darkfish --markup=tomdoc --tab-width=2 --no-dcov --exclude='/spec' --exclude='/log/' --exclude='/Gemfile' --exclude='/config/' --exclude='/index.rb' --exclude='/doc/' --exclude='/Rakefile' - -##### To run tests in spec_aws -1. install and launch clientside_aws -2. uncomment other entries in Gemfile -3. `bundle install` from project directory installs additional gems +Tested in Ruby 1.9.3 and 2.1.5 (the `dockerfile/ruby` and `ruby` docker images) and on multiple UNIX flavors including OSX. Suggested audio/video libraries are only needed if you're decoding or encoding in their formats. Likewise, the aws-sdk gem is only needed when utilizing Amazon's services. + +- Applications: [FFmpeg](http://www.ffmpeg.org), [Ecasound](http://eca.cx/ecasound/), [Sox](http://sox.sourceforge.net) +- Ruby Gems: aws-sdk, builder, mime-types, multipart-post, require_all, uuid +- Audio Libraries: mp3lame, ogg, opencore, samplerate, sndfile, speex, theora, vorbis +- Video Libraries: dirac, fontconfig, frei0r, fribidi, gd, openjpeg, vpx, xvidcore, x264 + + +### How to Install +Transcoding audio and video is extremely processor intensive, so while installation might be possible on most machines it isn't reccommended for all environments. In particular, running alongside a web server is only practical for demonstration purposes. Typically in production a pool of machines is deployed with each instance running a single process solely engaged in transcoding. + +1. Review [Dockerfile](Dockerfile) for commands that work on jessie +2. Install av libraries for supported formats and codecs +3. Install sox, ecasound and ffmpeg applications (in that order) +4. Install ruby and bundler gem +5. To install required gems `cd` to project directory and execute: + + `bundle install --without test` +6. Edit config/config.yml configuration file to match paths on system and configure logging/debugging options +7. To scan watch folder and/or queue for jobs `cd` to project directory and execute: + + `rake moviemasher:process_queues` +8. *optionally* add crontab entry from config/moviemasher.cron, after checking its binary paths + + +### User Feedback +If any problems arise while utilizing this repository, a [GitHub Issue Ticket](https://github.com/moviemasher/moviemasher.rb/issues) should be filed. Please include the job description that's causing problems and any relevant log entries - issues with callbacks can typically be resolved faster after seeing entries from the receiving web server's log. Please post your issue ticket in the appropriate repository and refrain from cross posting - all projects are monitored with equal zeal. + + +### Contributing +Please join in the shareable economy by gifting your efforts towards improving this project in any way you feel inclined. Pull requests for fixes, features and refactorings are always appreciated, as are documentation updates. Creative help with graphics, video and the web site is also needed. Please contact through [MovieMasher.com](https://moviemasher.com) to discuss your ideas. + + +#### Developer Setup +Several additional gems and applications that support them need to be installed in order to run the rspec tests in the spec directory: + +- Ruby Gems: clientside_aws, rmagick, hiredis, rack-test, rspec +- Applications: imagemagick, redis + +Addtionally, some tests utilize module descriptions from the [angular-moviemasher](https://github.com/moviemasher/angular-moviemasher "sits between moviemasher.js and moviemasher.rb, providing an editing GUI and simple CMS middleware layer") project, which is expected to be cloned to the same directory as this project. Tests will still pass without the project being installed, but rendering of mash inputs will not actually be tested. + +- Once applications are installed `cd` to project directory and execute: + + `bundle install --without production` + + `rspec spec` + +Or if docker is being used, a helpful development version of the image can be built by uncommenting the last section in Dockerfile. These commands add the applications and gems to the image, as well as specifying the repo directory as a `VOLUME` - it's replaced by the current host version at runtime. + +- To build development image `cd` to to project directory and execute: + + `sed -i '' 's/^## //' Dockerfile` + + `docker build --tag="moviemasher/moviemasher.rb:dev" .` + +- And then to run rspec tests in a container: + + `docker run -it --rm -v $(pwd):/mnt/moviemasher.rb moviemasher/moviemasher.rb:dev rspec spec` + +- If you have the [angular-moviemasher](https://github.com/moviemasher/angular-moviemasher "sits between moviemasher.js and moviemasher.rb, providing an editing GUI and simple CMS middleware layer") project installed alongside this one then the following switch can be added to the command above in order to mount it for the mash rendering tests: + + `-v $(pwd)/../angular-moviemasher:/mnt/angular-moviemasher` + ##### Known issues in Version 4.0.08 - local/sqs import/export has not been thoroughly tested diff --git a/README/README-short.txt b/README/README-short.txt new file mode 100644 index 0000000..e8c7526 --- /dev/null +++ b/README/README-short.txt @@ -0,0 +1 @@ +Based on ruby:latest - includes FFmpeg, Ecasound, supporting AV libaries and moviemasher.rb \ No newline at end of file diff --git a/README/logo.png b/README/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..975f9f64ba99ed89cde899fd370b30917d536baa GIT binary patch literal 33736 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 IM6N<$g5a^|{Qv*} literal 0 HcmV?d00001 diff --git a/Rakefile.rb b/Rakefile.rb index 5f33a3e..132c6de 100644 --- a/Rakefile.rb +++ b/Rakefile.rb @@ -1,7 +1,7 @@ task :environment -PathUser = "#{__dir__}/../config/userdata.json" -PathConfig = "#{__dir__}/../config/config.yml" +PathUser = "#{File.dirname(__FILE__)}/../config/userdata.json" +PathConfig = "#{File.dirname(__FILE__)}/../config/config.yml" namespace :moviemasher do desc "If json user data supplied then write it to config, otherwise start web server" diff --git a/bin/wav2png/Makefile b/bin/wav2png/Makefile new file mode 100644 index 0000000..3f38121 --- /dev/null +++ b/bin/wav2png/Makefile @@ -0,0 +1,20 @@ +CC= g++ +CXXFLAGS= -c -O2 -Wall -pedantic +LDFLAGS= -lgd -lsndfile -ljpeg +EXEC=wav2png + +all: anyoption.o main.o + $(CC) anyoption.o main.o $(LDFLAGS) -o $(EXEC) + +static: anyoption.o main.o + $(CC) -static anyoption.o main.o $(LDFLAGS) -lpng12 -lz -o $(EXEC)-static + +main.o: main.cpp + $(CC) $(CXXFLAGS) main.cpp + +anyoption.o: anyoption.cpp + $(CC) $(CXXFLAGS) anyoption.cpp + +clean: + rm ./*.o + rm $(EXEC) diff --git a/bin/wav2png/anyoption.cpp b/bin/wav2png/anyoption.cpp new file mode 100755 index 0000000..b65df5f --- /dev/null +++ b/bin/wav2png/anyoption.cpp @@ -0,0 +1,1184 @@ +#include +using namespace std; +/* + * AnyOption 1.3 + * + * kishan at hackorama dot com www.hackorama.com JULY 2001 + * + * + Acts as a common facade class for reading + * commandline options as well as options from + * an optionfile with delimited type value pairs + * + * + Handles the POSIX style single character options ( -w ) + * as well as the newer GNU long options ( --width ) + * + * + The option file assumes the traditional format of + * first character based comment lines and type value + * pairs with a delimiter , and flags which are not pairs + * + * # this is a coment + * # next line is an option value pair + * width : 100 + * # next line is a flag + * noimages + * + * + Supports printing out Help and Usage + * + * + Why not just use getopt() ? + * + * getopt() Its a POSIX standard not part of ANSI-C. + * So it may not be available on platforms like Windows. + * + * + Why it is so long ? + * + * The actual code which does command line parsing + * and option file parsing are done in few methods. + * Most of the extra code are for providing a flexible + * common public interface to both a resourcefile and + * and command line supporting POSIX style and + * GNU long option as well as mixing of both. + * + * + Please see "anyoption.h" for public method descriptions + * + */ + +/* Updated Auguest 2004 + * Fix from Michael D Peters (mpeters at sandia.gov) + * to remove static local variables, allowing multiple instantiations + * of the reader (for using multiple configuration files). There is + * an error in the destructor when using multiple instances, so you + * cannot delete your objects (it will crash), but not calling the + * destructor only introduces a small memory leak, so I + * have not bothered tracking it down. + * + * Also updated to use modern C++ style headers, rather than + * depricated iostream.h (it was causing my compiler problems) +*/ + +/* + * Updated September 2006 + * Fix from Boyan Asenov for a bug in mixing up option indexes + * leading to exception when mixing different options types + */ + +/* + * Updated July 2012 + * Discontinue the use of iostreams + */ + +#include "anyoption.h" + +#include +#include +#include + +using namespace std; + +AnyOption::AnyOption() +{ + init(); +} + +AnyOption::AnyOption(int maxopt) +{ + init( maxopt , maxopt ); +} + +AnyOption::AnyOption(int maxopt, int maxcharopt) +{ + init( maxopt , maxcharopt ); +} + +AnyOption::~AnyOption() +{ + if( mem_allocated ) + cleanup(); +} + +void +AnyOption::init() +{ + init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS ); +} + +void +AnyOption::init(int maxopt, int maxcharopt ) +{ + + max_options = maxopt; + max_char_options = maxcharopt; + max_usage_lines = DEFAULT_MAXUSAGE; + usage_lines = 0 ; + argc = 0; + argv = NULL; + posix_style = true; + verbose = false; + filename = NULL; + appname = NULL; + option_counter = 0; + optchar_counter = 0; + new_argv = NULL; + new_argc = 0 ; + max_legal_args = 0 ; + command_set = false; + file_set = false; + values = NULL; + g_value_counter = 0; + mem_allocated = false; + command_set = false; + file_set = false; + opt_prefix_char = '-'; + file_delimiter_char = ':'; + file_comment_char = '#'; + equalsign = '='; + comment = '#' ; + delimiter = ':' ; + endofline = '\n'; + whitespace = ' ' ; + nullterminate = '\0'; + set = false; + once = true; + hasoptions = false; + autousage = false; + + strcpy( long_opt_prefix , "--" ); + + if( alloc() == false ){ + printf("\nOPTIONS ERROR : Failed allocating memory\nExiting.\n"); + exit (0); + } +} + +bool +AnyOption::alloc() +{ + int i = 0 ; + int size = 0 ; + + if( mem_allocated ) + return true; + + size = (max_options+1) * sizeof(const char*); + options = (const char**)malloc( size ); + optiontype = (int*) malloc( (max_options+1)*sizeof(int) ); + optionindex = (int*) malloc( (max_options+1)*sizeof(int) ); + if( options == NULL || optiontype == NULL || optionindex == NULL ) + return false; + else + mem_allocated = true; + for( i = 0 ; i < max_options ; i++ ){ + options[i] = NULL; + optiontype[i] = 0 ; + optionindex[i] = -1 ; + } + optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) ); + optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) ); + optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) ); + if( optionchars == NULL || + optchartype == NULL || + optcharindex == NULL ) + { + mem_allocated = false; + return false; + } + for( i = 0 ; i < max_char_options ; i++ ){ + optionchars[i] = '0'; + optchartype[i] = 0 ; + optcharindex[i] = -1 ; + } + + size = (max_usage_lines+1) * sizeof(const char*) ; + usage = (const char**) malloc( size ); + + if( usage == NULL ){ + mem_allocated = false; + return false; + } + for( i = 0 ; i < max_usage_lines ; i++ ) + usage[i] = NULL; + + return true; +} + +bool +AnyOption::doubleOptStorage() +{ + options = (const char**)realloc( options, + ((2*max_options)+1) * sizeof( const char*) ); + optiontype = (int*) realloc( optiontype , + ((2 * max_options)+1)* sizeof(int) ); + optionindex = (int*) realloc( optionindex, + ((2 * max_options)+1) * sizeof(int) ); + if( options == NULL || optiontype == NULL || optionindex == NULL ) + return false; + /* init new storage */ + for( int i = max_options ; i < 2*max_options ; i++ ){ + options[i] = NULL; + optiontype[i] = 0 ; + optionindex[i] = -1 ; + } + max_options = 2 * max_options ; + return true; +} + +bool +AnyOption::doubleCharStorage() +{ + optionchars = (char*) realloc( optionchars, + ((2*max_char_options)+1)*sizeof(char) ); + optchartype = (int*) realloc( optchartype, + ((2*max_char_options)+1)*sizeof(int) ); + optcharindex = (int*) realloc( optcharindex, + ((2*max_char_options)+1)*sizeof(int) ); + if( optionchars == NULL || + optchartype == NULL || + optcharindex == NULL ) + return false; + /* init new storage */ + for( int i = max_char_options ; i < 2*max_char_options ; i++ ){ + optionchars[i] = '0'; + optchartype[i] = 0 ; + optcharindex[i] = -1 ; + } + max_char_options = 2 * max_char_options; + return true; +} + +bool +AnyOption::doubleUsageStorage() +{ + usage = (const char**)realloc( usage, + ((2*max_usage_lines)+1) * sizeof( const char*) ); + if ( usage == NULL ) + return false; + for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ ) + usage[i] = NULL; + max_usage_lines = 2 * max_usage_lines ; + return true; + +} + + +void +AnyOption::cleanup() +{ + free (options); + free (optiontype); + free (optionindex); + free (optionchars); + free (optchartype); + free (optcharindex); + free (usage); + if( values != NULL ) + free (values); + if( new_argv != NULL ) + free (new_argv); +} + +void +AnyOption::setCommandPrefixChar( char _prefix ) +{ + opt_prefix_char = _prefix; +} + +void +AnyOption::setCommandLongPrefix( char *_prefix ) +{ + if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){ + *( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0'; + } + + strcpy (long_opt_prefix, _prefix); +} + +void +AnyOption::setFileCommentChar( char _comment ) +{ + file_delimiter_char = _comment; +} + + +void +AnyOption::setFileDelimiterChar( char _delimiter ) +{ + file_comment_char = _delimiter ; +} + +bool +AnyOption::CommandSet() +{ + return( command_set ); +} + +bool +AnyOption::FileSet() +{ + return( file_set ); +} + +void +AnyOption::noPOSIX() +{ + posix_style = false; +} + +bool +AnyOption::POSIX() +{ + return posix_style; +} + + +void +AnyOption::setVerbose() +{ + verbose = true ; +} + +void +AnyOption::printVerbose() +{ + if( verbose ) + printf("\n"); +} +void +AnyOption::printVerbose( const char *msg ) +{ + if( verbose ) + printf("%s",msg); +} + +void +AnyOption::printVerbose( char *msg ) +{ + if( verbose ) + printf("%s",msg); +} + +void +AnyOption::printVerbose( char ch ) +{ + if( verbose ) + printf("%c",ch); +} + +bool +AnyOption::hasOptions() +{ + return hasoptions; +} + +void +AnyOption::autoUsagePrint(bool _autousage) +{ + autousage = _autousage; +} + +void +AnyOption::useCommandArgs( int _argc, char **_argv ) +{ + argc = _argc; + argv = _argv; + command_set = true; + appname = argv[0]; + if(argc > 1) hasoptions = true; +} + +void +AnyOption::useFiileName( const char *_filename ) +{ + filename = _filename; + file_set = true; +} + +/* + * set methods for options + */ + +void +AnyOption::setCommandOption( const char *opt ) +{ + addOption( opt , COMMAND_OPT ); + g_value_counter++; +} + +void +AnyOption::setCommandOption( char opt ) +{ + addOption( opt , COMMAND_OPT ); + g_value_counter++; +} + +void +AnyOption::setCommandOption( const char *opt , char optchar ) +{ + addOption( opt , COMMAND_OPT ); + addOption( optchar , COMMAND_OPT ); + g_value_counter++; +} + +void +AnyOption::setCommandFlag( const char *opt ) +{ + addOption( opt , COMMAND_FLAG ); + g_value_counter++; +} + +void +AnyOption::setCommandFlag( char opt ) +{ + addOption( opt , COMMAND_FLAG ); + g_value_counter++; +} + +void +AnyOption::setCommandFlag( const char *opt , char optchar ) +{ + addOption( opt , COMMAND_FLAG ); + addOption( optchar , COMMAND_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFileOption( const char *opt ) +{ + addOption( opt , FILE_OPT ); + g_value_counter++; +} + +void +AnyOption::setFileOption( char opt ) +{ + addOption( opt , FILE_OPT ); + g_value_counter++; +} + +void +AnyOption::setFileOption( const char *opt , char optchar ) +{ + addOption( opt , FILE_OPT ); + addOption( optchar, FILE_OPT ); + g_value_counter++; +} + +void +AnyOption::setFileFlag( const char *opt ) +{ + addOption( opt , FILE_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFileFlag( char opt ) +{ + addOption( opt , FILE_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFileFlag( const char *opt , char optchar ) +{ + addOption( opt , FILE_FLAG ); + addOption( optchar , FILE_FLAG ); + g_value_counter++; +} + +void +AnyOption::setOption( const char *opt ) +{ + addOption( opt , COMMON_OPT ); + g_value_counter++; +} + +void +AnyOption::setOption( char opt ) +{ + addOption( opt , COMMON_OPT ); + g_value_counter++; +} + +void +AnyOption::setOption( const char *opt , char optchar ) +{ + addOption( opt , COMMON_OPT ); + addOption( optchar , COMMON_OPT ); + g_value_counter++; +} + +void +AnyOption::setFlag( const char *opt ) +{ + addOption( opt , COMMON_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFlag( const char opt ) +{ + addOption( opt , COMMON_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFlag( const char *opt , char optchar ) +{ + addOption( opt , COMMON_FLAG ); + addOption( optchar , COMMON_FLAG ); + g_value_counter++; +} + +void +AnyOption::addOption( const char *opt, int type ) +{ + if( option_counter >= max_options ){ + if( doubleOptStorage() == false ){ + addOptionError( opt ); + return; + } + } + options[ option_counter ] = opt ; + optiontype[ option_counter ] = type ; + optionindex[ option_counter ] = g_value_counter; + option_counter++; +} + +void +AnyOption::addOption( char opt, int type ) +{ + if( !POSIX() ){ + printVerbose("Ignoring the option character \""); + printVerbose( opt ); + printVerbose( "\" ( POSIX options are turned off )" ); + printVerbose(); + return; + } + + + if( optchar_counter >= max_char_options ){ + if( doubleCharStorage() == false ){ + addOptionError( opt ); + return; + } + } + optionchars[ optchar_counter ] = opt ; + optchartype[ optchar_counter ] = type ; + optcharindex[ optchar_counter ] = g_value_counter; + optchar_counter++; +} + +void +AnyOption::addOptionError( const char *opt ) +{ + printf("OPTIONS ERROR : Failed allocating extra memory\n"); + printf("While adding the option : \"%s\"\n",opt); + printf("Exiting.\n"); + exit(0); +} + +void +AnyOption::addOptionError( char opt ) +{ + printf("OPTIONS ERROR : Failed allocating extra memory\n"); + printf("While adding the option : \"%c\"\n",opt); + printf("Exiting.\n"); + exit(0); +} + +void +AnyOption::processOptions() +{ + if( ! valueStoreOK() ) + return; +} + +void +AnyOption::processCommandArgs(int max_args) +{ + max_legal_args = max_args; + processCommandArgs(); +} + +void +AnyOption::processCommandArgs( int _argc, char **_argv, int max_args ) +{ + max_legal_args = max_args; + processCommandArgs( _argc, _argv ); +} + +void +AnyOption::processCommandArgs( int _argc, char **_argv ) +{ + useCommandArgs( _argc, _argv ); + processCommandArgs(); +} + +void +AnyOption::processCommandArgs() +{ + if( ! ( valueStoreOK() && CommandSet() ) ) + return; + + if( max_legal_args == 0 ) + max_legal_args = argc; + new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) ); + for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */ + if( argv[i][0] == long_opt_prefix[0] && + argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */ + int match_at = parseGNU( argv[i]+2 ); /* skip -- */ + if( match_at >= 0 && i < argc-1 ) /* found match */ + setValue( options[match_at] , argv[++i] ); + }else if( argv[i][0] == opt_prefix_char ) { /* POSIX char */ + if( POSIX() ){ + char ch = parsePOSIX( argv[i]+1 );/* skip - */ + if( ch != '0' && i < argc-1 ) /* matching char */ + setValue( ch , argv[++i] ); + } else { /* treat it as GNU option with a - */ + int match_at = parseGNU( argv[i]+1 ); /* skip - */ + if( match_at >= 0 && i < argc-1 ) /* found match */ + setValue( options[match_at] , argv[++i] ); + } + }else { /* not option but an argument keep index */ + if( new_argc < max_legal_args ){ + new_argv[ new_argc ] = i ; + new_argc++; + }else{ /* ignore extra arguments */ + printVerbose( "Ignoring extra argument: " ); + printVerbose( argv[i] ); + printVerbose( ); + printAutoUsage(); + } + printVerbose( "Unknown command argument option : " ); + printVerbose( argv[i] ); + printVerbose( ); + printAutoUsage(); + } + } +} + +char +AnyOption::parsePOSIX( char* arg ) +{ + + for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ + char ch = arg[i] ; + if( matchChar(ch) ) { /* keep matching flags till an option */ + /*if last char argv[++i] is the value */ + if( i == strlen(arg)-1 ){ + return ch; + }else{/* else the rest of arg is the value */ + i++; /* skip any '=' and ' ' */ + while( arg[i] == whitespace + || arg[i] == equalsign ) + i++; + setValue( ch , arg+i ); + return '0'; + } + } + } + printVerbose( "Unknown command argument option : " ); + printVerbose( arg ); + printVerbose( ); + printAutoUsage(); + return '0'; +} + +int +AnyOption::parseGNU( char *arg ) +{ + size_t split_at = 0; + /* if has a '=' sign get value */ + for( size_t i = 0 ; i < strlen(arg) ; i++ ){ + if(arg[i] == equalsign ){ + split_at = i ; /* store index */ + i = strlen(arg); /* get out of loop */ + } + } + if( split_at > 0 ){ /* it is an option value pair */ + char* tmp = (char*) malloc( (split_at+1)*sizeof(char) ); + for( size_t i = 0 ; i < split_at ; i++ ) + tmp[i] = arg[i]; + tmp[split_at] = '\0'; + + if ( matchOpt( tmp ) >= 0 ){ + setValue( options[matchOpt(tmp)] , arg+split_at+1 ); + free (tmp); + }else{ + printVerbose( "Unknown command argument option : " ); + printVerbose( arg ); + printVerbose( ); + printAutoUsage(); + free (tmp); + return -1; + } + }else{ /* regular options with no '=' sign */ + return matchOpt(arg); + } + return -1; +} + + +int +AnyOption::matchOpt( char *opt ) +{ + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], opt ) == 0 ){ + if( optiontype[i] == COMMON_OPT || + optiontype[i] == COMMAND_OPT ) + { /* found option return index */ + return i; + }else if( optiontype[i] == COMMON_FLAG || + optiontype[i] == COMMAND_FLAG ) + { /* found flag, set it */ + setFlagOn( opt ); + return -1; + } + } + } + printVerbose( "Unknown command argument option : " ); + printVerbose( opt ) ; + printVerbose( ); + printAutoUsage(); + return -1; +} +bool +AnyOption::matchChar( char c ) +{ + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == c ) { /* found match */ + if(optchartype[i] == COMMON_OPT || + optchartype[i] == COMMAND_OPT ) + { /* an option store and stop scanning */ + return true; + }else if( optchartype[i] == COMMON_FLAG || + optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */ + setFlagOn( c ); + return false; + } + } + } + printVerbose( "Unknown command argument option : " ); + printVerbose( c ) ; + printVerbose( ); + printAutoUsage(); + return false; +} + +bool +AnyOption::valueStoreOK( ) +{ + int size= 0; + if( !set ){ + if( g_value_counter > 0 ){ + size = g_value_counter * sizeof(char*); + values = (char**)malloc( size ); + for( int i = 0 ; i < g_value_counter ; i++) + values[i] = NULL; + set = true; + } + } + return set; +} + +/* + * public get methods + */ +char* +AnyOption::getValue( const char *option ) +{ + if( !valueStoreOK() ) + return NULL; + + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], option ) == 0 ) + return values[ optionindex[i] ]; + } + return NULL; +} + +bool +AnyOption::getFlag( const char *option ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], option ) == 0 ) + return findFlag( values[ optionindex[i] ] ); + } + return false; +} + +char* +AnyOption::getValue( char option ) +{ + if( !valueStoreOK() ) + return NULL; + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == option ) + return values[ optcharindex[i] ]; + } + return NULL; +} + +bool +AnyOption::getFlag( char option ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == option ) + return findFlag( values[ optcharindex[i] ] ) ; + } + return false; +} + +bool +AnyOption::findFlag( char* val ) +{ + if( val == NULL ) + return false; + + if( strcmp( TRUE_FLAG , val ) == 0 ) + return true; + + return false; +} + +/* + * private set methods + */ +bool +AnyOption::setValue( const char *option , char *value ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], option ) == 0 ){ + size_t length = (strlen(value)+1)*sizeof(char); + values[ optionindex[i] ] = (char*) malloc(length); + strncpy( values[ optionindex[i] ], value, length ); + return true; + } + } + return false; +} + +bool +AnyOption::setFlagOn( const char *option ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], option ) == 0 ){ + size_t length = (strlen(TRUE_FLAG)+1)*sizeof(char); + values[ optionindex[i] ] = (char*) malloc(length); + strncpy( values[ optionindex[i] ], TRUE_FLAG, length ); + return true; + } + } + return false; +} + +bool +AnyOption::setValue( char option , char *value ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == option ){ + size_t length = (strlen(value)+1)*sizeof(char); + values[ optcharindex[i] ] = (char*) malloc(length); + strncpy( values[ optcharindex[i] ], value, length ); + return true; + } + } + return false; +} + +bool +AnyOption::setFlagOn( char option ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == option ){ + size_t length = (strlen(TRUE_FLAG)+1)*sizeof(char); + values[ optcharindex[i] ] = (char*) malloc(length); + strncpy( values[ optcharindex[i] ] , TRUE_FLAG, length ); + return true; + } + } + return false; +} + + +int +AnyOption::getArgc( ) +{ + return new_argc; +} + +char* +AnyOption::getArgv( int index ) +{ + if( index < new_argc ){ + return ( argv[ new_argv[ index ] ] ); + } + return NULL; +} + +/* dotfile sub routines */ + +bool +AnyOption::processFile() +{ + if( ! (valueStoreOK() && FileSet()) ) + return false; + return ( consumeFile(readFile()) ); +} + +bool +AnyOption::processFile( const char *filename ) +{ + useFiileName(filename ); + return ( processFile() ); +} + +char* +AnyOption::readFile() +{ + return ( readFile(filename) ); +} + +/* + * read the file contents to a character buffer + */ + +char* +AnyOption::readFile( const char* fname ) +{ + char *buffer = NULL; + FILE *f = fopen(fname,"r"); + long length = 0; + if (f) + { + fseek(f,0,SEEK_END); + length = ftell(f); + } + buffer = (char*) malloc((length+1)*sizeof(char)); + if (f) + { + fseek(f,0,SEEK_SET); + fread(buffer,sizeof(char),length,f); + fclose(f); + } + buffer[length] = '\0'; + return buffer; +} + +/* + * scans a char* buffer for lines that does not + * start with the specified comment character. + */ +bool +AnyOption::consumeFile( char *buffer ) +{ + + if( buffer == NULL ) + return false; + + char *cursor = buffer;/* preserve the ptr */ + char *pline = NULL ; + int linelength = 0; + bool newline = true; + for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){ + if( *cursor == endofline ) { /* end of line */ + if( pline != NULL ) /* valid line */ + processLine( pline, linelength ); + pline = NULL; + newline = true; + }else if( newline ){ /* start of line */ + newline = false; + if( (*cursor != comment ) ){ /* not a comment */ + pline = cursor ; + linelength = 0 ; + } + } + cursor++; /* keep moving */ + linelength++; + } + free (buffer); + return true; +} + + +/* + * find a valid type value pair separated by a delimiter + * character and pass it to valuePairs() + * any line which is not valid will be considered a value + * and will get passed on to justValue() + * + * assuming delimiter is ':' the behaviour will be, + * + * width:10 - valid pair valuePairs( width, 10 ); + * width : 10 - valid pair valuepairs( width, 10 ); + * + * :::: - not valid + * width - not valid + * :10 - not valid + * width: - not valid + * :: - not valid + * : - not valid + * + */ + +void +AnyOption::processLine( char *theline, int length ) +{ + bool found = false; + char *pline = (char*) malloc( (length+1)*sizeof(char) ); + for( int i = 0 ; i < length ; i ++ ) + pline[i]= *(theline++); + pline[length] = nullterminate; + char *cursor = pline ; /* preserve the ptr */ + if( *cursor == delimiter || *(cursor+length-1) == delimiter ){ + justValue( pline );/* line with start/end delimiter */ + }else{ + for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */ + if( *cursor == delimiter ){ + *(cursor-1) = nullterminate; /* two strings */ + found = true; + valuePairs( pline , cursor+1 ); + } + cursor++; + } + cursor++; + if( !found ) /* not a pair */ + justValue( pline ); + } + free (pline); +} + +/* + * removes trailing and preceeding whitespaces from a string + */ +char* +AnyOption::chomp( char *str ) +{ + while( *str == whitespace ) + str++; + char *end = str+strlen(str)-1; + while( *end == whitespace ) + end--; + *(end+1) = nullterminate; + return str; +} + +void +AnyOption::valuePairs( char *type, char *value ) +{ + if ( strlen(chomp(type)) == 1 ){ /* this is a char option */ + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == type[0] ){ /* match */ + if( optchartype[i] == COMMON_OPT || + optchartype[i] == FILE_OPT ) + { + setValue( type[0] , chomp(value) ); + return; + } + } + } + } + /* if no char options matched */ + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], type ) == 0 ){ /* match */ + if( optiontype[i] == COMMON_OPT || + optiontype[i] == FILE_OPT ) + { + setValue( type , chomp(value) ); + return; + } + } + } + printVerbose( "Unknown option in resourcefile : " ); + printVerbose( type ); + printVerbose( ); +} + +void +AnyOption::justValue( char *type ) +{ + + if ( strlen(chomp(type)) == 1 ){ /* this is a char option */ + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == type[0] ){ /* match */ + if( optchartype[i] == COMMON_FLAG || + optchartype[i] == FILE_FLAG ) + { + setFlagOn( type[0] ); + return; + } + } + } + } + /* if no char options matched */ + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], type ) == 0 ){ /* match */ + if( optiontype[i] == COMMON_FLAG || + optiontype[i] == FILE_FLAG ) + { + setFlagOn( type ); + return; + } + } + } + printVerbose( "Unknown option in resourcefile : " ); + printVerbose( type ); + printVerbose( ); +} + +/* + * usage and help + */ + + +void +AnyOption::printAutoUsage() +{ + if( autousage ) printUsage(); +} + +void +AnyOption::printUsage() +{ + + if( once ) { + once = false ; + printf("\n"); + for( int i = 0 ; i < usage_lines ; i++ ) + printf("%s\n",usage[i]); + printf("\n"); + } +} + + +void +AnyOption::addUsage( const char *line ) +{ + if( usage_lines >= max_usage_lines ){ + if( doubleUsageStorage() == false ){ + addUsageError( line ); + exit(1); + } + } + usage[ usage_lines ] = line ; + usage_lines++; +} + +void +AnyOption::addUsageError( const char *line ) +{ + printf("\nOPTIONS ERROR : Failed allocating extra memory\n"); + printf("While adding the usage/help : \"%s\"\n",line); + printf("Exiting.\n"); + exit(0); +} diff --git a/bin/wav2png/anyoption.h b/bin/wav2png/anyoption.h new file mode 100755 index 0000000..d751d47 --- /dev/null +++ b/bin/wav2png/anyoption.h @@ -0,0 +1,261 @@ +#ifndef _ANYOPTION_H_ +#define _ANYOPTION_H_ + +#define COMMON_OPT 1 +#define COMMAND_OPT 2 +#define FILE_OPT 3 +#define COMMON_FLAG 4 +#define COMMAND_FLAG 5 +#define FILE_FLAG 6 + +#define COMMAND_OPTION_TYPE 1 +#define COMMAND_FLAG_TYPE 2 +#define FILE_OPTION_TYPE 3 +#define FILE_FLAG_TYPE 4 +#define UNKNOWN_TYPE 5 + +#define DEFAULT_MAXOPTS 10 +#define MAX_LONG_PREFIX_LENGTH 2 + +#define DEFAULT_MAXUSAGE 3 +#define DEFAULT_MAXHELP 10 + +#define TRUE_FLAG "true" + +class AnyOption +{ + +public: /* the public interface */ + AnyOption(); + AnyOption(int maxoptions ); + AnyOption(int maxoptions , int maxcharoptions); + ~AnyOption(); + + /* + * following set methods specifies the + * special characters and delimiters + * if not set traditional defaults will be used + */ + + void setCommandPrefixChar( char _prefix ); /* '-' in "-w" */ + void setCommandLongPrefix( char *_prefix ); /* '--' in "--width" */ + void setFileCommentChar( char _comment ); /* '#' in shellscripts */ + void setFileDelimiterChar( char _delimiter );/* ':' in "width : 100" */ + + /* + * provide the input for the options + * like argv[] for commndline and the + * option file name to use; + */ + + void useCommandArgs( int _argc, char **_argv ); + void useFiileName( const char *_filename ); + + /* + * turn off the POSIX style options + * this means anything starting with a '-' or "--" + * will be considered a valid option + * which alo means you cannot add a bunch of + * POIX options chars together like "-lr" for "-l -r" + * + */ + + void noPOSIX(); + + /* + * prints warning verbose if you set anything wrong + */ + void setVerbose(); + + + /* + * there are two types of options + * + * Option - has an associated value ( -w 100 ) + * Flag - no value, just a boolean flag ( -nogui ) + * + * the options can be either a string ( GNU style ) + * or a character ( traditional POSIX style ) + * or both ( --width, -w ) + * + * the options can be common to the commandline and + * the optionfile, or can belong only to either of + * commandline and optionfile + * + * following set methods, handle all the aboove + * cases of options. + */ + + /* options comman to command line and option file */ + void setOption( const char *opt_string ); + void setOption( char opt_char ); + void setOption( const char *opt_string , char opt_char ); + void setFlag( const char *opt_string ); + void setFlag( char opt_char ); + void setFlag( const char *opt_string , char opt_char ); + + /* options read from commandline only */ + void setCommandOption( const char *opt_string ); + void setCommandOption( char opt_char ); + void setCommandOption( const char *opt_string , char opt_char ); + void setCommandFlag( const char *opt_string ); + void setCommandFlag( char opt_char ); + void setCommandFlag( const char *opt_string , char opt_char ); + + /* options read from an option file only */ + void setFileOption( const char *opt_string ); + void setFileOption( char opt_char ); + void setFileOption( const char *opt_string , char opt_char ); + void setFileFlag( const char *opt_string ); + void setFileFlag( char opt_char ); + void setFileFlag( const char *opt_string , char opt_char ); + + /* + * process the options, registerd using + * useCommandArgs() and useFileName(); + */ + void processOptions(); + void processCommandArgs(); + void processCommandArgs( int max_args ); + bool processFile(); + + /* + * process the specified options + */ + void processCommandArgs( int _argc, char **_argv ); + void processCommandArgs( int _argc, char **_argv, int max_args ); + bool processFile( const char *_filename ); + + /* + * get the value of the options + * will return NULL if no value is set + */ + char *getValue( const char *_option ); + bool getFlag( const char *_option ); + char *getValue( char _optchar ); + bool getFlag( char _optchar ); + + /* + * Print Usage + */ + void printUsage(); + void printAutoUsage(); + void addUsage( const char *line ); + void printHelp(); + /* print auto usage printing for unknown options or flag */ + void autoUsagePrint(bool flag); + + /* + * get the argument count and arguments sans the options + */ + int getArgc(); + char* getArgv( int index ); + bool hasOptions(); + +private: /* the hidden data structure */ + int argc; /* commandline arg count */ + char **argv; /* commndline args */ + const char* filename; /* the option file */ + char* appname; /* the application name from argv[0] */ + + int *new_argv; /* arguments sans options (index to argv) */ + int new_argc; /* argument count sans the options */ + int max_legal_args; /* ignore extra arguments */ + + + /* option strings storage + indexing */ + int max_options; /* maximum number of options */ + const char **options; /* storage */ + int *optiontype; /* type - common, command, file */ + int *optionindex; /* index into value storage */ + int option_counter; /* counter for added options */ + + /* option chars storage + indexing */ + int max_char_options; /* maximum number options */ + char *optionchars; /* storage */ + int *optchartype; /* type - common, command, file */ + int *optcharindex; /* index into value storage */ + int optchar_counter; /* counter for added options */ + + /* values */ + char **values; /* common value storage */ + int g_value_counter; /* globally updated value index LAME! */ + + /* help and usage */ + const char **usage; /* usage */ + int max_usage_lines; /* max usage lines reseverd */ + int usage_lines; /* number of usage lines */ + + bool command_set; /* if argc/argv were provided */ + bool file_set; /* if a filename was provided */ + bool mem_allocated; /* if memory allocated in init() */ + bool posix_style; /* enables to turn off POSIX style options */ + bool verbose; /* silent|verbose */ + bool print_usage; /* usage verbose */ + bool print_help; /* help verbose */ + + char opt_prefix_char; /* '-' in "-w" */ + char long_opt_prefix[MAX_LONG_PREFIX_LENGTH + 1]; /* '--' in "--width" */ + char file_delimiter_char; /* ':' in width : 100 */ + char file_comment_char; /* '#' in "#this is a comment" */ + char equalsign; + char comment; + char delimiter; + char endofline; + char whitespace; + char nullterminate; + + bool set; //was static member + bool once; //was static member + + bool hasoptions; + bool autousage; + +private: /* the hidden utils */ + void init(); + void init(int maxopt, int maxcharopt ); + bool alloc(); + void cleanup(); + bool valueStoreOK(); + + /* grow storage arrays as required */ + bool doubleOptStorage(); + bool doubleCharStorage(); + bool doubleUsageStorage(); + + bool setValue( const char *option , char *value ); + bool setFlagOn( const char *option ); + bool setValue( char optchar , char *value); + bool setFlagOn( char optchar ); + + void addOption( const char* option , int type ); + void addOption( char optchar , int type ); + void addOptionError( const char *opt); + void addOptionError( char opt); + bool findFlag( char* value ); + void addUsageError( const char *line ); + bool CommandSet(); + bool FileSet(); + bool POSIX(); + + char parsePOSIX( char* arg ); + int parseGNU( char *arg ); + bool matchChar( char c ); + int matchOpt( char *opt ); + + /* dot file methods */ + char *readFile(); + char *readFile( const char* fname ); + bool consumeFile( char *buffer ); + void processLine( char *theline, int length ); + char *chomp( char *str ); + void valuePairs( char *type, char *value ); + void justValue( char *value ); + + void printVerbose( const char *msg ); + void printVerbose( char *msg ); + void printVerbose( char ch ); + void printVerbose( ); +}; + +#endif /* ! _ANYOPTION_H_ */ diff --git a/bin/wav2png/gpl.txt b/bin/wav2png/gpl.txt new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/bin/wav2png/gpl.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/bin/wav2png/main.cpp b/bin/wav2png/main.cpp new file mode 100644 index 0000000..470fb31 --- /dev/null +++ b/bin/wav2png/main.cpp @@ -0,0 +1,813 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * +*/ + +/* Created by Bram de Jong for MTG http://www.mtg.upf.edu/ + * + * You will need anyoption ( http://www.hackorama.com/anyoption/ ) and libsndfile + * ( http://www.mega-nerd.com/libsndfile/ ) and GD2 (http://www.boutell.com/gd/) + * to build this program. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sndfile.h" + +#ifdef WIN32 +#include "gdwin32/gd.h" +#else +#include "gd.h" +#endif +#include +using namespace std; + +#include "anyoption.h" + +typedef std::vector ColorVector; + +long hex2dec(char h) +{ + switch(h) + { + case 'a': return 10; + case 'b': return 11; + case 'c': return 12; + case 'd': return 13; + case 'e': return 14; + case 'f': return 15; + default: + { + char tmp = h - '0'; + if(tmp >= 0 && tmp <= 9) + return tmp; + else + return 0; + } + } +} + +// string as a HEX HTML value 000000 (black) FF0000 (red) etc... +long string2color(std::string s, gdImagePtr image) +{ + long r,g,b; + if(s.length() == 6) + { + std::transform(s.begin(), s.end(), s.begin(), (int (*)(int)) tolower); + r = (hex2dec(s.at(0))<<4) + hex2dec(s.at(1)); + g = (hex2dec(s.at(2))<<4) + hex2dec(s.at(3)); + b = (hex2dec(s.at(4))<<4) + hex2dec(s.at(5)); + } + else + { + r = g = b = 0; + } + + return gdImageColorAllocate(image, r, g, b); +} + +void HSVtoRGB( float &r, float &g, float &b, float h, float s, float v ) +{ + int i; + float f, p, q, t; + + if( s == 0 ) { + // achromatic (grey) + r = g = b = v; + return; + } + + h /= 60; // sector 0 to 5 + i = (int)floor( h ); + f = h - i; // factorial part of h + p = v * ( 1 - s ); + q = v * ( 1 - s * f ); + t = v * ( 1 - s * ( 1 - f ) ); + + switch( i ) { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + default: // case 5: + r = v; + g = p; + b = q; + break; + } + +} + +/* The hue value H runs from 0 to 360º. The saturation S is the degree of strength +or purity and is from 0 to 1. Purity is how much white is added to the color, so S=1 +makes the purest color (no white). Brightness V also ranges from 0 to 1, where 0 is the black.*/ +// x in [0..1] +long float2color(float value, gdImagePtr image) +{ + if(value > 1.f) value = 1.f; + else if(value < 0.f) value = 0.f; + + float h; + float s; + float v; + + h = (1.f-value)*360.0; + s = 0.8f; + v = 1.f; + + float r,g,b; + + HSVtoRGB(r,g,b,h,s,v); + + return gdImageColorAllocate(image, (int)(r*255), (int)(g*255), (int)(b*255)); +} + + +void getPeakSamplesInBlock(float *samples, long count, long channels, float &first, float &second, bool verbose) +{ + if (verbose) + std::cout << "\tprocessing " << count << " samples, " << channels << " channels" << std::endl; + + if(count < 1) + { + first = second = 0.f; + if (verbose) + std::cout << "\texiting as there's no samples" << std::endl; + return; + } + else if(count < 2) + { + first = second = samples[0]; + if (verbose) + std::cout << "\texiting as there's less than two samples" << std::endl; + return; + return; + } + + float tlow = samples[0]; + float thigh = samples[0]; + long high_i = 0; + long low_i = 0; + + for(long i=channels;i thigh) + { + thigh = val; + high_i = i; + } + + if(val < tlow) + { + tlow = val; + low_i = i; + } + } + + if (high_i > low_i) + { + first = tlow; + second = thigh; + } + else + { + first = thigh; + second = tlow; + } + + if (verbose) + std::cout << "\tprocessing: done" << std::endl; +} + +bool getPositionAndValue(std::string line, long &position, float &value, long positionIncrement = 0) +{ + long pos; + float val; + int good; + + good = sscanf(line.c_str(),"%ld,%f",&pos,&val); + + if(good == 2 && pos >= 0) + { + position = pos; + value = val; + return true; + } + + good = sscanf(line.c_str(),"%f",&val); + + if(good == 1 && good != EOF) + { + position += positionIncrement; + value = val; + return true; + } + + return false; +} + +bool getPositionAndColor(std::string line, long &position, long &color, gdImagePtr image, long positionIncrement = 0) +{ + long pos; + char colorString[6]; + int good; + + good = sscanf(line.c_str(),"%ld,#%6s",&pos,colorString); + + if(good == 2 && pos >= 0) + { + position = pos; + color = string2color(colorString,image); + return true; + } + + good = sscanf(line.c_str(),"#%6s",colorString); + + if(good == 1) + { + position += positionIncrement; + color = string2color(colorString,image); + return true; + } + + return false; +} + +ColorVector getColorValues(std::string filename, float samplesPerPixel, long width, gdImagePtr image) +{ + ColorVector colors; + + char buffer[256]; + std::string line; + std::ifstream infile; + infile.open(filename.c_str(), std::ifstream::in); + + float value = 0.f; + long color = 0; + long position = 0; + bool inputGood = true; + bool colorFileUsesColors = false; + long stepsize = 0; + std::vector values; + + if(infile.good()) + { + infile.getline(buffer,256); + line = buffer; + + int success = sscanf(line.c_str(),"[%ld]",&stepsize); + if(success == 1) + { + if(infile.good()) + { + infile.getline(buffer,256); + line = buffer; + } + else + { + return colors; + } + } + else + { + stepsize = 0; + } + + long hasHasChar = std::string(line).find("#"); + + if(hasHasChar > 0) + { + colorFileUsesColors = true; + } + } + else + { + return colors; + } + + if(colorFileUsesColors) + inputGood = getPositionAndColor(line,position,color,image,stepsize); + else + inputGood = getPositionAndValue(line,position,value,stepsize); + + float nextValue = value; + long nextColor = color; + + for(long i=0;i= position && inputGood) + { + color = nextColor; + value = nextValue; + + if(infile.good()) + { + infile.getline(buffer,256); + line = buffer; + + if(colorFileUsesColors) + { + inputGood = getPositionAndColor(line,position,nextColor,image,stepsize); + } + else + { + inputGood = getPositionAndValue(line,position,nextValue,stepsize); + } + } + else + { + inputGood = false; + } + } + + if(colorFileUsesColors) + colors.push_back(color); + else + values.push_back(value); + + } + + infile.close(); + + if(colorFileUsesColors) + return colors; + + if(values.size()) + { + int type = 1; + + switch(type) + { + case 0: + { + for(unsigned long k=0;k maxValue) + maxValue = values[j]; + + if(values[j] < minValue) + minValue = values[j]; + } + + if(minValue != maxValue) + { + for(unsigned long k=0;k (" << x2 << "," << y2 << "), color = " << std::hex << color << " image : " << image << std::dec << std::endl; + + gdImageLine(image,x1,y1,x2,y2,color); + oldX = x; + oldY = y; + + if (verbose) + std::cout << "\tdrawing line: done" << std::endl; +} + +int main(int argc, char* argv[]) +{ + AnyOption *opt = new AnyOption(); + + opt->setOption("input",'i'); + opt->setOption("width",'w'); + opt->setOption("height",'h'); + opt->setOption("output",'o'); + opt->setOption("colorfile",'c'); + opt->setOption("linecolor",'l'); + opt->setOption("backgroundcolor",'b'); + opt->setOption("zerocolor",'z'); + opt->setOption("padding",'p'); + opt->setOption("verbose",'v'); + + opt->setOption("type",'t'); + opt->setOption("quality",'q'); + + opt->addUsage( "Usage: wav2png --input wavefile.wav" ); + opt->addUsage( "\t" ); + opt->addUsage( "\tAdditional options: --width 300 --height 151 --output image.jpg --linecolor ff00aa --backgroundcolor 002222 --zerocolor ff0000 --colorfile filename --padding 2 --verbose true --type jpeg --quality 85" ); + opt->addUsage( "\tShort command line switches: -i -w -h -o -l -b -z -c -o"); + opt->addUsage( "\t" ); + opt->addUsage( "\twidth: width of PNG (default: 300)"); + opt->addUsage( "\theight: height of PNG (default: 151)"); + opt->addUsage( "\toutput: output filename (default: input filename with '.png' appended)"); + opt->addUsage( "\tlinecolor: color of waveform lines (default: 323232)"); + opt->addUsage( "\tbackgroundcolor: color of background (default: FFFFFF)"); + opt->addUsage( "\tzerocolor: color of line through zero (default: 960000)"); + opt->addUsage( "\t\tcolors are defined like HTML colors in hex"); + opt->addUsage( "\tcolorfile: file with (samplePosition,value) pairs for coloring"); + opt->addUsage( "\tpadding: padding around the edge"); + opt->addUsage( "\tverbose: true or false"); + opt->addUsage( "\ttype: png or jpeg"); + opt->addUsage( "\tquality: jpeg quality between 0 and 100"); + + opt->processCommandArgs( argc, argv ); + + std::string inputFilename; + std::string outputFilename; + + bool verbose = false; + if( opt->getValue("verbose") != NULL && strcmp(opt->getValue("verbose"), "true") == 0) + verbose = true; + + if (verbose) + std::cout << "verbose true" << std::endl; + + if (verbose) std::cout << "parsing options" << std::endl; + + long quality = -1; + if ( opt->getValue("quality") != NULL ) + quality = atoi(opt->getValue("quality")); + + if (verbose) + std::cout << "quality " << quality << std::endl; + + bool isPng = true; + if ( opt->getValue("type") != NULL && strcmp(opt->getValue("type"), "jpeg") == 0) + isPng = false; + + if (verbose) + std::cout << "isPng " << (isPng?"true":"false") << std::endl; + + if( opt->getValue("input") != NULL ) + { + inputFilename = opt->getValue("input"); + } + else + { + opt->printUsage(); + return 1; + } + + if (verbose) + std::cout << "input filename " << inputFilename << std::endl; + + if( opt->getValue("output") != NULL ) + { + outputFilename = opt->getValue("output"); + } + else + { + outputFilename = inputFilename + std::string(".png"); + } + + if (verbose) + std::cout << "output filename " << outputFilename << std::endl; + + long width = 354; + if( opt->getValue("width") != NULL ) + { + width = atoi(opt->getValue("width")); + + if(width <= 0) + return 1; + } + + + if (verbose) + std::cout << "width " << width << std::endl; + + long height = 165; + if( opt->getValue("height") != NULL ) + { + height = atoi(opt->getValue("height")); + + if(height <= 0) + return 1; + } + + if (verbose) + std::cout << "height " << height << std::endl; + + long padding = 2; + if( opt->getValue("padding") != NULL ) + { + padding = atoi(opt->getValue("padding")); + + if(padding<0) + return 1; + } + + if (verbose) + std::cout << "padding " << padding << std::endl; + + std::string colorFilename(""); + if( opt->getValue("colorfile") != NULL ) + { + colorFilename = std::string(opt->getValue("colorfile")); + } + + if (verbose) + std::cout << "color filename " << colorFilename << std::endl; + + if (verbose) std::cout << "opening wave file" << std::endl; + + SNDFILE *infile; + SF_INFO sfinfo ; + + // open the soundfile + if(!(infile = sf_open (inputFilename.c_str(), SFM_READ, &sfinfo))) + { + return 1; + }; + + if(sfinfo.frames == 0 || sfinfo.channels == 0) + { + sf_close(infile); + return 1; + } + + float samplesPerPixel = (float) sfinfo.frames / (float) width; + long maxReadSize = (long)ceilf(samplesPerPixel); + + if (verbose) std::cout << "samps/pixel "<< samplesPerPixel << std::endl; + + if (verbose) std::cout << "allocating image..." << std::endl; + gdImagePtr image = gdImageCreateTrueColor(width+padding*2, height+padding*2); + if (verbose) std::cout << "done..." << std::endl; + + ColorVector colors; + if(colorFilename != "") + { + if (verbose) std::cout << "getting color values" << std::endl; + colors = getColorValues(colorFilename,samplesPerPixel,width,image); + } + + + long backgroundColor; + long lineColor; + long zeroColor; + + if (verbose) std::cout << "parsing more options" << std::endl; + + if( opt->getValue("linecolor") != NULL ) + lineColor = string2color(opt->getValue("linecolor"),image); + else + lineColor = string2color("FFFFFF",image); + + if (verbose) + std::cout << "line color " << std::hex << lineColor << std::dec << std::endl; + + if( opt->getValue("backgroundcolor") != NULL ) + backgroundColor = string2color(opt->getValue("backgroundcolor"),image); + else + backgroundColor = string2color("000000",image); + + if (verbose) + std::cout << "background color " << std::hex << backgroundColor << std::dec << std::endl; + + if( opt->getValue("zerocolor") != NULL ) + zeroColor = string2color(opt->getValue("zerocolor"),image); + else + zeroColor = string2color("960000",image); + + if (verbose) + std::cout << "zero color " << std::hex << zeroColor << std::dec << std::endl; + + gdImageFilledRectangle(image,0,0,width+padding*2-1,height+padding*2-1, backgroundColor); + gdImageSetAntiAliased(image,lineColor); + moveTo(0,height*0.5f); + + + // sampling data + long dataSize = sfinfo.channels * maxReadSize; + if (verbose) std::cout << "allocating " << dataSize << " bytes" << std::endl; + float *data = new float[dataSize]; + if (verbose) std::cout << "allocated..." << std::endl; + + float first = 0, second = 0; + + // we need at least width samples to do something usefull... + for(long i=0;i maxReadSize) + { + blockSize = maxReadSize; + } + else if(blockSize < 1) + { + lineTo(image, (float)i, height * 0.5f * (1.f - first), gdAntiAliased, padding, width, height, verbose); + lineTo(image, (float)i, height * 0.5f * (1.f - second), gdAntiAliased, padding, width, height, verbose); + continue; + } + + if (verbose && !(i % std::max(width/20,(long)1))) + std::cout << "\treading wave file" << std::endl; + + long readcount = sf_readf_float(infile, data, blockSize); + + if(readcount == 0) + { + if (verbose) + std::cout << "\tthis is probably a broken wave file... It reported more samples than it has!" << std::endl; + break; + } + if(readcount < blockSize) + { + if (verbose) + std::cout << "\twe just read a non-complete block..." << std::endl; + } + + if (verbose && !(i % std::max(width/20,(long)1))) + std::cout << "\tread OK" << std::endl; + + if (verbose && !(i % std::max(width/20,(long)1))) + std::cout << "\tgetting sample peaks" << std::endl; + + getPeakSamplesInBlock(data, readcount, sfinfo.channels, first, second, verbose); + + if (verbose && !(i % std::max(width/20,(long)1))) + std::cout << "\tpeak OK" << std::endl; + + if(first != second) + { + lineTo(image, (float)i, height * 0.5f * (1.f - first), gdAntiAliased, padding, width, height, verbose); + lineTo(image, (float)i, height * 0.5f * (1.f - second), gdAntiAliased, padding, width, height, verbose); + } + else + { + lineTo(image, (float)i, height * 0.5f * (1.f - first), gdAntiAliased, padding, width, height, verbose); + } + } + + if (verbose) + std::cout << "closing sound file" << std::endl; + + sf_close (infile) ; + + if (verbose) + std::cout << "closed" << std::endl; + + + if (verbose) + std::cout << "generating GD image" << std::endl; + + if (verbose) + std::cout << "\topening output file" << std::endl; + + FILE *outputFile = fopen(outputFilename.c_str(),"wb"); + + if (verbose) + std::cout << "\tgdImageCreate" << std::endl; + + if (isPng) + gdImagePng(image,outputFile); + else + gdImageJpeg(image,outputFile,quality); + + if (verbose) + std::cout << "\tclose output file" << std::endl; + + fclose(outputFile); + + if (verbose) + std::cout << "\tgdImageDestroy" << std::endl; + + gdImageDestroy(image); + + if (verbose) + std::cout << "deleting data" << std::endl; + + delete data; + + if (verbose) + std::cout << "all fine and dandy, exiting" << std::endl; + + return 0; +} diff --git a/config/moviemasher.banner b/config/aws/moviemasher.banner similarity index 100% rename from config/moviemasher.banner rename to config/aws/moviemasher.banner diff --git a/config/moviemasher.upstart b/config/aws/moviemasher.upstart similarity index 100% rename from config/moviemasher.upstart rename to config/aws/moviemasher.upstart diff --git a/config/config.yml b/config/config.yml index 9197639..4555e71 100644 --- a/config/config.yml +++ b/config/config.yml @@ -1,11 +1,15 @@ - # chmod_directory_new: 0775 - # error_directory: - # render_keep: false - # log_level: info - # process_queues_seconds: 55 - # queue_wait_time_seconds: 2 -download_directory_size: 3 -download_directory: /tmp/moviemasher/cache -log_directory: /var/log/moviemasher -queue_directory: /tmp/moviemasher/queue -render_directory: /tmp/moviemasher/temporary +--- +:chmod_directory_new: '0775' +:download_directory: /tmp/moviemasher/cache +:download_bytes: 0M +:error_directory: +:queue_url: +:log_directory: /var/log/moviemasher +:verbose: info +:process_seconds: 55 +:queue_directory: /tmp/moviemasher/queue +:queue_wait_seconds: 2 +:render_directory: /tmp/moviemasher/temporary +:render_save: false +:aws_access_key_id: +:aws_secret_access_key: diff --git a/config/docker/config.yml b/config/docker/config.yml new file mode 100644 index 0000000..2eb65f3 --- /dev/null +++ b/config/docker/config.yml @@ -0,0 +1,7 @@ +--- +:download_directory: /mnt/download +:download_bytes: 100M +:log_directory: /mnt/log +:queue_directory: /mnt/queue +:render_directory: /mnt/render +:process_seconds: -2 diff --git a/config/docker/entrypoint.rb b/config/docker/entrypoint.rb new file mode 100755 index 0000000..19c0dab --- /dev/null +++ b/config/docker/entrypoint.rb @@ -0,0 +1,23 @@ +#!/usr/local/bin/ruby +command = ARGV.first +commands = { + :process => 0, + :process_one => -1, + :process_all => -2, + :process_loop => -3, + :moviemasher => false, +} +exec(ARGV.join ' ') unless commands.include? command.to_sym +ARGV.shift # remove command +require '/mnt/moviemasher.rb/lib/moviemasher' +config = YAML::load(File.open(ENV['MOVIEMASHER_CONFIG'] || '/mnt/moviemasher.rb/config/docker/config.yml')) +configuration = MovieMasher::Configuration.parse(ARGV, config, command) +if configuration.is_a? String + puts configuration +else + MovieMasher.configure configuration + puts MovieMasher.hello + MovieMasher.process_jobs ARGV + MovieMasher.process_queues commands[command.to_sym] + puts MovieMasher.goodbye +end diff --git a/doc/README_md.html b/doc/Documentation_md.html similarity index 60% rename from doc/README_md.html rename to doc/Documentation_md.html index 0f2738c..a7b1904 100644 --- a/doc/README_md.html +++ b/doc/Documentation_md.html @@ -4,7 +4,7 @@ -README - RDoc Documentation +Documentation - RDoc Documentation @@ -49,14 +49,9 @@

Table of Contents

@@ -68,9 +63,7 @@

Pages

@@ -96,6 +89,8 @@

Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -156,6 +151,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -164,8 +161,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -205,80 +200,38 @@

    Class and Module Index

    - moviemasher.js | angular-moviemasher -| moviemasher.rb

    +| moviemasher.rb

    Ruby library for mashing up video, images and audio utilizing FFmpeg and Ecasound

    moviemasher.rb

    +
    + +

    RDoc Documentation

    -

    Use moviemasher.rb to encode mashups of video, audio, and images from a -JSON formatted job description. A job specifies multiple media inputs to be -encoded together into one or more outputs, as well as where to find the -inputs and where to place the outputs.

    +
    Core Classes/Modules
    -

    The project aims to take the complexity out of describing common -audio/video editing operations to command line programs, which handle the -low level transcoding operations. The MovieMasher class turns your job into a series -of commands and then manages their execution.

    - -

    As part of job processing it can download media inputs from remote hosts -and upload media outputs as well. Using the same mechanisms it can also -trigger callbacks as a job is started, during its processing and when -it's completed so that external systems can be alerted.

    - -

    The project includes a rake task that can be routinely called to watch a -folder for job description files, as well as an example crontab entry that -calls it. Recall that ruby scripts run from cron lack your user's -environmental variables, so you'll probably need to edit the paths to -binary directories in the entry to match your system.

    - -

    AWS Integration

    - -

    There are optional configuration settings that support two specific Amazon -Web Services offerings: S3 for media storage and SQS for job queueing. If -set to use an SQS queue then it will be polled as part of the folder -watching process for job files. The ruby aws-sdk is utilized to interface -with SQS, so access key details can be provided in the configuration or -environmental variables or in a role if deployed on an EC2 instance.

    - -

    Similarly, aws-sdk is utilized for S3 interactions so if access key details -are present then buckets can be used either as sources for media inputs or -destinations for media outputs within job descriptions. These are -authenticated requests, so the buckets do not have to be public.

    - -

    Additionally, the Movie Masher AMI is available in Marketplace and includes -moviemasher.rb and all supporting applications. When launched it looks for -user data supplied in JSON format and merges it into the default -configuration, so it's possible to supply SQS options on startup. The -cron job described above is installed, so a configured SQS queue will -immediately start being polled for jobs. Otherwise the instance will start -up apache to serve the angular-moviemasher project, preconfigured to -utilize the local moviemasher.rb process (the instance id acts as a shared -password).

    - -

    Basic Usage

    +
    Core Usage
        require_relative 'lib/moviemasher.rb'
         job = { :inputs => [], :base_source => {}, :outputs => [], :destination => {} }
    @@ -318,111 +271,10 @@ 

    Basic Usage¶< drawtext. That last one relies on font media, the last of the modular types.

    -

    How to Install

    -
    1. -

      install ffmpeg, ecasound, sox and du programs

      -
    2. -

      install ruby and builder

      -
    3. -

      bundle install in project directory installs required gems -from Gemfile

      -
    4. -

      edit config/config.yml configuration file to match paths on system and -configure logging/debugging options

      -
    5. -

      rake moviemasher:process_queues searches watch folder and -optional SQS queue for jobs

      -
    6. -

      optionally install calling crontab entry found at config/moviemasher.cron -after checking binary paths in it

      -
    +

    To regenerate this documentation cd to project +directory and execute:

    -

    Requirements

    -
    • -

      ffmpeg with ffprobe

      -
    • -

      ecasound

      -
    • -

      sox

      -
    • -

      du

      -
    • -

      builder gem

      -
    • -

      require_all gem

      -
    • -

      json gem

      -
    • -

      uuid gem

      -
    • -

      mime-types gem

      -
    • -

      multipart-post gem

      -
    • -

      rake gem

      -
    • -

      rack gem

      -
    • -

      aws-sdk gem

      -
    - -

    Developer Setup

    -
    1. -

      uncomment entries in Gemfile related to spec tests

      -
    2. -

      bundle install from project directory installs additional gems

      -
    3. -

      rspec spec will run the core tests

      -
    4. -

      The following with regenerate the doc directory: - rdoc --visibility=public ---main='README.md' -o doc --fmt=darkfish --markup=tomdoc ---tab-width=2 --no-dcov --exclude='/spec' --exclude='/log/' ---exclude='/Gemfile' --exclude='/config/' ---exclude='/index.rb' --exclude='/doc/' ---exclude='/Rakefile'

      -
    - -
    To run tests in spec_aws
    -
    1. -

      install and launch clientside_aws

      -
    2. -

      uncomment other entries in Gemfile

      -
    3. -

      bundle install from project directory installs additional gems

      -
    - -
    Known issues in Version 4.0.08
    -
    • -

      local/sqs import/export has not been thoroughly tested

      -
    • -

      archiving of outputs not yet supported

      -
    • -

      freeze frame not yet supported

      -
    • -

      audio still being done in Ecasound

      -
    • -

      due to size considerations, video files not included in spec tests -(eventually tests will generate their own to work with)

      -
    - -
    Migrating from Version 4.0.07
    -
    • -

      The length key in clips has been renamed frames.

      -
    • -

      The audio and video keys in mash tracks have been -moved to mash.

      -
    • -

      The tracks key in mashes has been removed.

      -
    • -

      The fps key in outputs has been renamed -video_rate.

      -
    • -

      The audio_frequency key in outputs has been renamed -audio_rate.

      -
    • -

      The trim key in inputs has been renamed offset.

      -
    +
    rdoc --visibility=public -o doc --main='Documentation.md' --fmt=darkfish --markup=tomdoc --tab-width=2 --no-dcov --exclude='/spec' --exclude='/log' --exclude='/Gemfile' --exclude='/tmp' --exclude='/config' --exclude='/index.rb' --exclude='/doc' --exclude='/bin' --exclude='/Rakefile' --exclude='/Docker' --exclude='/README' --exclude='/LICENSE'

    diff --git a/doc/LICENSE.html b/doc/LICENSE.html deleted file mode 100644 index 20f06b6..0000000 --- a/doc/LICENSE.html +++ /dev/null @@ -1,571 +0,0 @@ - - - - - - -LICENSE - RDoc Documentation - - - - - - - - - - - - - - - - -
    - -

    Mozilla Public License, version 2.0

    -
    1. -

      Definitions

      -
    - -

    1.1. “Contributorâ€

    - -
    means each individual or legal entity that creates, contributes to the
    -creation of, or owns Covered Software.
    - -

    1.2. “Contributor Versionâ€

    - -
    means the combination of the Contributions of others (if any) used by a
    -Contributor and that particular Contributor's Contribution.
    - -

    1.3. “Contributionâ€

    - -
    means Covered Software of a particular Contributor.
    - -

    1.4. “Covered Softwareâ€

    - -
    means Source Code Form to which the initial Contributor has attached the
    -notice in Exhibit A, the Executable Form of such Source Code Form, and
    -Modifications of such Source Code Form, in each case including portions
    -thereof.
    - -

    1.5. “Incompatible With Secondary Licensesâ€

    - -
    means
    -
    -a. that the initial Contributor has attached the notice described in
    -   Exhibit B to the Covered Software; or
    -
    -b. that the Covered Software was made available under the terms of
    -   version 1.1 or earlier of the License, but not also under the terms of
    -   a Secondary License.
    - -

    1.6. “Executable Formâ€

    - -
    means any form of the work other than Source Code Form.
    - -

    1.7. “Larger Workâ€

    - -
    means a work that combines Covered Software with other material, in a
    -separate file or files, that is not Covered Software.
    - -

    1.8. “Licenseâ€

    - -
    means this document.
    - -

    1.9. “Licensableâ€

    - -
    means having the right to grant, to the maximum extent possible, whether
    -at the time of the initial grant or subsequently, any and all of the
    -rights conveyed by this License.
    - -

    1.10. “Modificationsâ€

    - -
    means any of the following:
    -
    -a. any file in Source Code Form that results from an addition to,
    -   deletion from, or modification of the contents of Covered Software; or
    -
    -b. any new file in Source Code Form that contains any Covered Software.
    - -

    1.11. “Patent Claims†of a Contributor

    - -
    means any patent claim(s), including without limitation, method,
    -process, and apparatus claims, in any patent Licensable by such
    -Contributor that would be infringed, but for the grant of the License,
    -by the making, using, selling, offering for sale, having made, import,
    -or transfer of either its Contributions or its Contributor Version.
    - -

    1.12. “Secondary Licenseâ€

    - -
    means either the GNU General Public License, Version 2.0, the GNU Lesser
    -General Public License, Version 2.1, the GNU Affero General Public
    -License, Version 3.0, or any later versions of those licenses.
    - -

    1.13. “Source Code Formâ€

    - -
    means the form of the work preferred for making modifications.
    - -

    1.14. “You†(or “Yourâ€)

    - -
    means an individual or a legal entity exercising rights under this
    -License. For legal entities, "You" includes any entity that controls, is
    -controlled by, or is under common control with You. For purposes of this
    -definition, "control" means (a) the power, direct or indirect, to cause
    -the direction or management of such entity, whether by contract or
    -otherwise, or (b) ownership of more than fifty percent (50%) of the
    -outstanding shares or beneficial ownership of such entity.
    -
    1. -

      License Grants and Conditions

      -
    - -

    2.1. Grants

    - -
    Each Contributor hereby grants You a world-wide, royalty-free,
    -non-exclusive license:
    -
    -a. under intellectual property rights (other than patent or trademark)
    -   Licensable by such Contributor to use, reproduce, make available,
    -   modify, display, perform, distribute, and otherwise exploit its
    -   Contributions, either on an unmodified basis, with Modifications, or
    -   as part of a Larger Work; and
    -
    -b. under Patent Claims of such Contributor to make, use, sell, offer for
    -   sale, have made, import, and otherwise transfer either its
    -   Contributions or its Contributor Version.
    - -

    2.2. Effective Date

    - -
    The licenses granted in Section 2.1 with respect to any Contribution
    -become effective for each Contribution on the date the Contributor first
    -distributes such Contribution.
    - -

    2.3. Limitations on Grant Scope

    - -
    The licenses granted in this Section 2 are the only rights granted under
    -this License. No additional rights or licenses will be implied from the
    -distribution or licensing of Covered Software under this License.
    -Notwithstanding Section 2.1(b) above, no patent license is granted by a
    -Contributor:
    -
    -a. for any code that a Contributor has removed from Covered Software; or
    -
    -b. for infringements caused by: (i) Your and any other third party's
    -   modifications of Covered Software, or (ii) the combination of its
    -   Contributions with other software (except as part of its Contributor
    -   Version); or
    -
    -c. under Patent Claims infringed by Covered Software in the absence of
    -   its Contributions.
    -
    -This License does not grant any rights in the trademarks, service marks,
    -or logos of any Contributor (except as may be necessary to comply with
    -the notice requirements in Section 3.4).
    - -

    2.4. Subsequent Licenses

    - -
    No Contributor makes additional grants as a result of Your choice to
    -distribute the Covered Software under a subsequent version of this
    -License (see Section 10.2) or under the terms of a Secondary License (if
    -permitted under the terms of Section 3.3).
    - -

    2.5. Representation

    - -
    Each Contributor represents that the Contributor believes its
    -Contributions are its original creation(s) or it has sufficient rights to
    -grant the rights to its Contributions conveyed by this License.
    - -

    2.6. Fair Use

    - -
    This License is not intended to limit any rights You have under
    -applicable copyright doctrines of fair use, fair dealing, or other
    -equivalents.
    - -

    2.7. Conditions

    - -
    Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
    -Section 2.1.
    -
    1. -

      Responsibilities

      -
    - -

    3.1. Distribution of Source Form

    - -
    All distribution of Covered Software in Source Code Form, including any
    -Modifications that You create or to which You contribute, must be under
    -the terms of this License. You must inform recipients that the Source
    -Code Form of the Covered Software is governed by the terms of this
    -License, and how they can obtain a copy of this License. You may not
    -attempt to alter or restrict the recipients' rights in the Source Code
    -Form.
    - -

    3.2. Distribution of Executable Form

    - -
    If You distribute Covered Software in Executable Form then:
    -
    -a. such Covered Software must also be made available in Source Code Form,
    -   as described in Section 3.1, and You must inform recipients of the
    -   Executable Form how they can obtain a copy of such Source Code Form by
    -   reasonable means in a timely manner, at a charge no more than the cost
    -   of distribution to the recipient; and
    -
    -b. You may distribute such Executable Form under the terms of this
    -   License, or sublicense it under different terms, provided that the
    -   license for the Executable Form does not attempt to limit or alter the
    -   recipients' rights in the Source Code Form under this License.
    - -

    3.3. Distribution of a Larger Work

    - -
    You may create and distribute a Larger Work under terms of Your choice,
    -provided that You also comply with the requirements of this License for
    -the Covered Software. If the Larger Work is a combination of Covered
    -Software with a work governed by one or more Secondary Licenses, and the
    -Covered Software is not Incompatible With Secondary Licenses, this
    -License permits You to additionally distribute such Covered Software
    -under the terms of such Secondary License(s), so that the recipient of
    -the Larger Work may, at their option, further distribute the Covered
    -Software under the terms of either this License or such Secondary
    -License(s).
    - -

    3.4. Notices

    - -
    You may not remove or alter the substance of any license notices
    -(including copyright notices, patent notices, disclaimers of warranty, or
    -limitations of liability) contained within the Source Code Form of the
    -Covered Software, except that You may alter any license notices to the
    -extent required to remedy known factual inaccuracies.
    - -

    3.5. Application of Additional Terms

    - -
    You may choose to offer, and to charge a fee for, warranty, support,
    -indemnity or liability obligations to one or more recipients of Covered
    -Software. However, You may do so only on Your own behalf, and not on
    -behalf of any Contributor. You must make it absolutely clear that any
    -such warranty, support, indemnity, or liability obligation is offered by
    -You alone, and You hereby agree to indemnify every Contributor for any
    -liability incurred by such Contributor as a result of warranty, support,
    -indemnity or liability terms You offer. You may include additional
    -disclaimers of warranty and limitations of liability specific to any
    -jurisdiction.
    -
    1. -

      Inability to Comply Due to Statute or Regulation

      - -

      If it is impossible for You to comply with any of the terms of this License -with respect to some or all of the Covered Software due to statute, -judicial order, or regulation then You must: (a) comply with the terms of -this License to the maximum extent possible; and (b) describe the -limitations and the code they affect. Such description must be placed in a -text file included with all distributions of the Covered Software under -this License. Except to the extent prohibited by statute or regulation, -such description must be sufficiently detailed for a recipient of ordinary -skill to be able to understand it.

      -
    2. -

      Termination

      -
    - -

    5.1. The rights granted under this License will terminate automatically if -You

    - -
    fail to comply with any of its terms. However, if You become compliant,
    -then the rights granted under this License from a particular Contributor
    -are reinstated (a) provisionally, unless and until such Contributor
    -explicitly and finally terminates Your grants, and (b) on an ongoing
    -basis, if such Contributor fails to notify You of the non-compliance by
    -some reasonable means prior to 60 days after You have come back into
    -compliance. Moreover, Your grants from a particular Contributor are
    -reinstated on an ongoing basis if such Contributor notifies You of the
    -non-compliance by some reasonable means, this is the first time You have
    -received notice of non-compliance with this License from such
    -Contributor, and You become compliant prior to 30 days after Your receipt
    -of the notice.
    - -

    5.2. If You initiate litigation against any entity by asserting a patent

    - -
    infringement claim (excluding declaratory judgment actions,
    -counter-claims, and cross-claims) alleging that a Contributor Version
    -directly or indirectly infringes any patent, then the rights granted to
    -You by any and all Contributors for the Covered Software under Section
    -2.1 of this License shall terminate.
    - -

    5.3. In the event of termination under Sections 5.1 or 5.2 above, all end -user

    - -
    license agreements (excluding distributors and resellers) which have been
    -validly granted by You or Your distributors under this License prior to
    -termination shall survive termination.
    -
    1. -

      Disclaimer of Warranty

      - -

      Covered Software is provided under this License on an “as is†basis, -without warranty of any kind, either expressed, implied, or statutory, -including, without limitation, warranties that the Covered Software is free -of defects, merchantable, fit for a particular purpose or non-infringing. -The entire risk as to the quality and performance of the Covered Software -is with You. Should any Covered Software prove defective in any respect, -You (not any Contributor) assume the cost of any necessary servicing, -repair, or correction. This disclaimer of warranty constitutes an essential -part of this License. No use of any Covered Software is authorized under -this License except under this disclaimer.

      -
    2. -

      Limitation of Liability

      - -

      Under no circumstances and under no legal theory, whether tort (including -negligence), contract, or otherwise, shall any Contributor, or anyone who -distributes Covered Software as permitted above, be liable to You for any -direct, indirect, special, incidental, or consequential damages of any -character including, without limitation, damages for lost profits, loss of -goodwill, work stoppage, computer failure or malfunction, or any and all -other commercial damages or losses, even if such party shall have been -informed of the possibility of such damages. This limitation of liability -shall not apply to liability for death or personal injury resulting from -such party's negligence to the extent applicable law prohibits such -limitation. Some jurisdictions do not allow the exclusion or limitation of -incidental or consequential damages, so this exclusion and limitation may -not apply to You.

      -
    3. -

      Litigation

      - -

      Any litigation relating to this License may be brought only in the courts -of a jurisdiction where the defendant maintains its principal place of -business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. Nothing -in this Section shall prevent a party's ability to bring cross-claims -or counter-claims.

      -
    4. -

      Miscellaneous

      - -

      This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides that -the language of a contract shall be construed against the drafter shall not -be used to construe this License against a Contributor.

      -
    5. -

      Versions of the License

      -
    - -

    10.1. New Versions

    - -
    Mozilla Foundation is the license steward. Except as provided in Section
    -10.3, no one other than the license steward has the right to modify or
    -publish new versions of this License. Each version will be given a
    -distinguishing version number.
    - -

    10.2. Effect of New Versions

    - -
    You may distribute the Covered Software under the terms of the version
    -of the License under which You originally received the Covered Software,
    -or under the terms of any subsequent version published by the license
    -steward.
    - -

    10.3. Modified Versions

    - -
    If you create software not governed by this License, and you want to
    -create a new license for such software, you may create and use a
    -modified version of this License if you rename the license and remove
    -any references to the name of the license steward (except to note that
    -such modified license differs from this License).
    - -

    10.4. Distributing Source Code Form that is Incompatible With Secondary

    - -
    Licenses If You choose to distribute Source Code Form that is
    -Incompatible With Secondary Licenses under the terms of this version of
    -the License, the notice described in Exhibit B of this License must be
    -attached.
    - -

    Exhibit A - Source Code Form License Notice

    - -
    This Source Code Form is subject to the
    -terms of the Mozilla Public License, v.
    -2.0. If a copy of the MPL was not
    -distributed with this file, You can
    -obtain one at
    -http://mozilla.org/MPL/2.0/.
    - -

    If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a -recipient would be likely to look for such a notice.

    - -

    You may add additional accurate notices of copyright ownership.

    - -

    Exhibit B - “Incompatible With Secondary Licenses†Notice

    - -
    This Source Code Form is "Incompatible
    -With Secondary Licenses", as defined by
    -the Mozilla Public License, v. 2.0.
    - -
    - - - - - diff --git a/doc/MovieMasher.html b/doc/MovieMasher.html index 20f1ce6..cb1888b 100644 --- a/doc/MovieMasher.html +++ b/doc/MovieMasher.html @@ -50,28 +50,29 @@

    Defined In

    • lib/callback.rb -
    • lib/constants/av.rb -
    • lib/constants/defaults.rb -
    • lib/constants/error.rb -
    • lib/constants/fill.rb -
    • lib/constants/gain.rb -
    • lib/constants/info.rb -
    • lib/constants/intermediate.rb -
    • lib/constants/method.rb +
    • lib/constant/av.rb +
    • lib/constant/defaults.rb +
    • lib/constant/error.rb +
    • lib/constant/fill.rb +
    • lib/constant/gain.rb +
    • lib/constant/info.rb +
    • lib/constant/intermediate.rb +
    • lib/constant/method.rb
    • lib/graph.rb
    • lib/input.rb
    • lib/job.rb -
    • lib/job_hash.rb
    • lib/mash.rb
    • lib/moviemasher.rb
    • lib/output.rb
    • lib/source.rb
    • lib/transfer.rb -
    • lib/utils/eval.rb -
    • lib/utils/filter_helpers.rb -
    • lib/utils/float_util.rb -
    • lib/utils/path.rb -
    • lib/utils/time_range.rb +
    • lib/util/eval.rb +
    • lib/util/filter_helpers.rb +
    • lib/util/float_util.rb +
    • lib/util/hashable.rb +
    • lib/util/path.rb +
    • lib/util/time_range.rb +
    • lib/version.rb
    @@ -103,8 +104,14 @@

    Methods

  • ::configure +
  • ::goodbye + +
  • ::hello +
  • ::process +
  • ::process_jobs +
  • ::process_queues @@ -118,9 +125,7 @@

    Pages

    @@ -146,6 +151,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -206,6 +213,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -214,8 +223,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -281,6 +288,19 @@

    module MovieMasher

    + +
    +

    Constants

    +
    + +
    VERSION + +
    + + +
    +
    + @@ -309,7 +329,7 @@

    Public Class Methods

    -
    # File lib/moviemasher.rb, line 46
    +            
    # File lib/moviemasher.rb, line 34
     def self.configuration
       configure nil 
       @@configuration
    @@ -341,52 +361,8 @@ 

    Public Class Methods

    Set one or more configuration options. If supplied a String, it's assumed to be a path to a JSON or YML file and converted to a Hash. The -Hash can use a String or Symbol for each key. The following keys are -supported:

    -
    chmod_directory_new -
    -

    Mode to use when creating directories, default: 0775

    -
    log_directory -
    -

    Where to put log file, default: /var/log/moviemasher

    -
    log_level -
    -

    Logger output level (debug, info, warn, error), default: info

    -
    download_directory -
    -

    Where to downloaded files, default: render_directory

    -
    download_directory_size -
    -

    Integer/String target cache size, default: 0M

    -
    render_directory -
    -

    Where to build files, default: /tmp/moviemasher/temporary

    -
    queue_directory -
    -

    Where to look for job files, default: /tmp/moviemasher/queue

    -
    process_queues_seconds -
    -

    How long to watch queues for jobs, default: 55

    -
    aws_OPTIONS -
    -

    passed to the AWS.config method if specified, default: empty

    -
    queue_url -
    -

    SQS queue endpoint to poll for jobs, default: empty

    -
    queue_wait_time_seconds -
    -

    How long to wait for SQS messages, default: 2

    -
    APP_path -
    -

    Path to du, ecasound, ffmpeg, ffprobe, -sox, wav2png, default: APP

    -
    error_directory -
    -

    Where to put failed job directories, default: empty

    -
    render_keep -
    -

    If false build files are removed, default: false

    -
    +Hash can use a String or Symbol for each key. See Config for supported +keys.

    Returns nothing.

    @@ -400,7 +376,7 @@

    Public Class Methods

    -
    # File lib/moviemasher.rb, line 74
    +            
    # File lib/moviemasher.rb, line 46
     def self.configure hash_or_path
       aws_config = Hash.new
       if hash_or_path and not hash_or_path.empty? 
    @@ -459,6 +435,72 @@ 

    Public Class Methods

    +
    + +
    + goodbye() + + click to toggle source + +
    + + +
    + +

    Returns valediction for command line apps.

    + + + + +
    +
    # File lib/moviemasher.rb, line 95
    +def self.goodbye
    +  "#{Time.now} #{self.name} done"
    +end
    +
    + +
    + + + + +
    + + +
    + +
    + hello() + + click to toggle source + +
    + + +
    + +

    Returns salutation for command line apps.

    + + + + +
    +
    # File lib/moviemasher.rb, line 99
    +def self.hello 
    +  "#{Time.now} #{self.name} version #{VERSION}"
    +end
    +
    + +
    + + + + +
    + +
    @@ -482,10 +524,9 @@

    Public Class Methods

    href="MovieMasher/Job.html#method-i-process">MovieMasher::Job#process method is called, its render directory is either moved to error_directory (if that option is not empty and a problem -arose during processing) or deleted (unless render_keep is +arose during processing) or deleted (unless render_save is true). The download_directory will also be pruned to -assure its size is not greater than -download_directory_size.

    +assure its size is not greater than download_bytes.

    Returns Job object with @@ -497,9 +538,8 @@

    Public Class Methods

    -
    # File lib/moviemasher.rb, line 131
    +            
    # File lib/moviemasher.rb, line 111
     def self.process object_or_path
    -  __log_transcoder(:debug) { "process called #{object_or_path}" }
       result = @@job = (object_or_path.is_a?(Job) ? object_or_path : Job.new(object_or_path, configuration))
       begin # try to process job
         @@job.process unless @@job[:error]
    @@ -512,7 +552,7 @@ 

    Public Class Methods

    if @@job[:error] and configuration[:error_directory] and not configuration[:error_directory].empty? then FileUtils.mv job_directory, configuration[:error_directory] else - FileUtils.rm_r job_directory unless configuration[:render_keep] + FileUtils.rm_r job_directory unless configuration[:render_save] end end rescue Exception => e @@ -523,7 +563,7 @@

    Public Class Methods

    begin # try to flush the download directory directory = @@configuration[:download_directory] directory = @@configuration[:render_directory] unless directory and not directory.empty? - __flush_downloads directory, configuration[:download_directory_size] + __flush_downloads directory, configuration[:download_bytes] rescue Exception => e __log_exception e end @@ -539,11 +579,47 @@

    Public Class Methods

    +
    + +
    + process_jobs(array) + + click to toggle source + +
    + + +
    + +

    Calls process for each item in array

    + + + + +
    +
    # File lib/moviemasher.rb, line 142
    +def self.process_jobs array # of job strings or paths
    +  array.each do |job_str|
    +    process job_str
    +  end
    +  (array.empty? ? nil : array.length)
    +end
    +
    + +
    + + + + +
    + +
    process_queues() + class="method-args">(process_seconds = nil) click to toggle source @@ -552,9 +628,9 @@

    Public Class Methods

    -

    Loops for process_queues_seconds searching for the oldest -JSON or YML formatted job file in queue_directory, as well -as polling queue_url for an SQS message. If the later is +

    Loops for process_seconds searching for the oldest JSON or +YML formatted job file in queue_directory, as well as +polling queue_url for an SQS message. If the later is found its body is expected to be a JSON formatted job and its identifier is used to populate the id key (if that's empty), as well as the basename of the file saved to the queue_directory. @@ -579,30 +655,39 @@

    Public Class Methods

    -
    # File lib/moviemasher.rb, line 179
    -def self.process_queues
    +            
    # File lib/moviemasher.rb, line 165
    +def self.process_queues process_seconds = nil
    +  process_seconds = configuration[:process_seconds] unless process_seconds
    +  process_seconds = process_seconds.to_i
       raise Error::Configuration.new "queue_directory not found in configuration" unless configuration[:queue_directory] and not configuration[:queue_directory].empty?
    -  run_seconds = configuration[:process_queues_seconds]
       start = Time.now
    -  oldest_file = nil
    -  working_file = "#{configuration[:queue_directory]}working.json"
    -  while run_seconds > (Time.now - start)
    -    if File.exists? working_file
    -      # if this process didn't create it, we must have crashed on it in a previous run
    -      __log_transcoder(:error) { "deleting previously active job:\n#{File.read working_file}" } unless oldest_file
    -      File.delete working_file
    -    end
    -    oldest_file = Dir["#{configuration[:queue_directory]}*.json"].sort_by{ |f| File.mtime(f) }.first
    -    if oldest_file then
    -      __log_transcoder(:info) { "started #{oldest_file}" }
    -      File.rename oldest_file, working_file
    +  Dir[Path.concat configuration[:queue_directory], 'working.*'].each do |working_file|
    +    # if this process didn't create it, we must have crashed on it in a previous run
    +    __log_transcoder(:error) { "deleting previously active job:\n#{File.read working_file}" }
    +    File.delete working_file       
    +  end
    +  while (0 > process_seconds) or (process_seconds > (Time.now - start))
    +    job = Dir[Path.concat configuration[:queue_directory], '*'].sort_by{ |f| File.mtime(f) }.first
    +    if job then
    +      __log_transcoder(:info) { "starting #{job}" }
    +      working_file = "#{File.dirname job}/working#{File.extname job}"
    +      File.rename job, working_file
           process working_file
    -      __log_transcoder(:info) { "finished #{oldest_file}" }
    +      __log_transcoder(:info) { "finishing #{job}" }
           File.delete working_file
    -      sleep 1
         else # see if one can be copied from the queue
    -      __sqs_request(run_seconds, start) unless configuration[:queue_url].nil? or configuration[:queue_url].empty?
    +      if (0 > process_seconds) or (process_seconds > (Time.now + configuration[:queue_wait_seconds] - start))
    +        job = __sqs_request unless configuration[:queue_url].nil? or configuration[:queue_url].empty?
    +        if job
    +          __log_transcoder(:info) { "starting #{job[:id]}" }
    +          process job 
    +          __log_transcoder(:info) { "finishing #{job[:id]}" }
    +        end
    +      end
         end
    +    break if -1 == process_seconds
    +    break if -2 == process_seconds and not found
    +    sleep 0.01
       end
     end
    diff --git a/doc/MovieMasher/AV.html b/doc/MovieMasher/AV.html index 1621791..288c60f 100644 --- a/doc/MovieMasher/AV.html +++ b/doc/MovieMasher/AV.html @@ -49,7 +49,7 @@

    @@ -83,9 +83,7 @@

    Pages

    @@ -111,6 +109,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -171,6 +171,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -179,8 +181,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -289,7 +289,7 @@

    Public Class Methods

    -
    # File lib/constants/av.rb, line 8
    +            
    # File lib/constant/av.rb, line 8
     def self.includes? has, desired
       (Both == desired) or (Both == has) or (desired == has) 
     end
    @@ -322,7 +322,7 @@

    Public Class Methods

    -
    # File lib/constants/av.rb, line 11
    +            
    # File lib/constant/av.rb, line 11
     def self.merge type1, type2
       return type1 unless type2 and type1 != type2
       Both
    diff --git a/doc/MovieMasher/Callback.html b/doc/MovieMasher/Callback.html
    index d5eae7b..2919b40 100644
    --- a/doc/MovieMasher/Callback.html
    +++ b/doc/MovieMasher/Callback.html
    @@ -107,9 +107,7 @@ 

    Pages

    @@ -135,6 +133,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -195,6 +195,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -203,8 +205,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Chain.html b/doc/MovieMasher/Chain.html index 7328675..5b572ce 100644 --- a/doc/MovieMasher/Chain.html +++ b/doc/MovieMasher/Chain.html @@ -92,9 +92,7 @@

    Pages

    @@ -120,6 +118,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -180,6 +180,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -188,8 +190,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/ChainEffects.html b/doc/MovieMasher/ChainEffects.html index 48cdb9f..d6764ba 100644 --- a/doc/MovieMasher/ChainEffects.html +++ b/doc/MovieMasher/ChainEffects.html @@ -86,9 +86,7 @@

    Pages

    @@ -114,6 +112,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -174,6 +174,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -182,8 +184,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/ChainModule.html b/doc/MovieMasher/ChainModule.html index 6e5bbf2..7800895 100644 --- a/doc/MovieMasher/ChainModule.html +++ b/doc/MovieMasher/ChainModule.html @@ -92,9 +92,7 @@

    Pages

    @@ -120,6 +118,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -180,6 +180,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -188,8 +190,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/ChainOverlay.html b/doc/MovieMasher/ChainOverlay.html index cf71691..6f8c3cf 100644 --- a/doc/MovieMasher/ChainOverlay.html +++ b/doc/MovieMasher/ChainOverlay.html @@ -88,9 +88,7 @@

    Pages

    @@ -116,6 +114,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -176,6 +176,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -184,8 +186,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/ChainScaler.html b/doc/MovieMasher/ChainScaler.html index d61da24..3c4e74d 100644 --- a/doc/MovieMasher/ChainScaler.html +++ b/doc/MovieMasher/ChainScaler.html @@ -88,9 +88,7 @@

    Pages

    @@ -116,6 +114,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -176,6 +176,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -184,8 +186,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/TypeTransfer.html b/doc/MovieMasher/Configuration.html similarity index 87% rename from doc/MovieMasher/TypeTransfer.html rename to doc/MovieMasher/Configuration.html index 65d1736..8de7335 100644 --- a/doc/MovieMasher/TypeTransfer.html +++ b/doc/MovieMasher/Configuration.html @@ -4,7 +4,7 @@ -module MovieMasher::TypeTransfer - RDoc Documentation +module MovieMasher::Configuration - RDoc Documentation @@ -49,8 +49,7 @@

    @@ -71,9 +70,7 @@

    Pages

    @@ -99,9 +96,9 @@

    Class and Module Index

  • MovieMasher::ChainScaler -
  • MovieMasher::Defaults +
  • MovieMasher::Configuration -
  • MovieMasher::Destination +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -161,6 +158,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -169,8 +168,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -199,7 +196,7 @@

    Class and Module Index

  • MovieMasher::TimeRange -
  • MovieMasher::TypeTransfer +
  • MovieMasher::Transfer @@ -208,7 +205,7 @@

    Class and Module Index

    -

    module MovieMasher::TypeTransfer

    +

    module MovieMasher::Configuration

    @@ -223,34 +220,6 @@

    module MovieMasher::TypeTransfer

    - -
    -

    Constants

    -
    - -
    File - -
    - - -
    Http - -
    - - -
    Https - -
    - - -
    S3 - -
    - - -
    -
    - diff --git a/doc/MovieMasher/Defaults.html b/doc/MovieMasher/Defaults.html index ed22621..adf3bc0 100644 --- a/doc/MovieMasher/Defaults.html +++ b/doc/MovieMasher/Defaults.html @@ -49,7 +49,7 @@

    @@ -80,9 +80,7 @@

    Pages

    @@ -108,6 +106,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -168,6 +168,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -176,8 +178,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -281,7 +281,7 @@

    Public Class Methods

    -
    # File lib/constants/defaults.rb, line 6
    +            
    # File lib/constant/defaults.rb, line 6
     def self.module_for_type type, media_id = nil
       case type
       when Mash::Font, Mash::Font.to_sym
    diff --git a/doc/MovieMasher/Destination.html b/doc/MovieMasher/Destination.html
    deleted file mode 100644
    index 3e9f4b8..0000000
    --- a/doc/MovieMasher/Destination.html
    +++ /dev/null
    @@ -1,297 +0,0 @@
    -
    -
    -
    -
    -
    -
    -class MovieMasher::Destination - RDoc Documentation
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    class MovieMasher::Destination

    - -
    - -
    - - - - -
    - - - - - - - - - - -
    -

    Public Class Methods

    - - -
    - -
    - create(hash) - - click to toggle source - -
    - - -
    - -

    Returns a new instance.

    - - - - -
    -
    # File lib/destination.rb, line 5
    -def self.create hash
    -  Destination.new hash
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - -
    - - - - diff --git a/doc/MovieMasher/Error.html b/doc/MovieMasher/Error.html index 84bc1e7..222e1ff 100644 --- a/doc/MovieMasher/Error.html +++ b/doc/MovieMasher/Error.html @@ -49,12 +49,12 @@

    @@ -75,9 +75,7 @@

    Pages

    @@ -103,6 +101,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -163,6 +163,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -171,8 +173,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/Configuration.html b/doc/MovieMasher/Error/Configuration.html index 0a172ca..080fc31 100644 --- a/doc/MovieMasher/Error/Configuration.html +++ b/doc/MovieMasher/Error/Configuration.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/Critical.html b/doc/MovieMasher/Error/Critical.html index a9b9af2..c575022 100644 --- a/doc/MovieMasher/Error/Critical.html +++ b/doc/MovieMasher/Error/Critical.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/Job.html b/doc/MovieMasher/Error/Job.html index ee94b9f..6c0b3bf 100644 --- a/doc/MovieMasher/Error/Job.html +++ b/doc/MovieMasher/Error/Job.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/JobInput.html b/doc/MovieMasher/Error/JobInput.html index 3f033bd..6892e50 100644 --- a/doc/MovieMasher/Error/JobInput.html +++ b/doc/MovieMasher/Error/JobInput.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/JobOutput.html b/doc/MovieMasher/Error/JobOutput.html index de3cad5..fe3ca22 100644 --- a/doc/MovieMasher/Error/JobOutput.html +++ b/doc/MovieMasher/Error/JobOutput.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/JobRender.html b/doc/MovieMasher/Error/JobRender.html index 4b1d6c6..8b47013 100644 --- a/doc/MovieMasher/Error/JobRender.html +++ b/doc/MovieMasher/Error/JobRender.html @@ -49,7 +49,7 @@

    @@ -86,9 +86,7 @@

    Pages

    @@ -114,6 +112,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -174,6 +174,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -182,8 +184,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -264,7 +264,7 @@

    Public Class Methods

    -
    # File lib/constants/error.rb, line 17
    +            
    # File lib/constant/error.rb, line 17
     def initialize ffmpeg_result, msg = "failed to render"
       error_lines = Array.new
       error_lines << msg if msg
    diff --git a/doc/MovieMasher/Error/JobSource.html b/doc/MovieMasher/Error/JobSource.html
    index 33bd27a..88b5133 100644
    --- a/doc/MovieMasher/Error/JobSource.html
    +++ b/doc/MovieMasher/Error/JobSource.html
    @@ -49,7 +49,7 @@ 

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/JobUpload.html b/doc/MovieMasher/Error/JobUpload.html index abd2089..f4694c9 100644 --- a/doc/MovieMasher/Error/JobUpload.html +++ b/doc/MovieMasher/Error/JobUpload.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/Object.html b/doc/MovieMasher/Error/Object.html index 0b920ff..8df95d7 100644 --- a/doc/MovieMasher/Error/Object.html +++ b/doc/MovieMasher/Error/Object.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/Parameter.html b/doc/MovieMasher/Error/Parameter.html index b1b61d0..19abb13 100644 --- a/doc/MovieMasher/Error/Parameter.html +++ b/doc/MovieMasher/Error/Parameter.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/Runtime.html b/doc/MovieMasher/Error/Runtime.html index d9bdb5c..69f1c53 100644 --- a/doc/MovieMasher/Error/Runtime.html +++ b/doc/MovieMasher/Error/Runtime.html @@ -49,7 +49,7 @@

    @@ -88,9 +88,7 @@

    Pages

    @@ -116,6 +114,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -176,6 +176,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -184,8 +186,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -266,7 +266,7 @@

    Public Class Methods

    -
    # File lib/constants/error.rb, line 5
    +            
    # File lib/constant/error.rb, line 5
     def initialize msg = nil
       @msg = msg if msg
     end
    @@ -305,7 +305,7 @@

    Public Instance Methods

    -
    # File lib/constants/error.rb, line 8
    +            
    # File lib/constant/error.rb, line 8
     def to_s
       @msg ? @msg : ''
     end
    diff --git a/doc/MovieMasher/Error/State.html b/doc/MovieMasher/Error/State.html index 5d3c36a..162d497 100644 --- a/doc/MovieMasher/Error/State.html +++ b/doc/MovieMasher/Error/State.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Error/Todo.html b/doc/MovieMasher/Error/Todo.html index 1fe321e..0feb3dc 100644 --- a/doc/MovieMasher/Error/Todo.html +++ b/doc/MovieMasher/Error/Todo.html @@ -49,7 +49,7 @@

    @@ -76,9 +76,7 @@

    Pages

    @@ -104,6 +102,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -164,6 +164,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -172,8 +174,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Evaluate.html b/doc/MovieMasher/Evaluate.html index f3589e9..2e3bd88 100644 --- a/doc/MovieMasher/Evaluate.html +++ b/doc/MovieMasher/Evaluate.html @@ -49,7 +49,7 @@

    @@ -84,9 +84,7 @@

    Pages

    @@ -112,6 +110,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -172,6 +172,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -180,8 +182,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -262,7 +262,7 @@

    Public Class Methods

    -
    # File lib/utils/eval.rb, line 4
    +            
    # File lib/util/eval.rb, line 4
     def self.equation s, raise_on_fail = nil
       # change all numbers to floats
    
       fs = s.to_s.gsub(/([0-9]+[.]?[0-9]*)/) { $1.to_f }
    @@ -304,7 +304,7 @@ 

    Public Class Methods

    -
    # File lib/utils/eval.rb, line 16
    +            
    # File lib/util/eval.rb, line 16
     def self.object data, scope = nil
       scope = Hash.new unless scope
       keys = (data.is_a?(Array) ? (0..(data.length-1)) : data.keys)
    @@ -347,7 +347,7 @@ 

    Public Class Methods

    -
    # File lib/utils/eval.rb, line 29
    +            
    # File lib/util/eval.rb, line 29
     def self.value v, scope
       split_value = __split v
       if 1 < split_value.length then # otherwise there are no curly braces
    
    diff --git a/doc/MovieMasher/Fill.html b/doc/MovieMasher/Fill.html
    index 378b557..0fa60d8 100644
    --- a/doc/MovieMasher/Fill.html
    +++ b/doc/MovieMasher/Fill.html
    @@ -49,7 +49,7 @@ 

    @@ -100,6 +98,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -160,6 +160,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -168,8 +170,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Filter.html b/doc/MovieMasher/Filter.html index 37893ff..f37f8df 100644 --- a/doc/MovieMasher/Filter.html +++ b/doc/MovieMasher/Filter.html @@ -90,9 +90,7 @@

    Pages

    @@ -118,6 +116,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -178,6 +178,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -186,8 +188,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/FilterEvaluated.html b/doc/MovieMasher/FilterEvaluated.html index 3ffba2e..a34318c 100644 --- a/doc/MovieMasher/FilterEvaluated.html +++ b/doc/MovieMasher/FilterEvaluated.html @@ -102,9 +102,7 @@

    Pages

    @@ -130,6 +128,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -190,6 +190,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -198,8 +200,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/FilterHash.html b/doc/MovieMasher/FilterHash.html index 65c6626..fd5bd11 100644 --- a/doc/MovieMasher/FilterHash.html +++ b/doc/MovieMasher/FilterHash.html @@ -90,9 +90,7 @@

    Pages

    @@ -118,6 +116,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -178,6 +178,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -186,8 +188,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/FilterHelpers.html b/doc/MovieMasher/FilterHelpers.html index 664d5cb..ff431fb 100644 --- a/doc/MovieMasher/FilterHelpers.html +++ b/doc/MovieMasher/FilterHelpers.html @@ -49,7 +49,7 @@

    @@ -104,9 +104,7 @@

    Pages

    @@ -132,6 +130,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -192,6 +192,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -200,8 +202,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -282,7 +282,7 @@

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 87
    +            
    # File lib/util/filter_helpers.rb, line 87
     def self.mm_cmp param_string, mash, scope, output = nil
       params = __params_from_str param_string
       #puts "mm_cmp (#{params[0].to_f} > #{params[1].to_f} ? #{params[2]} : #{params[3]}) = #{(params[0].to_f > params[1].to_f ? params[2] : params[3])}"
    @@ -319,7 +319,7 @@ 

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 46
    +            
    # File lib/util/filter_helpers.rb, line 46
     def self.mm_dir_horz param_string, mash, scope, output = nil
       raise Error::JobInput.new "mm_dir_horz no parameters #{param_string}" if param_string.empty?
       params = __params_from_str param_string
    @@ -364,7 +364,7 @@ 

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 65
    +            
    # File lib/util/filter_helpers.rb, line 65
     def self.mm_dir_vert param_string, mash, scope, output = nil
       raise Error::JobInput.new "mm_dir_vert no parameters #{param_string}" if param_string.empty?
       params = __params_from_str param_string
    @@ -410,7 +410,7 @@ 

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 33
    +            
    # File lib/util/filter_helpers.rb, line 33
     def self.mm_fontfamily param_string, mash, scope, output = nil
       params = __params_from_str param_string
       font_id = params.join ','
    @@ -447,7 +447,7 @@ 

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 26
    +            
    # File lib/util/filter_helpers.rb, line 26
     def self.mm_fontfile param_string, mash, scope, output = nil
       params = __params_from_str param_string
       font_id = params.join ','
    @@ -484,7 +484,7 @@ 

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 40
    +            
    # File lib/util/filter_helpers.rb, line 40
     def self.mm_horz param_string, mash = nil, scope = nil, output = nil
       __horz_vert :mm_width, param_string, mash, scope, output
     end
    @@ -517,7 +517,7 @@

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 81
    +            
    # File lib/util/filter_helpers.rb, line 81
     def self.mm_max param_string, mash, scope, output = nil
       __max_min :max, param_string, mash, scope, output
     end
    @@ -550,7 +550,7 @@

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 84
    +            
    # File lib/util/filter_helpers.rb, line 84
     def self.mm_min param_string, mash, scope, output = nil
       __max_min :min, param_string, mash, scope, output
     end
    @@ -583,7 +583,7 @@

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 61
    +            
    # File lib/util/filter_helpers.rb, line 61
     def self.mm_paren param_string, mash, scope, output = nil
       params = __params_from_str param_string
       "(#{params.join ','})"
    @@ -617,7 +617,7 @@ 

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 3
    +            
    # File lib/util/filter_helpers.rb, line 3
     def self.mm_textfile param_string, mash, scope, output = nil
       job_path = ''
       if output and scope[:mm_job]
    @@ -659,7 +659,7 @@ 

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 43
    +            
    # File lib/util/filter_helpers.rb, line 43
     def self.mm_vert param_string, mash = nil, scope = nil, output = nil
       __horz_vert :mm_height, param_string, mash, scope, output
     end
    @@ -692,7 +692,7 @@

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 15
    +            
    # File lib/util/filter_helpers.rb, line 15
     def self.rgb param_string, mash = nil, scope = nil, output = nil
       params = __params_from_str param_string
       "0x%02x%02x%02x" % params
    @@ -726,7 +726,7 @@ 

    Public Class Methods

    -
    # File lib/utils/filter_helpers.rb, line 19
    +            
    # File lib/util/filter_helpers.rb, line 19
     def self.rgba param_string, mash = nil, scope = nil, output = nil
       params = __params_from_str param_string
       alpha = params.pop.to_f
    diff --git a/doc/MovieMasher/FilterSetpts.html b/doc/MovieMasher/FilterSetpts.html
    index 9532329..6b227eb 100644
    --- a/doc/MovieMasher/FilterSetpts.html
    +++ b/doc/MovieMasher/FilterSetpts.html
    @@ -86,9 +86,7 @@ 

    Pages

    @@ -114,6 +112,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -174,6 +174,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -182,8 +184,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/FilterSource.html b/doc/MovieMasher/FilterSource.html index 366d29f..55e7bf0 100644 --- a/doc/MovieMasher/FilterSource.html +++ b/doc/MovieMasher/FilterSource.html @@ -88,9 +88,7 @@

    Pages

    @@ -116,6 +114,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -176,6 +176,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -184,8 +186,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/FilterSourceColor.html b/doc/MovieMasher/FilterSourceColor.html index 3b07592..4395569 100644 --- a/doc/MovieMasher/FilterSourceColor.html +++ b/doc/MovieMasher/FilterSourceColor.html @@ -90,9 +90,7 @@

    Pages

    @@ -118,6 +116,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -178,6 +178,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -186,8 +188,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/FilterSourceMovie.html b/doc/MovieMasher/FilterSourceMovie.html index 6b2cc53..6a561e4 100644 --- a/doc/MovieMasher/FilterSourceMovie.html +++ b/doc/MovieMasher/FilterSourceMovie.html @@ -88,9 +88,7 @@

    Pages

    @@ -116,6 +114,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -176,6 +176,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -184,8 +186,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Float.html b/doc/MovieMasher/Float.html deleted file mode 100644 index 8816aca..0000000 --- a/doc/MovieMasher/Float.html +++ /dev/null @@ -1,618 +0,0 @@ - - - - - - -module MovieMasher::Float - RDoc Documentation - - - - - - - - - - - - - - - - -
    -

    module MovieMasher::Float

    - -
    - -
    - - - - -
    - - - - - - -
    -

    Constants

    -
    - -
    Hundred - -
    - - -
    NegOne - -
    - - -
    One - -
    - - -
    Two - -
    - - -
    Zero - -
    - - -
    -
    - - - - - - -
    -

    Public Class Methods

    - - -
    - -
    - cmp(f1, f2, digits = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/float.rb, line 9
    -def self.cmp(f1, f2, digits = 3) # are 2 floats equal
    
    -  e = (10 ** digits).to_f
    -  i1 = (f1.to_f * e).round.to_i
    -  i2 = (f2.to_f * e).round.to_i
    -  (i1 == i2)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - gtr(big, small, digits = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/float.rb, line 18
    -def self.gtr(big, small, digits = 3) # is one float bigger than another
    
    -  e = (10 ** digits).to_f
    -  ibig = (big.to_f * e).round
    -  ismall = (small.to_f * e).round
    -  (ibig > ismall)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - gtre(big, small, digits = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/float.rb, line 24
    -def self.gtre(big, small, digits = 3) # is one float bigger or equal to another
    
    -  e = (10 ** digits).to_f
    -  ibig = (big.to_f * e).round
    -  ismall = (small.to_f * e).round
    -  (ibig >= ismall)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - less(small, big, digits = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/float.rb, line 15
    -def self.less(small, big, digits = 3) # is one float smaller than another
    
    -  not gtre(big, small, digits)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - max(a, b, digits = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/float.rb, line 30
    -def self.max(a, b, digits = 3)
    -  (gtr(a, b, digits) ? a : b)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - min(a, b, digits = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/float.rb, line 33
    -def self.min(a, b, digits = 3)
    -  (gtr(a, b, digits) ? b : a)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - precision(f, digits = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/float.rb, line 46
    -def self.precision f, digits = 3
    -  divisor = (10 ** digits.to_i).to_f
    -  (f.to_f * divisor).round / divisor
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - sort(a, b) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/float.rb, line 36
    -def self.sort(a, b)
    -  (gtr(a[0], b[0]) ? 1 : (cmp(a[0], b[0]) ? 0 : -1))
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - string(f, digits = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/float.rb, line 39
    -def self.string f, digits = 3
    -  return precision f, digits
    -  divisor = (10 ** digits.to_i).to_f
    -  fs = ((f.to_f * divisor).round).to_i.to_s.ljust(digits + 2, '0')
    -  fs.insert(-1 - digits, '.')
    -  fs
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - -
    - - - - diff --git a/doc/MovieMasher/FloatUtil.html b/doc/MovieMasher/FloatUtil.html index be875af..a0ca778 100644 --- a/doc/MovieMasher/FloatUtil.html +++ b/doc/MovieMasher/FloatUtil.html @@ -49,7 +49,7 @@

    @@ -96,9 +96,7 @@

    Pages

    @@ -124,6 +122,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -184,6 +184,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -192,8 +194,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -307,7 +307,7 @@

    Public Class Methods

    -
    # File lib/utils/float_util.rb, line 9
    +            
    # File lib/util/float_util.rb, line 9
     def self.cmp(f1, f2, digits = 3) # are 2 floats equal
    
       e = (10 ** digits).to_f
       i1 = (f1.to_f * e).round.to_i
    @@ -343,7 +343,7 @@ 

    Public Class Methods

    -
    # File lib/utils/float_util.rb, line 18
    +            
    # File lib/util/float_util.rb, line 18
     def self.gtr(big, small, digits = 3) # is one float bigger than another
    
       e = (10 ** digits).to_f
       ibig = (big.to_f * e).round
    @@ -379,7 +379,7 @@ 

    Public Class Methods

    -
    # File lib/utils/float_util.rb, line 24
    +            
    # File lib/util/float_util.rb, line 24
     def self.gtre(big, small, digits = 3) # is one float bigger or equal to another
    
       e = (10 ** digits).to_f
       ibig = (big.to_f * e).round
    @@ -415,7 +415,7 @@ 

    Public Class Methods

    -
    # File lib/utils/float_util.rb, line 15
    +            
    # File lib/util/float_util.rb, line 15
     def self.less(small, big, digits = 3) # is one float smaller than another
    
       not gtre(big, small, digits)
     end
    @@ -448,7 +448,7 @@

    Public Class Methods

    -
    # File lib/utils/float_util.rb, line 30
    +            
    # File lib/util/float_util.rb, line 30
     def self.max(a, b, digits = 3)
       (gtr(a, b, digits) ? a : b)
     end
    @@ -481,7 +481,7 @@

    Public Class Methods

    -
    # File lib/utils/float_util.rb, line 33
    +            
    # File lib/util/float_util.rb, line 33
     def self.min(a, b, digits = 3)
       (gtr(a, b, digits) ? b : a)
     end
    @@ -514,7 +514,7 @@

    Public Class Methods

    -
    # File lib/utils/float_util.rb, line 46
    +            
    # File lib/util/float_util.rb, line 46
     def self.precision f, digits = 3
       divisor = (10 ** digits.to_i).to_f
       (f.to_f * divisor).round / divisor
    @@ -548,7 +548,7 @@ 

    Public Class Methods

    -
    # File lib/utils/float_util.rb, line 36
    +            
    # File lib/util/float_util.rb, line 36
     def self.sort(a, b)
       (gtr(a[0], b[0]) ? 1 : (cmp(a[0], b[0]) ? 0 : -1))
     end
    @@ -581,7 +581,7 @@

    Public Class Methods

    -
    # File lib/utils/float_util.rb, line 39
    +            
    # File lib/util/float_util.rb, line 39
     def self.string f, digits = 3
       return precision f, digits
       divisor = (10 ** digits.to_i).to_f
    diff --git a/doc/MovieMasher/FrameRange.html b/doc/MovieMasher/FrameRange.html
    deleted file mode 100644
    index 2a80d77..0000000
    --- a/doc/MovieMasher/FrameRange.html
    +++ /dev/null
    @@ -1,910 +0,0 @@
    -
    -
    -
    -
    -
    -
    -class MovieMasher::FrameRange - RDoc Documentation
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    class MovieMasher::FrameRange

    - -
    - -
    - - - - -
    - - - - - - - - - - -
    -

    Public Class Methods

    - - -
    - -
    - from_times(start_time, stop_time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 3
    -def self.from_times(start_time, stop_time)
    -  start_time.synchronize stop_time
    -  FrameRange.new(start_time.frame, stop_time.frame - start_time.frame, start_time.fps)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - new(start = 0, length = 1, rate = 0) - - click to toggle source - -
    - - -
    - - - - -
    - Calls superclass method - -
    - - - -
    -
    # File lib/utils/frame_range.rb, line 13
    -def initialize (start = 0, length = 1, rate = 0)
    -  @length = length #.to_i
    -  super(start, rate)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    -

    Public Instance Methods

    - - -
    - -
    - copy_time_range() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 54
    -def copy_time_range
    -  FrameRange.new @frame, @length, @fps
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - description() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 88
    -def description
    -  "[FrameRange #{frame}+#{length}=#{get_end}@#{fps}]"
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - end_time() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 23
    -def end_time
    -  FrameTime.new(get_end, fps)
    - end
    -
    - -
    - - - - -
    - - -
    - -
    - get_end() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 51
    -def get_end
    -  frame + length
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - intersection(range) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 57
    -def intersection range
    -  result = nil
    -  range1 = self
    -  range2 = range
    -  if range1.fps != range2.fps then
    -    range1 = range1.copy_time_range
    -    range2 = range2.copy_time_range
    -    range1.synchronize range2
    -  end
    -  last_start = [range1.frame, range2.frame].max
    -  first_end = [range1.get_end, range2.get_end].min
    -  if (last_start < first_end) then
    -    result = FrameRange.new(last_start, first_end - last_start, range1.fps)
    -  end
    -  result
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - is_equal_to_time_range?(range) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 73
    -def is_equal_to_time_range? range
    -  equal = false
    -  if range and range.valid? then
    -    if (fps == range.fps) 
    -      equal = ((frame == range.frame) and (length == range.length))
    -    else
    -      # make copies so neither range is changed
    -      range1 = copy_time_range
    -      range2 = range.copy_time_range
    -      range1.synchronize range2
    -      equal = ((range1.frame == range2.frame) and (range1.length == range2.length))
    -    end
    -  end
    -  equal
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - length() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 7
    -def length
    -  @length
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - length=(n) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 10
    -def length= n
    -  @length = n
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - length_seconds(precision = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 17
    -def length_seconds(precision = 3)
    -  FloatUtil.precision((@length.to_f / @fps.to_f), precision)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - length_time() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 20
    -def length_time
    -  FrameTime.new(length, fps)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - max_end(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 40
    -def max_end time
    -  synchronize(time)
    -  set_end [time.get_end, get_end].max
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - max_length(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 36
    -def max_length time
    -  synchronize(time)
    -  @length = [time.frame, @length].max
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - min_length(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 44
    -def min_length time
    -  synchronize(time)
    -  @length = [time.frame, @length].min
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - scale(rate, rounding = :round) - - click to toggle source - -
    - - -
    - - - - -
    - Calls superclass method - -
    - - - -
    -
    # File lib/utils/frame_range.rb, line 26
    -def scale(rate, rounding = :round) # void
    -  if 0 < rate and fps != rate then
    -    if 0 < fps then
    -      floated = length.to_f / (fps.to_f / rate.to_f)
    -      floated = floated.send(rounding) if (rounding) 
    -      length = [1, floated].max
    -    end
    -    super rate, rounding
    -  end
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - set_end(n) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_range.rb, line 48
    -def set_end n
    -  length = [1, (n.to_f - frame.to_f).to_i].max
    - end
    -
    - -
    - - - - -
    - - -
    - -
    - -
    - - - - diff --git a/doc/MovieMasher/FrameTime.html b/doc/MovieMasher/FrameTime.html deleted file mode 100644 index 709083e..0000000 --- a/doc/MovieMasher/FrameTime.html +++ /dev/null @@ -1,1182 +0,0 @@ - - - - - - -class MovieMasher::FrameTime - RDoc Documentation - - - - - - - - - - - - - - - - -
    -

    class MovieMasher::FrameTime

    - -
    - -
    - - - - -
    - - - - - - - - - - -
    -

    Public Class Methods

    - - -
    - -
    - from_seconds(seconds = 0, rate = 0, rounding = :round) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 4
    -def self.from_seconds(seconds = 0, rate = 0, rounding = :round)
    -  FrameTime.new((seconds.to_f * rate.to_f).send(rounding).to_i, rate)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - new(frame = 0, fps = 0) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 43
    -def initialize(frame = 0, fps = 0)
    -  @frame = frame.to_i
    -  @fps = fps.to_i
    -end
    -
    - -
    - - - - -
    - - -
    - -
    -

    Public Instance Methods

    - - -
    - -
    - __gcd(a, b) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 138
    -def __gcd(a, b) # uint
    -  t = 0
    -  while (b != 0) do
    -    t = b
    -    b = a % b
    -    a = t
    -  end
    -  a
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - __lcm(a, b) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 147
    -def __lcm(a, b)
    -  (a * b / __gcd(a, b))
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - add(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 7
    -def add time
    -  synchronize time
    -  @frame += time.frame
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - copy_time() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 11
    -def copy_time
    -  FrameTime.new(@frame, @fps)  
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - description() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 14
    -def description
    -  "[FrameTime #{frame}@#{fps}]"
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - divide(number, rounding = :round) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 17
    -def divide(number, rounding = :round)
    -  number = number.to_f if number.respond_to? :to_f
    -  @frame = (@frame.to_f / number).send(rounding)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - fps() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 21
    -def fps
    -  @fps
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - frame() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 27
    -def frame
    -  @frame
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - frame=(new_frame) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 24
    -def frame= new_frame
    -  @frame = new_frame
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - frame_for_rate(rate, rounding = :round) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 30
    -def frame_for_rate(rate, rounding = :round)
    -  start = @frame
    -  if rate != @fps then
    -    start = FrameTime.from_seconds(get_seconds, @fps, rounding).frame
    -  end
    -  start  
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - get_seconds(precision = 3) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 37
    -def get_seconds precision = 3
    -  FloatUtil.precision((@frame.to_f / @fps.to_f), precision)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - get_time_range() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 40
    -def get_time_range
    -  FrameRange.new(@frame, 1, @fps)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - is_equal_to_time?(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 47
    -def is_equal_to_time? time
    -  equal = FALSE
    -  if valid? and time and time.respond_to?(:valid) and time.valid? then
    -    if (@fps == time.fps) then
    -      equal = (@frame == time.frame)
    -    else
    -      # make copies so neither time is changed
    -      time1 = copy_time
    -      time2 = time.copy_time
    -      time1.synchronize time2
    -      equal = (time1.frame == time2.frame)
    -    end
    -  end
    -  equal
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - less_than?(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 62
    -def less_than? time 
    -  less = false
    -  if valid? and time and time.respond_to?(:valid) and time.valid? then
    -    if @fps == time.fps then
    -      less = (@frame < time.frame)
    -    else
    -      # make copies so neither time is changed
    -      time1 = copy_time
    -      time2 = time.copy_time
    -      time1.synchronize time2
    -      less = (time1.frame <  time2.frame)
    -    end
    -  end
    -  less 
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - max(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 77
    -def max time
    -  if time and time.valid? then
    -    synchronize time
    -    @frame = [time.frame, @frame].max
    -  end
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - min(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 83
    -def min time
    -  if time and time.respond_to?(:valid) and time.valid? then
    -    synchronize time
    -    @frame = [time.frame, @frame].min
    -  end
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - multiply(number, rounding = :round) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 89
    -def multiply(number, rounding = :round)
    -  number = number.to_f if number.respond_to? :to_f
    -  @frame = (@frame.to_f * number).send(rounding)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - ratio(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 93
    -def ratio time
    -  n = 0
    -  if valid? and time and time.respond_to?(:valid) and time.valid? then
    -    if (@fps == time.fps) 
    -      n = @frame.to_f / time.frame.to_f
    -    else
    -      # make copies so neither time is changed
    -      time1 = copy_time
    -      time2 = time.copy_time
    -      time1.synchronize time2
    -      n = time1.frame.to_f / time2.frame.to_f
    -    end
    -  end
    -  n
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - scale(rate, rounding = :round) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 108
    -def scale(rate, rounding = :round)
    -  rate = rate.to_i if rate.respond_to? :to_i
    -  if 0 < rate and rate != @fps then
    -    if 0 < @fps
    -      floated = @frame.to_f / (@fps.to_f / rate.to_f)
    -      floated = floated.send(rounding) if rounding
    -      @frame = floated
    -    end
    -    @fps = rate
    -  end
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - subtract(time) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 119
    -def subtract time
    -  synchronize time
    -  subtracted = time.frame
    -  subtracted -= subtracted - @frame if subtracted > @frame
    -  @frame -= subtracted
    -  subtracted
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - synchronize(time, rounding = :round) - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 126
    -def synchronize(time, rounding = :round)
    -  if time and time.respond_to?(:fps) and time.respond_to?(:scale) then
    -    if time.fps != @fps then
    -      gcf = __lcm(time.fps, @fps)
    -      scale(gcf, rounding)
    -      time.scale(gcf, rounding)
    -    end
    -  end
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - valid?() - - click to toggle source - -
    - - -
    - - - - - - -
    -
    # File lib/utils/frame_time.rb, line 135
    -def valid?
    -  (0 < @fps and 0 <= @frame)
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - -
    - - - - diff --git a/doc/MovieMasher/Gain.html b/doc/MovieMasher/Gain.html index e4d8138..5c86f7c 100644 --- a/doc/MovieMasher/Gain.html +++ b/doc/MovieMasher/Gain.html @@ -49,7 +49,7 @@

    @@ -100,6 +98,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -160,6 +160,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -168,8 +170,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Graph.html b/doc/MovieMasher/Graph.html index ae56faa..0689bea 100644 --- a/doc/MovieMasher/Graph.html +++ b/doc/MovieMasher/Graph.html @@ -96,9 +96,7 @@

    Pages

    @@ -124,6 +122,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -184,6 +184,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -192,8 +194,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/GraphMash.html b/doc/MovieMasher/GraphMash.html index f70a523..64fa47f 100644 --- a/doc/MovieMasher/GraphMash.html +++ b/doc/MovieMasher/GraphMash.html @@ -92,9 +92,7 @@

    Pages

    @@ -120,6 +118,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -180,6 +180,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -188,8 +190,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/GraphRaw.html b/doc/MovieMasher/GraphRaw.html index dd2aae9..98897ff 100644 --- a/doc/MovieMasher/GraphRaw.html +++ b/doc/MovieMasher/GraphRaw.html @@ -88,9 +88,7 @@

    Pages

    @@ -116,6 +114,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -176,6 +176,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -184,8 +186,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/JobHash.html b/doc/MovieMasher/Hashable.html similarity index 83% rename from doc/MovieMasher/JobHash.html rename to doc/MovieMasher/Hashable.html index 07e8fd5..941edf5 100644 --- a/doc/MovieMasher/JobHash.html +++ b/doc/MovieMasher/Hashable.html @@ -4,7 +4,7 @@ -module MovieMasher::JobHash - RDoc Documentation +module MovieMasher::Hashable - RDoc Documentation @@ -49,7 +49,7 @@

    @@ -77,10 +77,14 @@

    Methods

  • #identifier +
  • #keys +
  • #to_hash
  • #to_json +
  • #values + @@ -92,9 +96,7 @@

    Pages

    @@ -120,6 +122,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -180,6 +184,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -188,8 +194,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -227,7 +231,7 @@

    Class and Module Index

    -

    module MovieMasher::JobHash

    +

    module MovieMasher::Hashable

    @@ -272,11 +276,11 @@

    Public Class Methods

    -
    # File lib/job_hash.rb, line 29
    +            
    # File lib/util/hashable.rb, line 29
     def initialize hash
       hash = Hash.new unless hash and hash.is_a? Hash
       @hash = hash
    -  @identifier = UUID.new.generate
    +  @identifier = UUID.new.generate if defined? UUID
     end
    @@ -319,7 +323,7 @@

    Public Instance Methods

    -
    # File lib/job_hash.rb, line 10
    +            
    # File lib/util/hashable.rb, line 10
     def [] symbol
       @hash[symbol]
     end
    @@ -361,7 +365,7 @@

    Public Instance Methods

    -
    # File lib/job_hash.rb, line 19
    +            
    # File lib/util/hashable.rb, line 19
     def []=(symbol, value)
       @hash[symbol] = value
     end
    @@ -394,7 +398,7 @@

    Public Instance Methods

    -
    # File lib/job_hash.rb, line 23
    +            
    # File lib/util/hashable.rb, line 23
     def class_symbol
       self.class.name.downcase.split('::').last.to_sym
     end
    @@ -430,7 +434,7 @@

    Public Instance Methods

    -
    # File lib/job_hash.rb, line 27
    +            
    # File lib/util/hashable.rb, line 27
     def identifier; @identifier; end
    @@ -442,6 +446,39 @@

    Public Instance Methods

    +
    + +
    + keys() + + click to toggle source + +
    + + +
    + + + + + + +
    +
    # File lib/util/hashable.rb, line 42
    +def keys
    +  @hash.keys
    +end
    +
    + +
    + + + + +
    + +
    @@ -461,7 +498,7 @@

    Public Instance Methods

    -
    # File lib/job_hash.rb, line 35
    +            
    # File lib/util/hashable.rb, line 35
     def to_hash
       Marshal.load(Marshal.dump(@hash))
     end
    @@ -494,7 +531,7 @@

    Public Instance Methods

    -
    # File lib/job_hash.rb, line 39
    +            
    # File lib/util/hashable.rb, line 39
     def to_json state = nil
       @hash.to_json state
     end
    @@ -508,6 +545,39 @@

    Public Instance Methods

    +
    + +
    + values() + + click to toggle source + +
    + + +
    + + + + + + +
    +
    # File lib/util/hashable.rb, line 45
    +def values
    +  @hash.values
    +end
    +
    + +
    + + + + +
    + + diff --git a/doc/MovieMasher/Info.html b/doc/MovieMasher/Info.html index 4695e7f..96856f5 100644 --- a/doc/MovieMasher/Info.html +++ b/doc/MovieMasher/Info.html @@ -49,7 +49,7 @@

    @@ -71,9 +71,7 @@

    Pages

    @@ -99,6 +97,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -159,6 +159,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -167,8 +169,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Input.html b/doc/MovieMasher/Input.html index f58a5c2..e5b323e 100644 --- a/doc/MovieMasher/Input.html +++ b/doc/MovieMasher/Input.html @@ -73,7 +73,7 @@

    Included Modules

    @@ -153,9 +153,7 @@

    Pages

    @@ -181,6 +179,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -241,6 +241,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -249,8 +251,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -1251,7 +1251,7 @@

    Public Instance Methods

    Inputs of TypeMash can point to anything that responds with a JSON formatted mash. After download they will pass the parsed Hash to MovieMasher::JobHash.new and reset +href="Hashable.html#method-c-new">MovieMasher::Hashable.new and reset their source to the returned instance. Alternatively, source can be initially set to a Hash/Mash so as to avoid download.

    @@ -1266,7 +1266,7 @@

    Public Instance Methods

    href="Mash.html">Mash. The former is sent to MovieMasher::Source.create while the later is sent to MovieMasher::JobHash.new.

    +href="Hashable.html#method-c-new">MovieMasher::Hashable.new.

    Returns

    A Source object or, for

    @@ -70,9 +70,7 @@

    Pages

    @@ -98,6 +96,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -158,6 +158,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -166,8 +168,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Job.html b/doc/MovieMasher/Job.html index 7ae0c8f..e3d3e35 100644 --- a/doc/MovieMasher/Job.html +++ b/doc/MovieMasher/Job.html @@ -72,7 +72,7 @@

    Included Modules

    @@ -87,6 +87,12 @@

    Methods

  • ::new +
  • ::resolved_hash + +
  • ::resolved_string + +
  • ::string_type +
  • #base_source
  • #callbacks @@ -122,9 +128,7 @@

    Pages

    @@ -150,6 +154,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -210,6 +216,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -218,8 +226,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -327,24 +333,25 @@

    Public Class Methods

    -
    # File lib/job.rb, line 632
    +            
    # File lib/job.rb, line 652
     def initialize hash_or_path, configuration = nil
       @logger = nil
       @audio_graphs = nil
       @video_graphs = nil
       @configuration = configuration || Hash.new
    -  super Job.__hash_from_path hash_or_path
    +  super Job.resolved_hash hash_or_path
       @outputs_desire = Job.__init_hash @hash
       path_job = __path_job
       __file_safe path_job
       # write massaged job json to job directory
    -  File.write(Path.concat(path_job, 'job.json'), @hash.to_json) 
    +  path_job = Path.concat(path_job, 'job.json')
    +  File.open(path_job, 'w') { |f| f << @hash.to_json }  
       # if we encountered a parsing error, log it
       log_entry(:error) { @hash[:error] } if @hash[:error]
     end
    @@ -358,6 +365,140 @@

    Public Class Methods

    +
    + +
    + resolved_hash(hash_or_path) + + click to toggle source + +
    + + +
    + + + + + + +
    +
    # File lib/job.rb, line 20
    +def self.resolved_hash hash_or_path
    +  data = Hash.new
    +  if hash_or_path.is_a? String
    +    hash_or_path = resolved_string hash_or_path
    +    if hash_or_path
    +      begin
    +        case string_type hash_or_path
    +        when 'yaml'
    +          data = YAML::load hash_or_path
    +        when 'json'
    +          data = JSON.parse hash_or_path
    +        else
    +          data[:error] = "unsupported configuration file type #{hash_or_path}"
    +        end
    +      rescue Exception => e
    +        data[:error] = "job file could not be parsed: #{e.message}" 
    +      end
    +    else
    +      data[:error] = "job file could not be found: #{hash_or_path}" 
    +    end
    +  else
    +    data = Marshal.load(Marshal.dump(hash_or_path)) if hash_or_path.is_a? Hash
    +  end
    +  __hash_keys_to_symbols! data
    +  data
    +end
    +
    + +
    + + + + +
    + + +
    + +
    + resolved_string(hash_or_path) + + click to toggle source + +
    + + +
    + + + + + + +
    +
    # File lib/job.rb, line 46
    +def self.resolved_string hash_or_path
    +  case string_type hash_or_path
    +  when 'json', 'yaml'
    +    hash_or_path 
    +  else
    +    (File.exists? hash_or_path ? File.read(hash_or_path) : nil)
    +  end
    +end
    +
    + +
    + + + + +
    + + +
    + +
    + string_type(hash_or_path) + + click to toggle source + +
    + + +
    + + + + + + +
    +
    # File lib/job.rb, line 54
    +def self.string_type hash_or_path
    +  case hash_or_path[0]
    +  when '{', '['
    +    'json'
    +  when '-'
    +    'yaml'
    +  else
    +    nil
    +  end
    +end
    +
    + +
    + + + + +
    + +
    @@ -388,7 +529,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 613
    +            
    # File lib/job.rb, line 633
     def base_source; _get __method__; end
    @@ -422,7 +563,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 615
    +            
    # File lib/job.rb, line 635
     def callbacks; _get __method__; end
    @@ -457,7 +598,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 617
    +            
    # File lib/job.rb, line 637
     def destination; _get __method__; end
    @@ -495,7 +636,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 624
    +            
    # File lib/job.rb, line 644
     def error; _get __method__; end
    @@ -533,7 +674,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 627
    +            
    # File lib/job.rb, line 647
     def id; _get __method__; end
    @@ -567,7 +708,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 647
    +            
    # File lib/job.rb, line 668
     def inputs; _get __method__; end
    @@ -601,7 +742,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 649
    +            
    # File lib/job.rb, line 670
     def log
       proc = _get(__method__)
       proc.call
    @@ -645,14 +786,14 @@ 

    Public Instance Methods

    -
    # File lib/job.rb, line 658
    +            
    # File lib/job.rb, line 679
     def log_entry type, &proc
       @hash[:error] = proc.call if :error == type
       logger_job = __logger
       if logger_job and logger_job.send (type.id2name + '?').to_sym
         logger_job.send(type, &proc)
       end
    -  puts proc.call if 'debug' == @configuration[:log_level]
    +  puts proc.call if 'debug' == @configuration[:verbose]
     end
    @@ -689,7 +830,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 670
    +            
    # File lib/job.rb, line 691
     def module_source; _get __method__; end
    @@ -723,7 +864,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 667
    +            
    # File lib/job.rb, line 688
     def outputs; _get __method__; end
    @@ -765,7 +906,7 @@

    Public Instance Methods

    -
    # File lib/job.rb, line 679
    +            
    # File lib/job.rb, line 700
     def process 
       rescued_exception = nil
       begin
    @@ -854,7 +995,7 @@ 

    Public Instance Methods

    -
    # File lib/job.rb, line 722
    +            
    # File lib/job.rb, line 743
     def progress; _get __method__; end
    diff --git a/doc/MovieMasher/Layer.html b/doc/MovieMasher/Layer.html index 40d4123..c2210b4 100644 --- a/doc/MovieMasher/Layer.html +++ b/doc/MovieMasher/Layer.html @@ -98,9 +98,7 @@

    Pages

    @@ -126,6 +124,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -186,6 +186,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -194,8 +196,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/LayerColor.html b/doc/MovieMasher/LayerColor.html index 110b662..3ad9953 100644 --- a/doc/MovieMasher/LayerColor.html +++ b/doc/MovieMasher/LayerColor.html @@ -92,9 +92,7 @@

    Pages

    @@ -120,6 +118,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -180,6 +180,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -188,8 +190,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/LayerModule.html b/doc/MovieMasher/LayerModule.html index 4f45346..9543a00 100644 --- a/doc/MovieMasher/LayerModule.html +++ b/doc/MovieMasher/LayerModule.html @@ -86,9 +86,7 @@

    Pages

    @@ -114,6 +112,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -174,6 +174,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -182,8 +184,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/LayerRaw.html b/doc/MovieMasher/LayerRaw.html index 82a1112..d0ab049 100644 --- a/doc/MovieMasher/LayerRaw.html +++ b/doc/MovieMasher/LayerRaw.html @@ -86,9 +86,7 @@

    Pages

    @@ -114,6 +112,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -174,6 +174,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -182,8 +184,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/LayerRawImage.html b/doc/MovieMasher/LayerRawImage.html index a28f104..541fe4c 100644 --- a/doc/MovieMasher/LayerRawImage.html +++ b/doc/MovieMasher/LayerRawImage.html @@ -88,9 +88,7 @@

    Pages

    @@ -116,6 +114,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -176,6 +176,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -184,8 +186,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/LayerRawVideo.html b/doc/MovieMasher/LayerRawVideo.html index 805f23a..4cf63f0 100644 --- a/doc/MovieMasher/LayerRawVideo.html +++ b/doc/MovieMasher/LayerRawVideo.html @@ -90,9 +90,7 @@

    Pages

    @@ -118,6 +116,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -178,6 +178,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -186,8 +188,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/LayerTheme.html b/doc/MovieMasher/LayerTheme.html index f85d071..b91e85c 100644 --- a/doc/MovieMasher/LayerTheme.html +++ b/doc/MovieMasher/LayerTheme.html @@ -86,9 +86,7 @@

    Pages

    @@ -114,6 +112,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -174,6 +174,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -182,8 +184,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/LayerTransition.html b/doc/MovieMasher/LayerTransition.html index f50e678..f43a856 100644 --- a/doc/MovieMasher/LayerTransition.html +++ b/doc/MovieMasher/LayerTransition.html @@ -92,9 +92,7 @@

    Pages

    @@ -120,6 +118,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -180,6 +180,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -188,8 +190,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Mash.html b/doc/MovieMasher/Mash.html index 8af3dab..c84fdc5 100644 --- a/doc/MovieMasher/Mash.html +++ b/doc/MovieMasher/Mash.html @@ -50,7 +50,7 @@

    Defined In

    • lib/mash.rb -
    • lib/utils/filter_helpers.rb +
    • lib/util/filter_helpers.rb
    @@ -73,7 +73,7 @@

    Included Modules

    @@ -127,9 +127,7 @@

    Pages

    @@ -155,6 +153,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -215,6 +215,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -223,8 +225,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Method.html b/doc/MovieMasher/Method.html index 863c4bf..49d488b 100644 --- a/doc/MovieMasher/Method.html +++ b/doc/MovieMasher/Method.html @@ -49,7 +49,7 @@

    @@ -71,9 +71,7 @@

    Pages

    @@ -99,6 +97,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -159,6 +159,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -167,8 +169,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Output.html b/doc/MovieMasher/Output.html index d92ac3c..a833e8c 100644 --- a/doc/MovieMasher/Output.html +++ b/doc/MovieMasher/Output.html @@ -72,7 +72,7 @@

    Included Modules

    @@ -172,9 +172,7 @@

    Pages

    @@ -200,6 +198,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -260,6 +260,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -268,8 +270,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/Path.html b/doc/MovieMasher/Path.html index f20dde6..91fb628 100644 --- a/doc/MovieMasher/Path.html +++ b/doc/MovieMasher/Path.html @@ -49,7 +49,7 @@

    @@ -92,9 +92,7 @@

    Pages

    @@ -120,6 +118,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -180,6 +180,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -188,8 +190,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -283,7 +283,7 @@

    Public Class Methods

    -
    # File lib/utils/path.rb, line 7
    +            
    # File lib/util/path.rb, line 7
     def self.add_slash_end s
       s = '' unless s
       s = "#{s}#{Slash}" unless s.end_with? Slash
    @@ -318,7 +318,7 @@ 

    Public Class Methods

    -
    # File lib/utils/path.rb, line 12
    +            
    # File lib/util/path.rb, line 12
     def self.add_slash_start s
       s = '' unless s
       s = "#{Slash}#{s}" unless s.start_with? Slash
    @@ -353,7 +353,7 @@ 

    Public Class Methods

    -
    # File lib/utils/path.rb, line 4
    +            
    # File lib/util/path.rb, line 4
     def self.add_slashes s
       add_slash_start(add_slash_end(s))
     end
    @@ -386,7 +386,7 @@

    Public Class Methods

    -
    # File lib/utils/path.rb, line 17
    +            
    # File lib/util/path.rb, line 17
     def self.concat s1, s2
       s1 = '' unless s1
       s2 = '' unless s2
    @@ -426,7 +426,7 @@ 

    Public Class Methods

    -
    # File lib/utils/path.rb, line 30
    +            
    # File lib/util/path.rb, line 30
     def self.strip_slash_end s
       s = '' unless s
       s = s[0..-2] if s.end_with? Slash
    @@ -461,7 +461,7 @@ 

    Public Class Methods

    -
    # File lib/utils/path.rb, line 35
    +            
    # File lib/util/path.rb, line 35
     def self.strip_slash_start s
       s = '' unless s
       s = s[1..-1] if s.start_with? Slash
    @@ -496,7 +496,7 @@ 

    Public Class Methods

    -
    # File lib/utils/path.rb, line 27
    +            
    # File lib/util/path.rb, line 27
     def self.strip_slashes s
       strip_slash_start(strip_slash_end(s))
     end
    diff --git a/doc/MovieMasher/Set.html b/doc/MovieMasher/Set.html deleted file mode 100644 index e9d28dc..0000000 --- a/doc/MovieMasher/Set.html +++ /dev/null @@ -1,455 +0,0 @@ - - - - - - -module MovieMasher::Set - RDoc Documentation - - - - - - - - - - - - - - - - -
    -

    module MovieMasher::Set

    - -
    - -

    Mix-in functionality for mocking a Hash.

    - -
    - - - - -
    - - - - - - - - - - -
    -

    Public Class Methods

    - - -
    - -
    - new(hash) - - click to toggle source - -
    - - -
    - -

    Set the actual Hash when creating.

    - - - - -
    -
    # File lib/set.rb, line 23
    -def initialize hash
    -  hash = Hash.new unless hash and hash.is_a? Hash
    -  @hash = hash
    -end
    -
    - -
    - - - - -
    - - -
    - -
    -

    Public Instance Methods

    - - -
    - -
    - [](symbol) - - click to toggle source - -
    - - -
    - -

    Convenience getter for underlying data Hash.

    -
    symbol -
    -

    Symbol key into hash.

    -
    - -

    Returns value of key or nil if no such key exists.

    - - - - -
    -
    # File lib/set.rb, line 10
    -def [] symbol
    -  @hash[symbol]
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - []=(symbol, value) - - click to toggle source - -
    - - -
    - -

    Convenience setter for underlying data Hash.

    -
    symbol -
    -

    Symbol key into hash.

    -
    value -
    -

    Object to set at key.

    -
    - -

    Returns value.

    - - - - -
    -
    # File lib/set.rb, line 19
    -def []=(symbol, value)
    -  @hash[symbol] = value
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - to_hash() - - click to toggle source - -
    - - -
    - -

    Return deep copy of underlying Hash.

    - - - - -
    -
    # File lib/set.rb, line 28
    -def to_hash
    -  Marshal.load(Marshal.dump(@hash))
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - to_json(state) - - click to toggle source - -
    - - -
    - -

    Return underlying Hash in JSON format.

    - - - - -
    -
    # File lib/set.rb, line 32
    -def to_json state
    -  @hash.to_json state
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - -
    - - - - diff --git a/doc/MovieMasher/Source.html b/doc/MovieMasher/Source.html index 2f98a35..0b90886 100644 --- a/doc/MovieMasher/Source.html +++ b/doc/MovieMasher/Source.html @@ -94,9 +94,7 @@

    Pages

    @@ -122,6 +120,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -182,6 +182,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -190,8 +192,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/MovieMasher/SourceRelative.html b/doc/MovieMasher/SourceRelative.html deleted file mode 100644 index 540e4e6..0000000 --- a/doc/MovieMasher/SourceRelative.html +++ /dev/null @@ -1,316 +0,0 @@ - - - - - - -class MovieMasher::SourceRelative - RDoc Documentation - - - - - - - - - - - - - - - - -
    -

    class MovieMasher::SourceRelative

    - -
    - -

    MovieMasher::Job#base_source/Job#module_source -and base_source at -Input/Input#module_source for TypeMash inputs, describing how to -retrieve assets with relative paths for sources.

    - -

    When MovieMasher::Input#source or -Media#source is a String that is a relative path, then it is resolved using -the absolute path derived from a SourceRelative object. If the asset is Media -of TypeFont then MovieMasher::Input#module_source -is used if defined, otherwise MovieMasher::Job#module_source. -For other assets MovieMasher::Input#base_source -is used if defined, otherwise MovieMasher::Job#base_source.

    - -
    - - - - -
    - - - - - - - - - - -
    -

    Public Class Methods

    - - -
    - -
    - create(hash) - - click to toggle source - -
    - - -
    - -

    Returns a new instance.

    - - - - -
    -
    # File lib/source_relative.rb, line 11
    -def self.create hash
    -  SourceRelative.new hash
    -end
    -
    - -
    - - - - -
    - - -
    - -
    - -
    - - - - diff --git a/doc/MovieMasher/TimeRange.html b/doc/MovieMasher/TimeRange.html index 1d3f935..5a75079 100644 --- a/doc/MovieMasher/TimeRange.html +++ b/doc/MovieMasher/TimeRange.html @@ -49,7 +49,7 @@

    @@ -114,9 +114,7 @@

    Pages

    @@ -142,6 +140,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -202,6 +202,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -210,8 +212,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -292,7 +292,7 @@

    Public Class Methods

    -
    # File lib/utils/time_range.rb, line 63
    +            
    # File lib/util/time_range.rb, line 63
     def initialize (start = 0, rate = 0, length = 1)
       @length = length #.to_i
       @start = start.to_i
    @@ -333,7 +333,7 @@ 

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 42
    +            
    # File lib/util/time_range.rb, line 42
     def dup
       TimeRange.new @start, @length, @rate
     end
    @@ -366,7 +366,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 45
    +            
    # File lib/util/time_range.rb, line 45
     def end_seconds
       TimeRange.new(stop, rate).start_seconds
     end
    @@ -399,7 +399,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 48
    +            
    # File lib/util/time_range.rb, line 48
     def equals? range
       equal = false
       if range and 0 < range.rate and 0 <= range.start then
    @@ -444,7 +444,7 @@ 

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 68
    +            
    # File lib/util/time_range.rb, line 68
     def intersection range
       result = nil
       range1 = self
    @@ -490,7 +490,7 @@ 

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 84
    +            
    # File lib/util/time_range.rb, line 84
     def length
       @length
     end
    @@ -523,7 +523,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 87
    +            
    # File lib/util/time_range.rb, line 87
     def length= n
       @length = n
     end
    @@ -556,7 +556,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 90
    +            
    # File lib/util/time_range.rb, line 90
     def length_seconds(precision = 3)
       FloatUtil.precision((@length.to_f / @rate.to_f), precision)
     end
    @@ -589,7 +589,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 93
    +            
    # File lib/util/time_range.rb, line 93
     def rate
       @rate
     end
    @@ -622,7 +622,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 96
    +            
    # File lib/util/time_range.rb, line 96
     def rate= n
       @rate = n
     end
    @@ -655,7 +655,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 99
    +            
    # File lib/util/time_range.rb, line 99
     def start
       @start
     end
    @@ -688,7 +688,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 102
    +            
    # File lib/util/time_range.rb, line 102
     def start= n
       @start = n
     end
    @@ -721,7 +721,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 105
    +            
    # File lib/util/time_range.rb, line 105
     def start_seconds precision = 3
       FloatUtil.precision((@start.to_f / @rate.to_f), precision)
     end
    @@ -754,7 +754,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 108
    +            
    # File lib/util/time_range.rb, line 108
     def stop
       start + length
     end
    @@ -787,7 +787,7 @@

    Public Instance Methods

    -
    # File lib/utils/time_range.rb, line 111
    +            
    # File lib/util/time_range.rb, line 111
     def synchronize(time, rounding = :round)
       if time and time.respond_to?(:rate) and time.respond_to?(:scale) then
         if time.rate != @rate then
    diff --git a/doc/MovieMasher/Transfer.html b/doc/MovieMasher/Transfer.html
    index 92607db..737e8a9 100644
    --- a/doc/MovieMasher/Transfer.html
    +++ b/doc/MovieMasher/Transfer.html
    @@ -72,7 +72,7 @@ 

    Included Modules

    @@ -142,9 +142,7 @@

    Pages

    @@ -170,6 +168,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -230,6 +230,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -238,8 +240,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor diff --git a/doc/created.rid b/doc/created.rid index f4f1ac5..44a3810 100644 --- a/doc/created.rid +++ b/doc/created.rid @@ -1,26 +1,26 @@ -Thu, 30 Oct 2014 08:49:21 -0400 +Tue, 18 Nov 2014 08:26:56 -0500 +./Documentation.md Tue, 18 Nov 2014 01:10:29 -0500 ./lib/callback.rb Thu, 30 Oct 2014 02:37:12 -0400 -./lib/constants/av.rb Mon, 27 Oct 2014 11:13:25 -0400 -./lib/constants/defaults.rb Thu, 30 Oct 2014 00:19:16 -0400 -./lib/constants/error.rb Mon, 27 Oct 2014 19:22:10 -0400 -./lib/constants/fill.rb Sat, 25 Oct 2014 16:09:39 -0400 -./lib/constants/gain.rb Tue, 28 Oct 2014 10:56:23 -0400 -./lib/constants/info.rb Mon, 27 Oct 2014 15:22:10 -0400 -./lib/constants/intermediate.rb Sat, 04 Oct 2014 13:59:43 -0400 -./lib/constants/method.rb Sun, 12 Oct 2014 19:11:44 -0400 +./lib/constant/av.rb Mon, 27 Oct 2014 11:13:25 -0400 +./lib/constant/defaults.rb Fri, 07 Nov 2014 21:42:23 -0500 +./lib/constant/error.rb Mon, 27 Oct 2014 19:22:10 -0400 +./lib/constant/fill.rb Sat, 25 Oct 2014 16:09:39 -0400 +./lib/constant/gain.rb Tue, 28 Oct 2014 10:56:23 -0400 +./lib/constant/info.rb Mon, 27 Oct 2014 15:22:10 -0400 +./lib/constant/intermediate.rb Sat, 04 Oct 2014 13:59:43 -0400 +./lib/constant/method.rb Sun, 12 Oct 2014 19:11:44 -0400 ./lib/graph.rb Wed, 29 Oct 2014 14:02:56 -0400 -./lib/input.rb Thu, 30 Oct 2014 02:08:11 -0400 -./lib/job.rb Thu, 30 Oct 2014 02:08:10 -0400 -./lib/job_hash.rb Wed, 29 Oct 2014 16:21:00 -0400 -./lib/mash.rb Wed, 29 Oct 2014 18:51:08 -0400 -./lib/moviemasher.rb Wed, 29 Oct 2014 23:35:29 -0400 -./lib/output.rb Thu, 30 Oct 2014 01:58:58 -0400 +./lib/input.rb Fri, 07 Nov 2014 15:25:44 -0500 +./lib/job.rb Sun, 16 Nov 2014 22:10:53 -0500 +./lib/mash.rb Fri, 07 Nov 2014 15:25:44 -0500 +./lib/moviemasher.rb Sun, 16 Nov 2014 22:14:19 -0500 +./lib/output.rb Fri, 07 Nov 2014 15:25:44 -0500 ./lib/source.rb Thu, 30 Oct 2014 02:27:05 -0400 -./lib/transfer.rb Thu, 30 Oct 2014 02:25:32 -0400 -./lib/utils/eval.rb Tue, 28 Oct 2014 20:44:59 -0400 -./lib/utils/filter_helpers.rb Tue, 28 Oct 2014 10:57:52 -0400 -./lib/utils/float_util.rb Tue, 28 Oct 2014 10:57:55 -0400 -./lib/utils/path.rb Sat, 25 Oct 2014 15:30:48 -0400 -./lib/utils/time_range.rb Wed, 29 Oct 2014 14:16:42 -0400 -./LICENSE Sat, 28 Jun 2014 09:18:43 -0400 -./README.md Thu, 30 Oct 2014 01:58:58 -0400 +./lib/transfer.rb Fri, 07 Nov 2014 15:25:44 -0500 +./lib/util/eval.rb Fri, 07 Nov 2014 15:25:44 -0500 +./lib/util/filter_helpers.rb Tue, 28 Oct 2014 10:57:52 -0400 +./lib/util/float_util.rb Tue, 28 Oct 2014 10:57:55 -0400 +./lib/util/hashable.rb Fri, 07 Nov 2014 17:00:55 -0500 +./lib/util/path.rb Sat, 25 Oct 2014 15:30:48 -0400 +./lib/util/time_range.rb Wed, 29 Oct 2014 14:16:42 -0400 +./lib/version.rb Sun, 16 Nov 2014 20:30:11 -0500 diff --git a/doc/index.html b/doc/index.html index c35d56e..00091e3 100644 --- a/doc/index.html +++ b/doc/index.html @@ -49,9 +49,7 @@

    Pages

    @@ -77,6 +75,8 @@

    Class and Module Index

  • MovieMasher::ChainScaler +
  • MovieMasher::Configuration +
  • MovieMasher::Defaults
  • MovieMasher::Error @@ -137,6 +137,8 @@

    Class and Module Index

  • MovieMasher::GraphRaw +
  • MovieMasher::Hashable +
  • MovieMasher::Info
  • MovieMasher::Input @@ -145,8 +147,6 @@

    Class and Module Index

  • MovieMasher::Job -
  • MovieMasher::JobHash -
  • MovieMasher::Layer
  • MovieMasher::LayerColor @@ -186,80 +186,38 @@

    Class and Module Index

    - moviemasher.js | angular-moviemasher -| moviemasher.rb

    +| moviemasher.rb

    Ruby library for mashing up video, images and audio utilizing FFmpeg and Ecasound

    moviemasher.rb

    +
    + +

    RDoc Documentation

    -

    Use moviemasher.rb to encode mashups of video, audio, and images from a -JSON formatted job description. A job specifies multiple media inputs to be -encoded together into one or more outputs, as well as where to find the -inputs and where to place the outputs.

    +
    Core Classes/Modules
    -

    The project aims to take the complexity out of describing common -audio/video editing operations to command line programs, which handle the -low level transcoding operations. The MovieMasher class turns your job into a series -of commands and then manages their execution.

    - -

    As part of job processing it can download media inputs from remote hosts -and upload media outputs as well. Using the same mechanisms it can also -trigger callbacks as a job is started, during its processing and when -it's completed so that external systems can be alerted.

    - -

    The project includes a rake task that can be routinely called to watch a -folder for job description files, as well as an example crontab entry that -calls it. Recall that ruby scripts run from cron lack your user's -environmental variables, so you'll probably need to edit the paths to -binary directories in the entry to match your system.

    - -

    AWS Integration

    - -

    There are optional configuration settings that support two specific Amazon -Web Services offerings: S3 for media storage and SQS for job queueing. If -set to use an SQS queue then it will be polled as part of the folder -watching process for job files. The ruby aws-sdk is utilized to interface -with SQS, so access key details can be provided in the configuration or -environmental variables or in a role if deployed on an EC2 instance.

    - -

    Similarly, aws-sdk is utilized for S3 interactions so if access key details -are present then buckets can be used either as sources for media inputs or -destinations for media outputs within job descriptions. These are -authenticated requests, so the buckets do not have to be public.

    - -

    Additionally, the Movie Masher AMI is available in Marketplace and includes -moviemasher.rb and all supporting applications. When launched it looks for -user data supplied in JSON format and merges it into the default -configuration, so it's possible to supply SQS options on startup. The -cron job described above is installed, so a configured SQS queue will -immediately start being polled for jobs. Otherwise the instance will start -up apache to serve the angular-moviemasher project, preconfigured to -utilize the local moviemasher.rb process (the instance id acts as a shared -password).

    - -

    Basic Usage

    +
    Core Usage
        require_relative 'lib/moviemasher.rb'
         job = { :inputs => [], :base_source => {}, :outputs => [], :destination => {} }
    @@ -299,111 +257,10 @@ 

    Basic Usage¶< drawtext. That last one relies on font media, the last of the modular types.

    -

    How to Install

    -
    1. -

      install ffmpeg, ecasound, sox and du programs

      -
    2. -

      install ruby and builder

      -
    3. -

      bundle install in project directory installs required gems -from Gemfile

      -
    4. -

      edit config/config.yml configuration file to match paths on system and -configure logging/debugging options

      -
    5. -

      rake moviemasher:process_queues searches watch folder and -optional SQS queue for jobs

      -
    6. -

      optionally install calling crontab entry found at config/moviemasher.cron -after checking binary paths in it

      -
    +

    To regenerate this documentation cd to project +directory and execute:

    -

    Requirements

    -
    • -

      ffmpeg with ffprobe

      -
    • -

      ecasound

      -
    • -

      sox

      -
    • -

      du

      -
    • -

      builder gem

      -
    • -

      require_all gem

      -
    • -

      json gem

      -
    • -

      uuid gem

      -
    • -

      mime-types gem

      -
    • -

      multipart-post gem

      -
    • -

      rake gem

      -
    • -

      rack gem

      -
    • -

      aws-sdk gem

      -
    - -

    Developer Setup

    -
    1. -

      uncomment entries in Gemfile related to spec tests

      -
    2. -

      bundle install from project directory installs additional gems

      -
    3. -

      rspec spec will run the core tests

      -
    4. -

      The following with regenerate the doc directory: - rdoc --visibility=public ---main='README.md' -o doc --fmt=darkfish --markup=tomdoc ---tab-width=2 --no-dcov --exclude='/spec' --exclude='/log/' ---exclude='/Gemfile' --exclude='/config/' ---exclude='/index.rb' --exclude='/doc/' ---exclude='/Rakefile'

      -
    - -
    To run tests in spec_aws
    -
    1. -

      install and launch clientside_aws

      -
    2. -

      uncomment other entries in Gemfile

      -
    3. -

      bundle install from project directory installs additional gems

      -
    - -
    Known issues in Version 4.0.08
    -
    • -

      local/sqs import/export has not been thoroughly tested

      -
    • -

      archiving of outputs not yet supported

      -
    • -

      freeze frame not yet supported

      -
    • -

      audio still being done in Ecasound

      -
    • -

      due to size considerations, video files not included in spec tests -(eventually tests will generate their own to work with)

      -
    - -
    Migrating from Version 4.0.07
    -
    • -

      The length key in clips has been renamed frames.

      -
    • -

      The audio and video keys in mash tracks have been -moved to mash.

      -
    • -

      The tracks key in mashes has been removed.

      -
    • -

      The fps key in outputs has been renamed -video_rate.

      -
    • -

      The audio_frequency key in outputs has been renamed -audio_rate.

      -
    • -

      The trim key in inputs has been renamed offset.

      -
    +
    rdoc --visibility=public -o doc --main='Documentation.md' --fmt=darkfish --markup=tomdoc --tab-width=2 --no-dcov --exclude='/spec' --exclude='/log' --exclude='/Gemfile' --exclude='/tmp' --exclude='/config' --exclude='/index.rb' --exclude='/doc' --exclude='/bin' --exclude='/Rakefile' --exclude='/Docker' --exclude='/README' --exclude='/LICENSE'

    diff --git a/doc/js/search_index.js b/doc/js/search_index.js index 24fcd90..6659da6 100644 --- a/doc/js/search_index.js +++ b/doc/js/search_index.js @@ -1 +1 @@ -var search_data = {"index":{"searchIndex":["moviemasher","av","callback","chain","chaineffects","chainmodule","chainoverlay","chainscaler","defaults","error","configuration","critical","job","jobinput","joboutput","jobrender","jobsource","jobupload","object","parameter","runtime","state","todo","evaluate","fill","filter","filterevaluated","filterhash","filterhelpers","filtersetpts","filtersource","filtersourcecolor","filtersourcemovie","floatutil","gain","graph","graphmash","graphraw","info","input","intermediate","job","jobhash","layer","layercolor","layermodule","layerraw","layerrawimage","layerrawvideo","layertheme","layertransition","mash","method","output","path","source","timerange","transfer","<<()","[]()","[]=()","__coerce()","__command_name_value()","__filter_dimension_keys()","__filter_is_source?()","__filter_parse_scope_value()","__filter_scope_binding()","__filter_trim_input()","add_new_layer()","add_new_layer()","add_slash_end()","add_slash_start()","add_slashes()","audio()","audio_bitrate()","audio_bitrate=()","audio_codec()","audio_codec=()","audio_rate()","audio_rate=()","av()","av()","backcolor()","backcolor=()","base_source()","base_source()","bucket()","bucket=()","callbacks()","chain_command()","chain_command()","chain_command()","class_symbol()","clip_has_audio()","clips_having_audio()","clips_in_range()","cmp()","color_value()","command_parameters()","concat()","configuration()","configure()","create()","create()","create()","create()","create()","create_layer()","data()","data=()","destination()","destination()","destination=()","dimensions()","dimensions()","dimensions=()","dimensions=()","directory()","directory=()","dup()","duration()","duration()","duration()","duration=()","end_seconds()","equals?()","equation()","error()","extension()","extension()","extension()","extension=()","extension=()","extension=()","fill()","fill=()","filter_command()","filter_command()","filter_command()","filter_command()","filter_command()","filter_name()","filter_name()","filter_name()","forecolor()","forecolor=()","gain()","gain=()","gain_changes()","graph_command()","graph_command()","graph_command()","graph_scope()","graph_scope()","gtr()","gtre()","has_audio?()","has_video?()","hash()","hash?()","host()","host=()","id()","identifier()","includes?()","initialize_chains()","initialize_chains()","initialize_chains()","initialize_chains()","initialize_chains()","initialize_filters()","initialize_filters()","initialize_filters()","initialize_filters()","input_scope()","inputs()","intersection()","layer_command()","layer_command()","layer_command()","layer_command()","layer_command()","layer_command()","layer_scope()","layer_scope()","length()","length()","length=()","length=()","length_seconds()","less()","log()","log_entry()","loop()","loop=()","max()","media()","media()","media_count_for_clips()","media_search()","merge()","merger_command()","method()","method=()","min()","mm_cmp()","mm_dir_horz()","mm_dir_vert()","mm_fontfamily()","mm_fontfile()","mm_horz()","mm_max()","mm_min()","mm_paren()","mm_textfile()","mm_vert()","module_for_type()","module_source()","module_source()","name()","name()","name()","name=()","name=()","name=()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","no_audio()","no_audio()","no_audio=()","no_audio=()","no_video()","no_video=()","object()","offset()","offset=()","outputs()","parameters()","parameters=()","pass()","pass=()","path()","path()","path=()","path=()","port()","port=()","precision()","precision()","precision=()","process()","process()","process_queues()","progress()","progress_seconds()","progress_seconds=()","quality()","quality=()","range()","range()","rate()","rate=()","region()","region=()","required()","required=()","rgb()","rgba()","sort()","source()","source=()","start()","start()","start=()","start=()","start_seconds()","stop()","string()","strip_slash_end()","strip_slash_start()","strip_slashes()","synchronize()","to_hash()","to_json()","to_s()","trigger()","trigger=()","trim_command()","trim_command()","type()","type()","type()","type=()","type=()","type=()","user()","user=()","value()","video()","video_bitrate()","video_bitrate=()","video_codec()","video_codec=()","video_format()","video_format=()","video_ranges()","license","readme"],"longSearchIndex":["moviemasher","moviemasher::av","moviemasher::callback","moviemasher::chain","moviemasher::chaineffects","moviemasher::chainmodule","moviemasher::chainoverlay","moviemasher::chainscaler","moviemasher::defaults","moviemasher::error","moviemasher::error::configuration","moviemasher::error::critical","moviemasher::error::job","moviemasher::error::jobinput","moviemasher::error::joboutput","moviemasher::error::jobrender","moviemasher::error::jobsource","moviemasher::error::jobupload","moviemasher::error::object","moviemasher::error::parameter","moviemasher::error::runtime","moviemasher::error::state","moviemasher::error::todo","moviemasher::evaluate","moviemasher::fill","moviemasher::filter","moviemasher::filterevaluated","moviemasher::filterhash","moviemasher::filterhelpers","moviemasher::filtersetpts","moviemasher::filtersource","moviemasher::filtersourcecolor","moviemasher::filtersourcemovie","moviemasher::floatutil","moviemasher::gain","moviemasher::graph","moviemasher::graphmash","moviemasher::graphraw","moviemasher::info","moviemasher::input","moviemasher::intermediate","moviemasher::job","moviemasher::jobhash","moviemasher::layer","moviemasher::layercolor","moviemasher::layermodule","moviemasher::layerraw","moviemasher::layerrawimage","moviemasher::layerrawvideo","moviemasher::layertheme","moviemasher::layertransition","moviemasher::mash","moviemasher::method","moviemasher::output","moviemasher::path","moviemasher::source","moviemasher::timerange","moviemasher::transfer","moviemasher::chain#<<()","moviemasher::jobhash#[]()","moviemasher::jobhash#[]=()","moviemasher::filterevaluated#__coerce()","moviemasher::filterevaluated#__command_name_value()","moviemasher::filterevaluated#__filter_dimension_keys()","moviemasher::filterevaluated#__filter_is_source?()","moviemasher::filterevaluated#__filter_parse_scope_value()","moviemasher::filterevaluated#__filter_scope_binding()","moviemasher::layerrawvideo#__filter_trim_input()","moviemasher::graphmash#add_new_layer()","moviemasher::layertransition#add_new_layer()","moviemasher::path::add_slash_end()","moviemasher::path::add_slash_start()","moviemasher::path::add_slashes()","moviemasher::mash#audio()","moviemasher::output#audio_bitrate()","moviemasher::output#audio_bitrate=()","moviemasher::output#audio_codec()","moviemasher::output#audio_codec=()","moviemasher::output#audio_rate()","moviemasher::output#audio_rate=()","moviemasher::input#av()","moviemasher::output#av()","moviemasher::output#backcolor()","moviemasher::output#backcolor=()","moviemasher::input#base_source()","moviemasher::job#base_source()","moviemasher::transfer#bucket()","moviemasher::transfer#bucket=()","moviemasher::job#callbacks()","moviemasher::chain#chain_command()","moviemasher::chainmodule#chain_command()","moviemasher::chainscaler#chain_command()","moviemasher::jobhash#class_symbol()","moviemasher::mash::clip_has_audio()","moviemasher::mash::clips_having_audio()","moviemasher::mash::clips_in_range()","moviemasher::floatutil::cmp()","moviemasher::graph::color_value()","moviemasher::filterevaluated#command_parameters()","moviemasher::path::concat()","moviemasher::configuration()","moviemasher::configure()","moviemasher::callback::create()","moviemasher::input::create()","moviemasher::output::create()","moviemasher::source::create()","moviemasher::transfer::create()","moviemasher::graph#create_layer()","moviemasher::callback#data()","moviemasher::callback#data=()","moviemasher::job#destination()","moviemasher::output#destination()","moviemasher::output#destination=()","moviemasher::input#dimensions()","moviemasher::output#dimensions()","moviemasher::input#dimensions=()","moviemasher::output#dimensions=()","moviemasher::transfer#directory()","moviemasher::transfer#directory=()","moviemasher::timerange#dup()","moviemasher::graph#duration()","moviemasher::input#duration()","moviemasher::mash::duration()","moviemasher::input#duration=()","moviemasher::timerange#end_seconds()","moviemasher::timerange#equals?()","moviemasher::evaluate::equation()","moviemasher::job#error()","moviemasher::callback#extension()","moviemasher::output#extension()","moviemasher::source#extension()","moviemasher::callback#extension=()","moviemasher::output#extension=()","moviemasher::source#extension=()","moviemasher::input#fill()","moviemasher::input#fill=()","moviemasher::filter#filter_command()","moviemasher::filterevaluated#filter_command()","moviemasher::filterhash#filter_command()","moviemasher::filtersource#filter_command()","moviemasher::filtersourcecolor#filter_command()","moviemasher::filter#filter_name()","moviemasher::filtersourcecolor#filter_name()","moviemasher::filtersourcemovie#filter_name()","moviemasher::output#forecolor()","moviemasher::output#forecolor=()","moviemasher::input#gain()","moviemasher::input#gain=()","moviemasher::mash::gain_changes()","moviemasher::graph#graph_command()","moviemasher::graphmash#graph_command()","moviemasher::graphraw#graph_command()","moviemasher::graph#graph_scope()","moviemasher::graphmash#graph_scope()","moviemasher::floatutil::gtr()","moviemasher::floatutil::gtre()","moviemasher::mash::has_audio?()","moviemasher::mash::has_video?()","moviemasher::filterhash#hash()","moviemasher::mash::hash?()","moviemasher::transfer#host()","moviemasher::transfer#host=()","moviemasher::job#id()","moviemasher::jobhash#identifier()","moviemasher::av::includes?()","moviemasher::layer#initialize_chains()","moviemasher::layerrawimage#initialize_chains()","moviemasher::layerrawvideo#initialize_chains()","moviemasher::layertheme#initialize_chains()","moviemasher::layertransition#initialize_chains()","moviemasher::chain#initialize_filters()","moviemasher::chaineffects#initialize_filters()","moviemasher::chainmodule#initialize_filters()","moviemasher::chainoverlay#initialize_filters()","moviemasher::chainmodule#input_scope()","moviemasher::job#inputs()","moviemasher::timerange#intersection()","moviemasher::layer#layer_command()","moviemasher::layercolor#layer_command()","moviemasher::layerraw#layer_command()","moviemasher::layerrawimage#layer_command()","moviemasher::layerrawvideo#layer_command()","moviemasher::layertransition#layer_command()","moviemasher::layer#layer_scope()","moviemasher::layermodule#layer_scope()","moviemasher::input#length()","moviemasher::timerange#length()","moviemasher::input#length=()","moviemasher::timerange#length=()","moviemasher::timerange#length_seconds()","moviemasher::floatutil::less()","moviemasher::job#log()","moviemasher::job#log_entry()","moviemasher::input#loop()","moviemasher::input#loop=()","moviemasher::floatutil::max()","moviemasher::mash::media()","moviemasher::mash#media()","moviemasher::mash::media_count_for_clips()","moviemasher::mash::media_search()","moviemasher::av::merge()","moviemasher::layer#merger_command()","moviemasher::transfer#method()","moviemasher::transfer#method=()","moviemasher::floatutil::min()","moviemasher::filterhelpers::mm_cmp()","moviemasher::filterhelpers::mm_dir_horz()","moviemasher::filterhelpers::mm_dir_vert()","moviemasher::filterhelpers::mm_fontfamily()","moviemasher::filterhelpers::mm_fontfile()","moviemasher::filterhelpers::mm_horz()","moviemasher::filterhelpers::mm_max()","moviemasher::filterhelpers::mm_min()","moviemasher::filterhelpers::mm_paren()","moviemasher::filterhelpers::mm_textfile()","moviemasher::filterhelpers::mm_vert()","moviemasher::defaults::module_for_type()","moviemasher::input#module_source()","moviemasher::job#module_source()","moviemasher::callback#name()","moviemasher::output#name()","moviemasher::source#name()","moviemasher::callback#name=()","moviemasher::output#name=()","moviemasher::source#name=()","moviemasher::chain::new()","moviemasher::chainmodule::new()","moviemasher::chainoverlay::new()","moviemasher::chainscaler::new()","moviemasher::error::jobrender::new()","moviemasher::error::runtime::new()","moviemasher::filter::new()","moviemasher::filterevaluated::new()","moviemasher::filterhash::new()","moviemasher::filtersetpts::new()","moviemasher::filtersource::new()","moviemasher::filtersourcecolor::new()","moviemasher::filtersourcemovie::new()","moviemasher::graph::new()","moviemasher::graphmash::new()","moviemasher::graphraw::new()","moviemasher::job::new()","moviemasher::jobhash::new()","moviemasher::layer::new()","moviemasher::layercolor::new()","moviemasher::layertransition::new()","moviemasher::timerange::new()","moviemasher::input#no_audio()","moviemasher::output#no_audio()","moviemasher::input#no_audio=()","moviemasher::output#no_audio=()","moviemasher::input#no_video()","moviemasher::input#no_video=()","moviemasher::evaluate::object()","moviemasher::input#offset()","moviemasher::input#offset=()","moviemasher::job#outputs()","moviemasher::transfer#parameters()","moviemasher::transfer#parameters=()","moviemasher::transfer#pass()","moviemasher::transfer#pass=()","moviemasher::output#path()","moviemasher::transfer#path()","moviemasher::output#path=()","moviemasher::transfer#path=()","moviemasher::transfer#port()","moviemasher::transfer#port=()","moviemasher::floatutil::precision()","moviemasher::output#precision()","moviemasher::output#precision=()","moviemasher::process()","moviemasher::job#process()","moviemasher::process_queues()","moviemasher::job#progress()","moviemasher::callback#progress_seconds()","moviemasher::callback#progress_seconds=()","moviemasher::output#quality()","moviemasher::output#quality=()","moviemasher::layer#range()","moviemasher::layercolor#range()","moviemasher::timerange#rate()","moviemasher::timerange#rate=()","moviemasher::transfer#region()","moviemasher::transfer#region=()","moviemasher::output#required()","moviemasher::output#required=()","moviemasher::filterhelpers::rgb()","moviemasher::filterhelpers::rgba()","moviemasher::floatutil::sort()","moviemasher::input#source()","moviemasher::input#source=()","moviemasher::input#start()","moviemasher::timerange#start()","moviemasher::input#start=()","moviemasher::timerange#start=()","moviemasher::timerange#start_seconds()","moviemasher::timerange#stop()","moviemasher::floatutil::string()","moviemasher::path::strip_slash_end()","moviemasher::path::strip_slash_start()","moviemasher::path::strip_slashes()","moviemasher::timerange#synchronize()","moviemasher::jobhash#to_hash()","moviemasher::jobhash#to_json()","moviemasher::error::runtime#to_s()","moviemasher::callback#trigger()","moviemasher::callback#trigger=()","moviemasher::layer#trim_command()","moviemasher::layercolor#trim_command()","moviemasher::input#type()","moviemasher::output#type()","moviemasher::transfer#type()","moviemasher::input#type=()","moviemasher::output#type=()","moviemasher::transfer#type=()","moviemasher::transfer#user()","moviemasher::transfer#user=()","moviemasher::evaluate::value()","moviemasher::mash#video()","moviemasher::output#video_bitrate()","moviemasher::output#video_bitrate=()","moviemasher::output#video_codec()","moviemasher::output#video_codec=()","moviemasher::output#video_format()","moviemasher::output#video_format=()","moviemasher::mash::video_ranges()","",""],"info":[["MovieMasher","","MovieMasher.html","","

    Handles global configuration and high level processing of Job objects. The\n::process_queues method will …\n"],["MovieMasher::AV","","MovieMasher/AV.html","",""],["MovieMasher::Callback","","MovieMasher/Callback.html","","

    A Transfer object and element in Job#callbacks representing a remote\nrequesttriggered at a particular …\n"],["MovieMasher::Chain","","MovieMasher/Chain.html","","

    chain\n"],["MovieMasher::ChainEffects","","MovieMasher/ChainEffects.html","",""],["MovieMasher::ChainModule","","MovieMasher/ChainModule.html","",""],["MovieMasher::ChainOverlay","","MovieMasher/ChainOverlay.html","",""],["MovieMasher::ChainScaler","","MovieMasher/ChainScaler.html","",""],["MovieMasher::Defaults","","MovieMasher/Defaults.html","",""],["MovieMasher::Error","","MovieMasher/Error.html","",""],["MovieMasher::Error::Configuration","","MovieMasher/Error/Configuration.html","",""],["MovieMasher::Error::Critical","","MovieMasher/Error/Critical.html","","

    serious code errors\n"],["MovieMasher::Error::Job","","MovieMasher/Error/Job.html","","

    job related errors\n"],["MovieMasher::Error::JobInput","","MovieMasher/Error/JobInput.html","",""],["MovieMasher::Error::JobOutput","","MovieMasher/Error/JobOutput.html","",""],["MovieMasher::Error::JobRender","","MovieMasher/Error/JobRender.html","",""],["MovieMasher::Error::JobSource","","MovieMasher/Error/JobSource.html","",""],["MovieMasher::Error::JobUpload","","MovieMasher/Error/JobUpload.html","",""],["MovieMasher::Error::Object","","MovieMasher/Error/Object.html","",""],["MovieMasher::Error::Parameter","","MovieMasher/Error/Parameter.html","",""],["MovieMasher::Error::Runtime","","MovieMasher/Error/Runtime.html","",""],["MovieMasher::Error::State","","MovieMasher/Error/State.html","",""],["MovieMasher::Error::Todo","","MovieMasher/Error/Todo.html","",""],["MovieMasher::Evaluate","","MovieMasher/Evaluate.html","",""],["MovieMasher::Fill","","MovieMasher/Fill.html","",""],["MovieMasher::Filter","","MovieMasher/Filter.html","",""],["MovieMasher::FilterEvaluated","","MovieMasher/FilterEvaluated.html","",""],["MovieMasher::FilterHash","","MovieMasher/FilterHash.html","",""],["MovieMasher::FilterHelpers","","MovieMasher/FilterHelpers.html","",""],["MovieMasher::FilterSetpts","","MovieMasher/FilterSetpts.html","",""],["MovieMasher::FilterSource","","MovieMasher/FilterSource.html","",""],["MovieMasher::FilterSourceColor","","MovieMasher/FilterSourceColor.html","",""],["MovieMasher::FilterSourceMovie","","MovieMasher/FilterSourceMovie.html","",""],["MovieMasher::FloatUtil","","MovieMasher/FloatUtil.html","",""],["MovieMasher::Gain","","MovieMasher/Gain.html","",""],["MovieMasher::Graph","","MovieMasher/Graph.html","",""],["MovieMasher::GraphMash","","MovieMasher/GraphMash.html","",""],["MovieMasher::GraphRaw","","MovieMasher/GraphRaw.html","",""],["MovieMasher::Info","","MovieMasher/Info.html","",""],["MovieMasher::Input","","MovieMasher/Input.html","","

    An element in Job#inputs representing media to be included in the mashup,\nwhich is eventually rendered …\n"],["MovieMasher::Intermediate","","MovieMasher/Intermediate.html","",""],["MovieMasher::Job","","MovieMasher/Job.html","","

    Represents a single transcoding operation. Once #process is called all of\nthe job's #inputs are downloaded …\n"],["MovieMasher::JobHash","","MovieMasher/JobHash.html","","

    Mix-in functionality for mocking a Hash.\n"],["MovieMasher::Layer","","MovieMasher/Layer.html","",""],["MovieMasher::LayerColor","","MovieMasher/LayerColor.html","",""],["MovieMasher::LayerModule","","MovieMasher/LayerModule.html","",""],["MovieMasher::LayerRaw","","MovieMasher/LayerRaw.html","",""],["MovieMasher::LayerRawImage","","MovieMasher/LayerRawImage.html","",""],["MovieMasher::LayerRawVideo","","MovieMasher/LayerRawVideo.html","",""],["MovieMasher::LayerTheme","","MovieMasher/LayerTheme.html","",""],["MovieMasher::LayerTransition","","MovieMasher/LayerTransition.html","",""],["MovieMasher::Mash","","MovieMasher/Mash.html","","

    Input#source of mash inputs, representing a collection #media arranged on\n#audio and #video tracks. …\n"],["MovieMasher::Method","","MovieMasher/Method.html","",""],["MovieMasher::Output","","MovieMasher/Output.html","","

    Represents a single rendered version of the mashup, including all\nformatting parameters and quality settings. …\n"],["MovieMasher::Path","","MovieMasher/Path.html","",""],["MovieMasher::Source","","MovieMasher/Source.html","","

    A Transfer object used for Input#source and Media#source, describing how to\nretrieve an audio, image, …\n"],["MovieMasher::TimeRange","","MovieMasher/TimeRange.html","",""],["MovieMasher::Transfer","","MovieMasher/Transfer.html","","

    Base class for Callback and Source as well as used directly to resolve\nInput and Output relative paths …\n"],["<<","MovieMasher::Chain","MovieMasher/Chain.html#method-i-3C-3C","(filter)",""],["[]","MovieMasher::JobHash","MovieMasher/JobHash.html#method-i-5B-5D","(symbol)","

    Convenience getter for underlying data Hash.\n

    symbol — Symbol key into hash.\n\n

    Returns value of key or nil if …\n"],["[]=","MovieMasher::JobHash","MovieMasher/JobHash.html#method-i-5B-5D-3D","(symbol, value)","

    Convenience setter for underlying data Hash.\n

    symbol — Symbol key into hash.\n

    value — Object to set at key.\n"],["__coerce","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__coerce","(s)",""],["__command_name_value","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__command_name_value","(name, value, scope, job_output)",""],["__filter_dimension_keys","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__filter_dimension_keys","(filter_id)",""],["__filter_is_source?","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__filter_is_source-3F","(filter_id)",""],["__filter_parse_scope_value","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__filter_parse_scope_value","(scope, value_str, job_output = nil)",""],["__filter_scope_binding","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__filter_scope_binding","(scope)",""],["__filter_trim_input","MovieMasher::LayerRawVideo","MovieMasher/LayerRawVideo.html#method-i-__filter_trim_input","()",""],["add_new_layer","MovieMasher::GraphMash","MovieMasher/GraphMash.html#method-i-add_new_layer","(input)",""],["add_new_layer","MovieMasher::LayerTransition","MovieMasher/LayerTransition.html#method-i-add_new_layer","(clip)",""],["add_slash_end","MovieMasher::Path","MovieMasher/Path.html#method-c-add_slash_end","(s)",""],["add_slash_start","MovieMasher::Path","MovieMasher/Path.html#method-c-add_slash_start","(s)",""],["add_slashes","MovieMasher::Path","MovieMasher/Path.html#method-c-add_slashes","(s)",""],["audio","MovieMasher::Mash","MovieMasher/Mash.html#method-i-audio","()","

    Array — One or more Track objects.\n\n"],["audio_bitrate","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_bitrate","()",""],["audio_bitrate=","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_bitrate-3D","(value)","

    String — FFmpeg -b:a switch, placed before #audio_rate.\n

    Integer — The character 'k' will be appended. …\n"],["audio_codec","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_codec","()",""],["audio_codec=","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_codec-3D","(value)","

    String — FFmpeg -c:a switch, placed after #audio_rate.\n

    Default — aac -strict experimental\n

    Types — TypeAudio …\n"],["audio_rate","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_rate","()",""],["audio_rate=","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_rate-3D","(value)","

    String — FFmpeg -r:a switch, placed after #audio_bitrate and before #audio_codec.\n

    Default — 44100\n

    Types — TypeAudio …\n"],["av","MovieMasher::Input","MovieMasher/Input.html#method-i-av","()","

    String — The AV type.\n

    Constant — AV::Audio, AV::Video, AV::Both, or AV::Neither if an error was encountered\n…\n"],["av","MovieMasher::Output","MovieMasher/Output.html#method-i-av","()","

    String — The AV type.\n

    Constant — AV::Audio, AV::Video or AV::Both.\n

    Default — Based on #type and #no_audio.\n"],["backcolor","MovieMasher::Output","MovieMasher/Output.html#method-i-backcolor","()",""],["backcolor=","MovieMasher::Output","MovieMasher/Output.html#method-i-backcolor-3D","(value)","

    String — Six character hex, rgb(0,0,0) or standard color name.\n

    Default — FFFFFF for TypeWaveform, black for …\n"],["base_source","MovieMasher::Input","MovieMasher/Input.html#method-i-base_source","()","

    Transfer — Resolves relative URLs.\n

    Default — Job#base_source\n

    Types — Just TypeMash.\n"],["base_source","MovieMasher::Job","MovieMasher/Job.html#method-i-base_source","()","

    Transfer — Resolves relative paths within Input#source and Media#source String values.\n\n"],["bucket","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-bucket","()",""],["bucket=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-bucket-3D","(value)","

    String — Name of AWS S3 bucket where file is stored.\n

    Types — Just TypeS3.\n\n"],["callbacks","MovieMasher::Job","MovieMasher/Job.html#method-i-callbacks","()","

    Array — Zero or more Callback objects.\n\n"],["chain_command","MovieMasher::Chain","MovieMasher/Chain.html#method-i-chain_command","(scope, job_output)",""],["chain_command","MovieMasher::ChainModule","MovieMasher/ChainModule.html#method-i-chain_command","(scope, job_output)",""],["chain_command","MovieMasher::ChainScaler","MovieMasher/ChainScaler.html#method-i-chain_command","(scope, job_output)",""],["class_symbol","MovieMasher::JobHash","MovieMasher/JobHash.html#method-i-class_symbol","()","

    Returns Symbol of lowercased class name without namespace qualifiers.\n"],["clip_has_audio","MovieMasher::Mash","MovieMasher/Mash.html#method-c-clip_has_audio","(clip)",""],["clips_having_audio","MovieMasher::Mash","MovieMasher/Mash.html#method-c-clips_having_audio","(mash)",""],["clips_in_range","MovieMasher::Mash","MovieMasher/Mash.html#method-c-clips_in_range","(mash, range, track_type)",""],["cmp","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-cmp","(f1, f2, digits = 3)",""],["color_value","MovieMasher::Graph","MovieMasher/Graph.html#method-c-color_value","(color)",""],["command_parameters","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-command_parameters","(scope, job_output)",""],["concat","MovieMasher::Path","MovieMasher/Path.html#method-c-concat","(s1, s2)",""],["configuration","MovieMasher","MovieMasher.html#method-c-configuration","()","

    Returns the configuration Hash with Symbol keys.\n"],["configure","MovieMasher","MovieMasher.html#method-c-configure","(hash_or_path)","

    hash_or_path — Set one or more configuration options. If supplied a String, it's\nassumed to be a path …\n"],["create","MovieMasher::Callback","MovieMasher/Callback.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create","MovieMasher::Input","MovieMasher/Input.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create","MovieMasher::Output","MovieMasher/Output.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create","MovieMasher::Source","MovieMasher/Source.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create","MovieMasher::Transfer","MovieMasher/Transfer.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create_layer","MovieMasher::Graph","MovieMasher/Graph.html#method-i-create_layer","(input)",""],["data","MovieMasher::Callback","MovieMasher/Callback.html#method-i-data","()",""],["data=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-data-3D","(value)","

    Hash/Array - Values to recursively evaluate and parse into request body.\n

    Default — nil\n\n"],["destination","MovieMasher::Job","MovieMasher/Job.html#method-i-destination","()","

    Transfer — Shared by all Output objects that don't have one of their own.\n\n"],["destination","MovieMasher::Output","MovieMasher/Output.html#method-i-destination","()",""],["destination=","MovieMasher::Output","MovieMasher/Output.html#method-i-destination-3D","(value)","

    Transfer — Describes where to upload this output.\n

    Default — Job#destination\n\n"],["dimensions","MovieMasher::Input","MovieMasher/Input.html#method-i-dimensions","()",""],["dimensions","MovieMasher::Output","MovieMasher/Output.html#method-i-dimensions","()",""],["dimensions=","MovieMasher::Input","MovieMasher/Input.html#method-i-dimensions-3D","(value)","

    String — WIDTHxHEIGHT of element.\n

    Default — Probed from downloaded.\n

    Types — TypeImage and TypeVideo.\n"],["dimensions=","MovieMasher::Output","MovieMasher/Output.html#method-i-dimensions-3D","(value)","

    String — Output pixel size formatted as WIDTHxHEIGHT.\n

    Default — 512x288 for TypeVideo, 8000x32 for TypeWaveform …\n"],["directory","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-directory","()",""],["directory=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-directory-3D","(value)","

    String — Added to URL after #directory and before #name, with slash on either side.\n

    Default — Nil means do …\n"],["dup","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-dup","()",""],["duration","MovieMasher::Graph","MovieMasher/Graph.html#method-i-duration","()",""],["duration","MovieMasher::Input","MovieMasher/Input.html#method-i-duration","()",""],["duration","MovieMasher::Mash","MovieMasher/Mash.html#method-c-duration","(mash)",""],["duration=","MovieMasher::Input","MovieMasher/Input.html#method-i-duration-3D","(value)","

    Float — Seconds of input available for presentation.\n

    Default — Probed from downloaded.\n

    Types — All except TypeImage …\n"],["end_seconds","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-end_seconds","()",""],["equals?","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-equals-3F","(range)",""],["equation","MovieMasher::Evaluate","MovieMasher/Evaluate.html#method-c-equation","(s, raise_on_fail = nil)",""],["error","MovieMasher::Job","MovieMasher/Job.html#method-i-error","()","

    Problem encountered during #new or #process. If the source of the problem\nis a command line application …\n"],["extension","MovieMasher::Callback","MovieMasher/Callback.html#method-i-extension","()",""],["extension","MovieMasher::Output","MovieMasher/Output.html#method-i-extension","()",""],["extension","MovieMasher::Source","MovieMasher/Source.html#method-i-extension","()",""],["extension=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-extension-3D","(value)","

    String — Added to file path after #name, with period inserted between.\n\n"],["extension=","MovieMasher::Output","MovieMasher/Output.html#method-i-extension-3D","(value)","

    String — Extension for rendered file, also implies format.\n

    Default — Removed from #name if present, otherwise …\n\n"],["extension=","MovieMasher::Source","MovieMasher/Source.html#method-i-extension-3D","(value)","

    String — Appended to file path after #name, with period inserted between.\n\n"],["fill","MovieMasher::Input","MovieMasher/Input.html#method-i-fill","()",""],["fill=","MovieMasher::Input","MovieMasher/Input.html#method-i-fill-3D","(value)","

    String — How to size in relation to Output#dimensions.\n

    Constant — Fill::Crop, Fill::None, Fill::Scale or …\n"],["filter_command","MovieMasher::Filter","MovieMasher/Filter.html#method-i-filter_command","(scope, job_output)",""],["filter_command","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-filter_command","(scope = nil, job_output = nil)",""],["filter_command","MovieMasher::FilterHash","MovieMasher/FilterHash.html#method-i-filter_command","(scope = nil, job_output = nil)",""],["filter_command","MovieMasher::FilterSource","MovieMasher/FilterSource.html#method-i-filter_command","(scope, job_output)",""],["filter_command","MovieMasher::FilterSourceColor","MovieMasher/FilterSourceColor.html#method-i-filter_command","(scope, job_output)",""],["filter_name","MovieMasher::Filter","MovieMasher/Filter.html#method-i-filter_name","()",""],["filter_name","MovieMasher::FilterSourceColor","MovieMasher/FilterSourceColor.html#method-i-filter_name","()",""],["filter_name","MovieMasher::FilterSourceMovie","MovieMasher/FilterSourceMovie.html#method-i-filter_name","()",""],["forecolor","MovieMasher::Output","MovieMasher/Output.html#method-i-forecolor","()",""],["forecolor=","MovieMasher::Output","MovieMasher/Output.html#method-i-forecolor-3D","(value)","

    String — Six character Hex color.\n

    Default — 000000\n

    Types — Only TypeWaveform.\n"],["gain","MovieMasher::Input","MovieMasher/Input.html#method-i-gain","()",""],["gain=","MovieMasher::Input","MovieMasher/Input.html#method-i-gain-3D","(value)","

    Float — Multiplier to adjust volume of audio when mixed into mashup.\n

    Array — Duple Float values signifying …\n"],["gain_changes","MovieMasher::Mash","MovieMasher/Mash.html#method-c-gain_changes","(gain)",""],["graph_command","MovieMasher::Graph","MovieMasher/Graph.html#method-i-graph_command","(output, job = nil)",""],["graph_command","MovieMasher::GraphMash","MovieMasher/GraphMash.html#method-i-graph_command","(output, job = nil)",""],["graph_command","MovieMasher::GraphRaw","MovieMasher/GraphRaw.html#method-i-graph_command","(output, job = nil)",""],["graph_scope","MovieMasher::Graph","MovieMasher/Graph.html#method-i-graph_scope","()",""],["graph_scope","MovieMasher::GraphMash","MovieMasher/GraphMash.html#method-i-graph_scope","()",""],["gtr","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-gtr","(big, small, digits = 3)",""],["gtre","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-gtre","(big, small, digits = 3)",""],["has_audio?","MovieMasher::Mash","MovieMasher/Mash.html#method-c-has_audio-3F","(mash)",""],["has_video?","MovieMasher::Mash","MovieMasher/Mash.html#method-c-has_video-3F","(mash)",""],["hash","MovieMasher::FilterHash","MovieMasher/FilterHash.html#method-i-hash","()",""],["hash?","MovieMasher::Mash","MovieMasher/Mash.html#method-c-hash-3F","(hash)",""],["host","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-host","()",""],["host=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-host-3D","(value)","

    String — Remote server name or IP address where file is stored.\n

    Types — TypeHttp and TypeHttps.\n\n"],["id","MovieMasher::Job","MovieMasher/Job.html#method-i-id","()","

    String — user supplied identifier.\n

    Default — Nil, or messageId if the Job originated from an SQS message. …\n\n"],["identifier","MovieMasher::JobHash","MovieMasher/JobHash.html#method-i-identifier","()","

    String — Unique identifier for object.\n\n"],["includes?","MovieMasher::AV","MovieMasher/AV.html#method-c-includes-3F","(has, desired)",""],["initialize_chains","MovieMasher::Layer","MovieMasher/Layer.html#method-i-initialize_chains","()",""],["initialize_chains","MovieMasher::LayerRawImage","MovieMasher/LayerRawImage.html#method-i-initialize_chains","()",""],["initialize_chains","MovieMasher::LayerRawVideo","MovieMasher/LayerRawVideo.html#method-i-initialize_chains","()",""],["initialize_chains","MovieMasher::LayerTheme","MovieMasher/LayerTheme.html#method-i-initialize_chains","()",""],["initialize_chains","MovieMasher::LayerTransition","MovieMasher/LayerTransition.html#method-i-initialize_chains","()",""],["initialize_filters","MovieMasher::Chain","MovieMasher/Chain.html#method-i-initialize_filters","()",""],["initialize_filters","MovieMasher::ChainEffects","MovieMasher/ChainEffects.html#method-i-initialize_filters","()",""],["initialize_filters","MovieMasher::ChainModule","MovieMasher/ChainModule.html#method-i-initialize_filters","()",""],["initialize_filters","MovieMasher::ChainOverlay","MovieMasher/ChainOverlay.html#method-i-initialize_filters","()",""],["input_scope","MovieMasher::ChainModule","MovieMasher/ChainModule.html#method-i-input_scope","(scope)",""],["inputs","MovieMasher::Job","MovieMasher/Job.html#method-i-inputs","()","

    Array — One or more Input objects.\n\n"],["intersection","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-intersection","(range)",""],["layer_command","MovieMasher::Layer","MovieMasher/Layer.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerColor","MovieMasher/LayerColor.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerRaw","MovieMasher/LayerRaw.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerRawImage","MovieMasher/LayerRawImage.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerRawVideo","MovieMasher/LayerRawVideo.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerTransition","MovieMasher/LayerTransition.html#method-i-layer_command","(scope, job_output)",""],["layer_scope","MovieMasher::Layer","MovieMasher/Layer.html#method-i-layer_scope","(scope, job_output)",""],["layer_scope","MovieMasher::LayerModule","MovieMasher/LayerModule.html#method-i-layer_scope","(scope, job_output)",""],["length","MovieMasher::Input","MovieMasher/Input.html#method-i-length","()",""],["length","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-length","()",""],["length=","MovieMasher::Input","MovieMasher/Input.html#method-i-length-3D","(value)","

    Float — Seconds the input appears in the mashup.\n

    Default — #duration - #offset\n\n"],["length=","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-length-3D","(n)",""],["length_seconds","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-length_seconds","(precision = 3)",""],["less","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-less","(small, big, digits = 3)",""],["log","MovieMasher::Job","MovieMasher/Job.html#method-i-log","()","

    String — Current content of the job's log file.\n\n"],["log_entry","MovieMasher::Job","MovieMasher/Job.html#method-i-log_entry","(type, &proc)","

    Output to the job's log file. If type is :error then\njob will be halted and its #error will be set …\n"],["loop","MovieMasher::Input","MovieMasher/Input.html#method-i-loop","()",""],["loop=","MovieMasher::Input","MovieMasher/Input.html#method-i-loop-3D","(value)","

    Integer — Number of times to loop input.\n

    Types — Just TypeAudio.\n\n"],["max","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-max","(a, b, digits = 3)",""],["media","MovieMasher::Mash","MovieMasher/Mash.html#method-c-media","(mash, ob_or_id)",""],["media","MovieMasher::Mash","MovieMasher/Mash.html#method-i-media","()","

    Array — One or more Media objects.\n\n"],["media_count_for_clips","MovieMasher::Mash","MovieMasher/Mash.html#method-c-media_count_for_clips","(mash, clips, referenced)",""],["media_search","MovieMasher::Mash","MovieMasher/Mash.html#method-c-media_search","(type, ob_or_id, mash)",""],["merge","MovieMasher::AV","MovieMasher/AV.html#method-c-merge","(type1, type2)",""],["merger_command","MovieMasher::Layer","MovieMasher/Layer.html#method-i-merger_command","(scope)",""],["method","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-method","()",""],["method=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-method-3D","(value)","

    String — How to retrieve the file.\n

    Constant — Method::Copy, Method::Move or Method::Symlink.\n

    Default — Method::Symlink …\n"],["min","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-min","(a, b, digits = 3)",""],["mm_cmp","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_cmp","(param_string, mash, scope, output = nil)",""],["mm_dir_horz","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_dir_horz","(param_string, mash, scope, output = nil)",""],["mm_dir_vert","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_dir_vert","(param_string, mash, scope, output = nil)",""],["mm_fontfamily","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_fontfamily","(param_string, mash, scope, output = nil)",""],["mm_fontfile","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_fontfile","(param_string, mash, scope, output = nil)",""],["mm_horz","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_horz","(param_string, mash = nil, scope = nil, output = nil)",""],["mm_max","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_max","(param_string, mash, scope, output = nil)",""],["mm_min","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_min","(param_string, mash, scope, output = nil)",""],["mm_paren","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_paren","(param_string, mash, scope, output = nil)",""],["mm_textfile","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_textfile","(param_string, mash, scope, output = nil)",""],["mm_vert","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_vert","(param_string, mash = nil, scope = nil, output = nil)",""],["module_for_type","MovieMasher::Defaults","MovieMasher/Defaults.html#method-c-module_for_type","(type, media_id = nil)",""],["module_source","MovieMasher::Input","MovieMasher/Input.html#method-i-module_source","()","

    Transfer — Resolves relative font URLs for modules.\n

    Default — Job#module_source\n

    Types — Just TypeMash.\n"],["module_source","MovieMasher::Job","MovieMasher/Job.html#method-i-module_source","()","

    Transfer — Resolves relative font paths within Media#source String values.\n

    Default — #base_source\n\n"],["name","MovieMasher::Callback","MovieMasher/Callback.html#method-i-name","()",""],["name","MovieMasher::Output","MovieMasher/Output.html#method-i-name","()",""],["name","MovieMasher::Source","MovieMasher/Source.html#method-i-name","()",""],["name=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-name-3D","(value)","

    String — The full or basename of file added to URL after #path. If full, #extension\nwill be set and removed …\n\n"],["name=","MovieMasher::Output","MovieMasher/Output.html#method-i-name-3D","(value)","

    String — Basename for rendered file.\n

    Default — #type, or empty for TypeSequence.\n

    Types — All, but TypeSequence …\n"],["name=","MovieMasher::Source","MovieMasher/Source.html#method-i-name-3D","(value)","

    String — The full or basename of file appended to file path. If full, #extension\nwill be set and removed …\n\n"],["new","MovieMasher::Chain","MovieMasher/Chain.html#method-c-new","(input = nil, job_input = nil)",""],["new","MovieMasher::ChainModule","MovieMasher/ChainModule.html#method-c-new","(mod_input, mash_input, applied_input)",""],["new","MovieMasher::ChainOverlay","MovieMasher/ChainOverlay.html#method-c-new","(job_output)",""],["new","MovieMasher::ChainScaler","MovieMasher/ChainScaler.html#method-c-new","(input = nil, job_input = nil)",""],["new","MovieMasher::Error::JobRender","MovieMasher/Error/JobRender.html#method-c-new","(ffmpeg_result, msg = \"failed to render\")",""],["new","MovieMasher::Error::Runtime","MovieMasher/Error/Runtime.html#method-c-new","(msg = nil)",""],["new","MovieMasher::Filter","MovieMasher/Filter.html#method-c-new","(id = nil)",""],["new","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-c-new","(filter_config, mash_input = nil, applied_input = nil)",""],["new","MovieMasher::FilterHash","MovieMasher/FilterHash.html#method-c-new","(id, hash = nil)",""],["new","MovieMasher::FilterSetpts","MovieMasher/FilterSetpts.html#method-c-new","(expr = 'PTS-STARTPTS')",""],["new","MovieMasher::FilterSource","MovieMasher/FilterSource.html#method-c-new","(id, hash, dimensions = nil)",""],["new","MovieMasher::FilterSourceColor","MovieMasher/FilterSourceColor.html#method-c-new","(duration, color)",""],["new","MovieMasher::FilterSourceMovie","MovieMasher/FilterSourceMovie.html#method-c-new","(input, job_input)",""],["new","MovieMasher::Graph","MovieMasher/Graph.html#method-c-new","(job_input, render_range = nil, label_name = 'layer')",""],["new","MovieMasher::GraphMash","MovieMasher/GraphMash.html#method-c-new","(mash_input, render_range, label_name = 'layer')",""],["new","MovieMasher::GraphRaw","MovieMasher/GraphRaw.html#method-c-new","(input)",""],["new","MovieMasher::Job","MovieMasher/Job.html#method-c-new","(hash_or_path, configuration = nil)","

    Create a new Job object from a nested structure or a file path.\n

    hash_or_path — Hash or String expected to …\n\n"],["new","MovieMasher::JobHash","MovieMasher/JobHash.html#method-c-new","(hash)","

    Set the actual Hash when creating.\n"],["new","MovieMasher::Layer","MovieMasher/Layer.html#method-c-new","(input, job_input)",""],["new","MovieMasher::LayerColor","MovieMasher/LayerColor.html#method-c-new","(duration, color)",""],["new","MovieMasher::LayerTransition","MovieMasher/LayerTransition.html#method-c-new","(input, job_input, job)",""],["new","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-c-new","(start = 0, rate = 0, length = 1)",""],["no_audio","MovieMasher::Input","MovieMasher/Input.html#method-i-no_audio","()",""],["no_audio","MovieMasher::Output","MovieMasher/Output.html#method-i-no_audio","()",""],["no_audio=","MovieMasher::Input","MovieMasher/Input.html#method-i-no_audio-3D","(value)","

    Boolean — If true, audio in input will be ignored.\n

    Default — Initially based on #type, but could change after …\n"],["no_audio=","MovieMasher::Output","MovieMasher/Output.html#method-i-no_audio-3D","(value)","

    Boolean — If true, audio in inputs will not be included.\n

    Default — FALSE\n

    Types — Just TypeVideo, but accessible …\n"],["no_video","MovieMasher::Input","MovieMasher/Input.html#method-i-no_video","()",""],["no_video=","MovieMasher::Input","MovieMasher/Input.html#method-i-no_video-3D","(value)","

    Boolean — If true, video in input will be ignored.\n

    Default — Initially based on #type, but could change after …\n"],["object","MovieMasher::Evaluate","MovieMasher/Evaluate.html#method-c-object","(data, scope = nil)",""],["offset","MovieMasher::Input","MovieMasher/Input.html#method-i-offset","()",""],["offset=","MovieMasher::Input","MovieMasher/Input.html#method-i-offset-3D","(value)","

    Float — Seconds to remove from beginning of input.\n

    Default — 0.0 means nothing removed.\n

    Types — TypeAudio and …\n"],["outputs","MovieMasher::Job","MovieMasher/Job.html#method-i-outputs","()","

    Array — One or more Output objects.\n\n"],["parameters","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-parameters","()",""],["parameters=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-parameters-3D","(value)","

    Hash — Query string parameters to send with request for file. The values\nareevaluated, with Job and Input …\n"],["pass","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-pass","()",""],["pass=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-pass-3D","(value)","

    String — Password for standard HTTP authentication.\n

    Default — Nil means do not provide authenticating details. …\n"],["path","MovieMasher::Output","MovieMasher/Output.html#method-i-path","()",""],["path","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-path","()",""],["path=","MovieMasher::Output","MovieMasher/Output.html#method-i-path-3D","(value)","

    String — Prepended to #name during upload.\n

    Default — empty\n\n"],["path=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-path-3D","(value)","

    String — Added to URL after #directory and before #name, with slash on either side.\n

    Default — Nil means do …\n"],["port","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-port","()",""],["port=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-port-3D","(value)","

    Integer — Port number to contact #host on.\n

    Constant — Method::Copy, Method::Move or Method::Symlink.\n

    Default … — "],["precision","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-precision","(f, digits = 3)",""],["precision","MovieMasher::Output","MovieMasher/Output.html#method-i-precision","()",""],["precision=","MovieMasher::Output","MovieMasher/Output.html#method-i-precision-3D","(value)","

    Integer — Number of decimal places that Job#duration and #duration must match by for\nsuccessful rendering. …\n"],["process","MovieMasher","MovieMasher.html#method-c-process","(object_or_path)","

    object_or_path — Job object or String/Hash to be passed to Job.new along with\n::configuration. After the …\n\n"],["process","MovieMasher::Job","MovieMasher/Job.html#method-i-process","()","

    Downloads assets for each Input, renders each Output and uploads\nto#destination or Output#destination …\n"],["process_queues","MovieMasher","MovieMasher.html#method-c-process_queues","()","

    Loops for process_queues_seconds searching for the oldest\nJSON or YML formatted job file in queue_directory …\n"],["progress","MovieMasher::Job","MovieMasher/Job.html#method-i-progress","()","

    Current status of processing. The following keys are available:\n

    :downloading — number of files referenced …\n"],["progress_seconds","MovieMasher::Callback","MovieMasher/Callback.html#method-i-progress_seconds","()",""],["progress_seconds=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-progress_seconds-3D","(value)","

    Integer — Seconds to wait before making requests.\n

    Default — 44100\n

    Triggers — Only TriggerProgress.\n"],["quality","MovieMasher::Output","MovieMasher/Output.html#method-i-quality","()",""],["quality=","MovieMasher::Output","MovieMasher/Output.html#method-i-quality-3D","(value)","

    Integer — FFmpeg -q:v switch, 1 (best) to 32 (worst).\n

    Default — 1\n

    Types — TypeImage and TypeSequence.\n"],["range","MovieMasher::Layer","MovieMasher/Layer.html#method-i-range","()",""],["range","MovieMasher::LayerColor","MovieMasher/LayerColor.html#method-i-range","()",""],["rate","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-rate","()",""],["rate=","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-rate-3D","(n)",""],["region","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-region","()",""],["region=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-region-3D","(value)","

    String — Global AWS geographical region code.\n

    Default — Nil means us-east-1 standard region.\n

    Types — Just TypeS3 …\n"],["required","MovieMasher::Output","MovieMasher/Output.html#method-i-required","()",""],["required=","MovieMasher::Output","MovieMasher/Output.html#method-i-required-3D","(value)","

    Boolean — Whether or not Job should halt if output cannot be rendered or uploaded.\n

    Default — nil\n\n"],["rgb","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-rgb","(param_string, mash = nil, scope = nil, output = nil)",""],["rgba","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-rgba","(param_string, mash = nil, scope = nil, output = nil)",""],["sort","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-sort","(a, b)",""],["source","MovieMasher::Input","MovieMasher/Input.html#method-i-source","()",""],["source=","MovieMasher::Input","MovieMasher/Input.html#method-i-source-3D","(value)","

    Describes the download request for the element, as either a URL or\nHash/Source. If the URL is relative …\n"],["start","MovieMasher::Input","MovieMasher/Input.html#method-i-start","()",""],["start","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-start","()",""],["start=","MovieMasher::Input","MovieMasher/Input.html#method-i-start-3D","(value)","

    Float — Seconds from start of mashup to introduce the input.\n

    Default — -1.0 means after previous audio in …\n"],["start=","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-start-3D","(n)",""],["start_seconds","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-start_seconds","(precision = 3)",""],["stop","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-stop","()",""],["string","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-string","(f, digits = 3)",""],["strip_slash_end","MovieMasher::Path","MovieMasher/Path.html#method-c-strip_slash_end","(s)",""],["strip_slash_start","MovieMasher::Path","MovieMasher/Path.html#method-c-strip_slash_start","(s)",""],["strip_slashes","MovieMasher::Path","MovieMasher/Path.html#method-c-strip_slashes","(s)",""],["synchronize","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-synchronize","(time, rounding = :round)",""],["to_hash","MovieMasher::JobHash","MovieMasher/JobHash.html#method-i-to_hash","()","

    Return deep copy of underlying Hash.\n"],["to_json","MovieMasher::JobHash","MovieMasher/JobHash.html#method-i-to_json","(state = nil)","

    Return underlying Hash in JSON format.\n"],["to_s","MovieMasher::Error::Runtime","MovieMasher/Error/Runtime.html#method-i-to_s","()",""],["trigger","MovieMasher::Callback","MovieMasher/Callback.html#method-i-trigger","()",""],["trigger=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-trigger-3D","(value)","

    String — The event that fires the request.\n

    Constant — TriggerInitiate, TriggerProgress, TriggerError or TriggerComplete …\n"],["trim_command","MovieMasher::Layer","MovieMasher/Layer.html#method-i-trim_command","(render_range, job_output)",""],["trim_command","MovieMasher::LayerColor","MovieMasher/LayerColor.html#method-i-trim_command","(render_range, job_output)",""],["type","MovieMasher::Input","MovieMasher/Input.html#method-i-type","()",""],["type","MovieMasher::Output","MovieMasher/Output.html#method-i-type","()",""],["type","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-type","()",""],["type=","MovieMasher::Input","MovieMasher/Input.html#method-i-type-3D","(value)","

    String — The kind of input.\n

    Constant — TypeAudio, TypeImage, TypeMash or TypeVideo.\n

    Default — Probed from downloaded. …\n"],["type=","MovieMasher::Output","MovieMasher/Output.html#method-i-type-3D","(value)","

    String — The kind of output.\n

    Constant — TypeAudio, TypeImage, TypeSequence, TypeVideo or TypeWaveform.\n

    Default … — "],["type=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-type-3D","(value)","

    String — The kind of transfer.\n

    Constant — TypeFile, TypeHttp, TypeHttps or TypeS3.\n

    Default — TypeFile\n"],["user","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-user","()",""],["user=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-user-3D","(value)","

    String — Username for standard HTTP authentication.\n

    Default — Nil means do not provide authenticating details. …\n"],["value","MovieMasher::Evaluate","MovieMasher/Evaluate.html#method-c-value","(v, scope)",""],["video","MovieMasher::Mash","MovieMasher/Mash.html#method-i-video","()","

    Array — One or more Track objects.\n\n"],["video_bitrate","MovieMasher::Output","MovieMasher/Output.html#method-i-video_bitrate","()",""],["video_bitrate=","MovieMasher::Output","MovieMasher/Output.html#method-i-video_bitrate-3D","(value)","

    String — FFmpeg -b:v switch, placed after #video_codec and before #video_rate.\n

    Integer — The character 'k' …\n"],["video_codec","MovieMasher::Output","MovieMasher/Output.html#method-i-video_codec","()",""],["video_codec=","MovieMasher::Output","MovieMasher/Output.html#method-i-video_codec-3D","(value)","

    String — FFmpeg -c:v switch, placed after #video_format and before #video_bitrate.\n

    Default — libx264 -level …\n"],["video_format","MovieMasher::Output","MovieMasher/Output.html#method-i-video_format","()",""],["video_format=","MovieMasher::Output","MovieMasher/Output.html#method-i-video_format-3D","(value)","

    String — FFmpeg -f:v switch, placed after #dimensions and before #video_codec.\n

    Default — nil\n

    Types — Only TypeVideo …\n"],["video_ranges","MovieMasher::Mash","MovieMasher/Mash.html#method-c-video_ranges","(mash)",""],["LICENSE","","LICENSE.html","","

    Mozilla Public License, version 2.0\n

    Definitions\n\n

    1.1. “Contributorâ€\n"],["README","","README_md.html","","

    moviemasher.js | angular-moviemasher | moviemasher.rb\n

    Ruby library for mashing up video, images and audio …\n"]]}} \ No newline at end of file +var search_data = {"index":{"searchIndex":["moviemasher","av","callback","chain","chaineffects","chainmodule","chainoverlay","chainscaler","configuration","defaults","error","configuration","critical","job","jobinput","joboutput","jobrender","jobsource","jobupload","object","parameter","runtime","state","todo","evaluate","fill","filter","filterevaluated","filterhash","filterhelpers","filtersetpts","filtersource","filtersourcecolor","filtersourcemovie","floatutil","gain","graph","graphmash","graphraw","hashable","info","input","intermediate","job","layer","layercolor","layermodule","layerraw","layerrawimage","layerrawvideo","layertheme","layertransition","mash","method","output","path","source","timerange","transfer","<<()","[]()","[]=()","__coerce()","__command_name_value()","__filter_dimension_keys()","__filter_is_source?()","__filter_parse_scope_value()","__filter_scope_binding()","__filter_trim_input()","add_new_layer()","add_new_layer()","add_slash_end()","add_slash_start()","add_slashes()","audio()","audio_bitrate()","audio_bitrate=()","audio_codec()","audio_codec=()","audio_rate()","audio_rate=()","av()","av()","backcolor()","backcolor=()","base_source()","base_source()","bucket()","bucket=()","callbacks()","chain_command()","chain_command()","chain_command()","class_symbol()","clip_has_audio()","clips_having_audio()","clips_in_range()","cmp()","color_value()","command_parameters()","concat()","configuration()","configure()","create()","create()","create()","create()","create()","create_layer()","data()","data=()","destination()","destination()","destination=()","dimensions()","dimensions()","dimensions=()","dimensions=()","directory()","directory=()","dup()","duration()","duration()","duration()","duration=()","end_seconds()","equals?()","equation()","error()","extension()","extension()","extension()","extension=()","extension=()","extension=()","fill()","fill=()","filter_command()","filter_command()","filter_command()","filter_command()","filter_command()","filter_name()","filter_name()","filter_name()","forecolor()","forecolor=()","gain()","gain=()","gain_changes()","goodbye()","graph_command()","graph_command()","graph_command()","graph_scope()","graph_scope()","gtr()","gtre()","has_audio?()","has_video?()","hash()","hash?()","hello()","host()","host=()","id()","identifier()","includes?()","initialize_chains()","initialize_chains()","initialize_chains()","initialize_chains()","initialize_chains()","initialize_filters()","initialize_filters()","initialize_filters()","initialize_filters()","input_scope()","inputs()","intersection()","keys()","layer_command()","layer_command()","layer_command()","layer_command()","layer_command()","layer_command()","layer_scope()","layer_scope()","length()","length()","length=()","length=()","length_seconds()","less()","log()","log_entry()","loop()","loop=()","max()","media()","media()","media_count_for_clips()","media_search()","merge()","merger_command()","method()","method=()","min()","mm_cmp()","mm_dir_horz()","mm_dir_vert()","mm_fontfamily()","mm_fontfile()","mm_horz()","mm_max()","mm_min()","mm_paren()","mm_textfile()","mm_vert()","module_for_type()","module_source()","module_source()","name()","name()","name()","name=()","name=()","name=()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","new()","no_audio()","no_audio()","no_audio=()","no_audio=()","no_video()","no_video=()","object()","offset()","offset=()","outputs()","parameters()","parameters=()","pass()","pass=()","path()","path()","path=()","path=()","port()","port=()","precision()","precision()","precision=()","process()","process()","process_jobs()","process_queues()","progress()","progress_seconds()","progress_seconds=()","quality()","quality=()","range()","range()","rate()","rate=()","region()","region=()","required()","required=()","resolved_hash()","resolved_string()","rgb()","rgba()","sort()","source()","source=()","start()","start()","start=()","start=()","start_seconds()","stop()","string()","string_type()","strip_slash_end()","strip_slash_start()","strip_slashes()","synchronize()","to_hash()","to_json()","to_s()","trigger()","trigger=()","trim_command()","trim_command()","type()","type()","type()","type=()","type=()","type=()","user()","user=()","value()","values()","video()","video_bitrate()","video_bitrate=()","video_codec()","video_codec=()","video_format()","video_format=()","video_ranges()","documentation"],"longSearchIndex":["moviemasher","moviemasher::av","moviemasher::callback","moviemasher::chain","moviemasher::chaineffects","moviemasher::chainmodule","moviemasher::chainoverlay","moviemasher::chainscaler","moviemasher::configuration","moviemasher::defaults","moviemasher::error","moviemasher::error::configuration","moviemasher::error::critical","moviemasher::error::job","moviemasher::error::jobinput","moviemasher::error::joboutput","moviemasher::error::jobrender","moviemasher::error::jobsource","moviemasher::error::jobupload","moviemasher::error::object","moviemasher::error::parameter","moviemasher::error::runtime","moviemasher::error::state","moviemasher::error::todo","moviemasher::evaluate","moviemasher::fill","moviemasher::filter","moviemasher::filterevaluated","moviemasher::filterhash","moviemasher::filterhelpers","moviemasher::filtersetpts","moviemasher::filtersource","moviemasher::filtersourcecolor","moviemasher::filtersourcemovie","moviemasher::floatutil","moviemasher::gain","moviemasher::graph","moviemasher::graphmash","moviemasher::graphraw","moviemasher::hashable","moviemasher::info","moviemasher::input","moviemasher::intermediate","moviemasher::job","moviemasher::layer","moviemasher::layercolor","moviemasher::layermodule","moviemasher::layerraw","moviemasher::layerrawimage","moviemasher::layerrawvideo","moviemasher::layertheme","moviemasher::layertransition","moviemasher::mash","moviemasher::method","moviemasher::output","moviemasher::path","moviemasher::source","moviemasher::timerange","moviemasher::transfer","moviemasher::chain#<<()","moviemasher::hashable#[]()","moviemasher::hashable#[]=()","moviemasher::filterevaluated#__coerce()","moviemasher::filterevaluated#__command_name_value()","moviemasher::filterevaluated#__filter_dimension_keys()","moviemasher::filterevaluated#__filter_is_source?()","moviemasher::filterevaluated#__filter_parse_scope_value()","moviemasher::filterevaluated#__filter_scope_binding()","moviemasher::layerrawvideo#__filter_trim_input()","moviemasher::graphmash#add_new_layer()","moviemasher::layertransition#add_new_layer()","moviemasher::path::add_slash_end()","moviemasher::path::add_slash_start()","moviemasher::path::add_slashes()","moviemasher::mash#audio()","moviemasher::output#audio_bitrate()","moviemasher::output#audio_bitrate=()","moviemasher::output#audio_codec()","moviemasher::output#audio_codec=()","moviemasher::output#audio_rate()","moviemasher::output#audio_rate=()","moviemasher::input#av()","moviemasher::output#av()","moviemasher::output#backcolor()","moviemasher::output#backcolor=()","moviemasher::input#base_source()","moviemasher::job#base_source()","moviemasher::transfer#bucket()","moviemasher::transfer#bucket=()","moviemasher::job#callbacks()","moviemasher::chain#chain_command()","moviemasher::chainmodule#chain_command()","moviemasher::chainscaler#chain_command()","moviemasher::hashable#class_symbol()","moviemasher::mash::clip_has_audio()","moviemasher::mash::clips_having_audio()","moviemasher::mash::clips_in_range()","moviemasher::floatutil::cmp()","moviemasher::graph::color_value()","moviemasher::filterevaluated#command_parameters()","moviemasher::path::concat()","moviemasher::configuration()","moviemasher::configure()","moviemasher::callback::create()","moviemasher::input::create()","moviemasher::output::create()","moviemasher::source::create()","moviemasher::transfer::create()","moviemasher::graph#create_layer()","moviemasher::callback#data()","moviemasher::callback#data=()","moviemasher::job#destination()","moviemasher::output#destination()","moviemasher::output#destination=()","moviemasher::input#dimensions()","moviemasher::output#dimensions()","moviemasher::input#dimensions=()","moviemasher::output#dimensions=()","moviemasher::transfer#directory()","moviemasher::transfer#directory=()","moviemasher::timerange#dup()","moviemasher::graph#duration()","moviemasher::input#duration()","moviemasher::mash::duration()","moviemasher::input#duration=()","moviemasher::timerange#end_seconds()","moviemasher::timerange#equals?()","moviemasher::evaluate::equation()","moviemasher::job#error()","moviemasher::callback#extension()","moviemasher::output#extension()","moviemasher::source#extension()","moviemasher::callback#extension=()","moviemasher::output#extension=()","moviemasher::source#extension=()","moviemasher::input#fill()","moviemasher::input#fill=()","moviemasher::filter#filter_command()","moviemasher::filterevaluated#filter_command()","moviemasher::filterhash#filter_command()","moviemasher::filtersource#filter_command()","moviemasher::filtersourcecolor#filter_command()","moviemasher::filter#filter_name()","moviemasher::filtersourcecolor#filter_name()","moviemasher::filtersourcemovie#filter_name()","moviemasher::output#forecolor()","moviemasher::output#forecolor=()","moviemasher::input#gain()","moviemasher::input#gain=()","moviemasher::mash::gain_changes()","moviemasher::goodbye()","moviemasher::graph#graph_command()","moviemasher::graphmash#graph_command()","moviemasher::graphraw#graph_command()","moviemasher::graph#graph_scope()","moviemasher::graphmash#graph_scope()","moviemasher::floatutil::gtr()","moviemasher::floatutil::gtre()","moviemasher::mash::has_audio?()","moviemasher::mash::has_video?()","moviemasher::filterhash#hash()","moviemasher::mash::hash?()","moviemasher::hello()","moviemasher::transfer#host()","moviemasher::transfer#host=()","moviemasher::job#id()","moviemasher::hashable#identifier()","moviemasher::av::includes?()","moviemasher::layer#initialize_chains()","moviemasher::layerrawimage#initialize_chains()","moviemasher::layerrawvideo#initialize_chains()","moviemasher::layertheme#initialize_chains()","moviemasher::layertransition#initialize_chains()","moviemasher::chain#initialize_filters()","moviemasher::chaineffects#initialize_filters()","moviemasher::chainmodule#initialize_filters()","moviemasher::chainoverlay#initialize_filters()","moviemasher::chainmodule#input_scope()","moviemasher::job#inputs()","moviemasher::timerange#intersection()","moviemasher::hashable#keys()","moviemasher::layer#layer_command()","moviemasher::layercolor#layer_command()","moviemasher::layerraw#layer_command()","moviemasher::layerrawimage#layer_command()","moviemasher::layerrawvideo#layer_command()","moviemasher::layertransition#layer_command()","moviemasher::layer#layer_scope()","moviemasher::layermodule#layer_scope()","moviemasher::input#length()","moviemasher::timerange#length()","moviemasher::input#length=()","moviemasher::timerange#length=()","moviemasher::timerange#length_seconds()","moviemasher::floatutil::less()","moviemasher::job#log()","moviemasher::job#log_entry()","moviemasher::input#loop()","moviemasher::input#loop=()","moviemasher::floatutil::max()","moviemasher::mash::media()","moviemasher::mash#media()","moviemasher::mash::media_count_for_clips()","moviemasher::mash::media_search()","moviemasher::av::merge()","moviemasher::layer#merger_command()","moviemasher::transfer#method()","moviemasher::transfer#method=()","moviemasher::floatutil::min()","moviemasher::filterhelpers::mm_cmp()","moviemasher::filterhelpers::mm_dir_horz()","moviemasher::filterhelpers::mm_dir_vert()","moviemasher::filterhelpers::mm_fontfamily()","moviemasher::filterhelpers::mm_fontfile()","moviemasher::filterhelpers::mm_horz()","moviemasher::filterhelpers::mm_max()","moviemasher::filterhelpers::mm_min()","moviemasher::filterhelpers::mm_paren()","moviemasher::filterhelpers::mm_textfile()","moviemasher::filterhelpers::mm_vert()","moviemasher::defaults::module_for_type()","moviemasher::input#module_source()","moviemasher::job#module_source()","moviemasher::callback#name()","moviemasher::output#name()","moviemasher::source#name()","moviemasher::callback#name=()","moviemasher::output#name=()","moviemasher::source#name=()","moviemasher::chain::new()","moviemasher::chainmodule::new()","moviemasher::chainoverlay::new()","moviemasher::chainscaler::new()","moviemasher::error::jobrender::new()","moviemasher::error::runtime::new()","moviemasher::filter::new()","moviemasher::filterevaluated::new()","moviemasher::filterhash::new()","moviemasher::filtersetpts::new()","moviemasher::filtersource::new()","moviemasher::filtersourcecolor::new()","moviemasher::filtersourcemovie::new()","moviemasher::graph::new()","moviemasher::graphmash::new()","moviemasher::graphraw::new()","moviemasher::hashable::new()","moviemasher::job::new()","moviemasher::layer::new()","moviemasher::layercolor::new()","moviemasher::layertransition::new()","moviemasher::timerange::new()","moviemasher::input#no_audio()","moviemasher::output#no_audio()","moviemasher::input#no_audio=()","moviemasher::output#no_audio=()","moviemasher::input#no_video()","moviemasher::input#no_video=()","moviemasher::evaluate::object()","moviemasher::input#offset()","moviemasher::input#offset=()","moviemasher::job#outputs()","moviemasher::transfer#parameters()","moviemasher::transfer#parameters=()","moviemasher::transfer#pass()","moviemasher::transfer#pass=()","moviemasher::output#path()","moviemasher::transfer#path()","moviemasher::output#path=()","moviemasher::transfer#path=()","moviemasher::transfer#port()","moviemasher::transfer#port=()","moviemasher::floatutil::precision()","moviemasher::output#precision()","moviemasher::output#precision=()","moviemasher::process()","moviemasher::job#process()","moviemasher::process_jobs()","moviemasher::process_queues()","moviemasher::job#progress()","moviemasher::callback#progress_seconds()","moviemasher::callback#progress_seconds=()","moviemasher::output#quality()","moviemasher::output#quality=()","moviemasher::layer#range()","moviemasher::layercolor#range()","moviemasher::timerange#rate()","moviemasher::timerange#rate=()","moviemasher::transfer#region()","moviemasher::transfer#region=()","moviemasher::output#required()","moviemasher::output#required=()","moviemasher::job::resolved_hash()","moviemasher::job::resolved_string()","moviemasher::filterhelpers::rgb()","moviemasher::filterhelpers::rgba()","moviemasher::floatutil::sort()","moviemasher::input#source()","moviemasher::input#source=()","moviemasher::input#start()","moviemasher::timerange#start()","moviemasher::input#start=()","moviemasher::timerange#start=()","moviemasher::timerange#start_seconds()","moviemasher::timerange#stop()","moviemasher::floatutil::string()","moviemasher::job::string_type()","moviemasher::path::strip_slash_end()","moviemasher::path::strip_slash_start()","moviemasher::path::strip_slashes()","moviemasher::timerange#synchronize()","moviemasher::hashable#to_hash()","moviemasher::hashable#to_json()","moviemasher::error::runtime#to_s()","moviemasher::callback#trigger()","moviemasher::callback#trigger=()","moviemasher::layer#trim_command()","moviemasher::layercolor#trim_command()","moviemasher::input#type()","moviemasher::output#type()","moviemasher::transfer#type()","moviemasher::input#type=()","moviemasher::output#type=()","moviemasher::transfer#type=()","moviemasher::transfer#user()","moviemasher::transfer#user=()","moviemasher::evaluate::value()","moviemasher::hashable#values()","moviemasher::mash#video()","moviemasher::output#video_bitrate()","moviemasher::output#video_bitrate=()","moviemasher::output#video_codec()","moviemasher::output#video_codec=()","moviemasher::output#video_format()","moviemasher::output#video_format=()","moviemasher::mash::video_ranges()",""],"info":[["MovieMasher","","MovieMasher.html","","

    Handles global configuration and high level processing of Job objects. The\n::process_queues method will …\n"],["MovieMasher::AV","","MovieMasher/AV.html","",""],["MovieMasher::Callback","","MovieMasher/Callback.html","","

    A Transfer object and element in Job#callbacks representing a remote\nrequesttriggered at a particular …\n"],["MovieMasher::Chain","","MovieMasher/Chain.html","","

    chain\n"],["MovieMasher::ChainEffects","","MovieMasher/ChainEffects.html","",""],["MovieMasher::ChainModule","","MovieMasher/ChainModule.html","",""],["MovieMasher::ChainOverlay","","MovieMasher/ChainOverlay.html","",""],["MovieMasher::ChainScaler","","MovieMasher/ChainScaler.html","",""],["MovieMasher::Configuration","","MovieMasher/Configuration.html","",""],["MovieMasher::Defaults","","MovieMasher/Defaults.html","",""],["MovieMasher::Error","","MovieMasher/Error.html","",""],["MovieMasher::Error::Configuration","","MovieMasher/Error/Configuration.html","",""],["MovieMasher::Error::Critical","","MovieMasher/Error/Critical.html","","

    serious code errors\n"],["MovieMasher::Error::Job","","MovieMasher/Error/Job.html","","

    job related errors\n"],["MovieMasher::Error::JobInput","","MovieMasher/Error/JobInput.html","",""],["MovieMasher::Error::JobOutput","","MovieMasher/Error/JobOutput.html","",""],["MovieMasher::Error::JobRender","","MovieMasher/Error/JobRender.html","",""],["MovieMasher::Error::JobSource","","MovieMasher/Error/JobSource.html","",""],["MovieMasher::Error::JobUpload","","MovieMasher/Error/JobUpload.html","",""],["MovieMasher::Error::Object","","MovieMasher/Error/Object.html","",""],["MovieMasher::Error::Parameter","","MovieMasher/Error/Parameter.html","",""],["MovieMasher::Error::Runtime","","MovieMasher/Error/Runtime.html","",""],["MovieMasher::Error::State","","MovieMasher/Error/State.html","",""],["MovieMasher::Error::Todo","","MovieMasher/Error/Todo.html","",""],["MovieMasher::Evaluate","","MovieMasher/Evaluate.html","",""],["MovieMasher::Fill","","MovieMasher/Fill.html","",""],["MovieMasher::Filter","","MovieMasher/Filter.html","",""],["MovieMasher::FilterEvaluated","","MovieMasher/FilterEvaluated.html","",""],["MovieMasher::FilterHash","","MovieMasher/FilterHash.html","",""],["MovieMasher::FilterHelpers","","MovieMasher/FilterHelpers.html","",""],["MovieMasher::FilterSetpts","","MovieMasher/FilterSetpts.html","",""],["MovieMasher::FilterSource","","MovieMasher/FilterSource.html","",""],["MovieMasher::FilterSourceColor","","MovieMasher/FilterSourceColor.html","",""],["MovieMasher::FilterSourceMovie","","MovieMasher/FilterSourceMovie.html","",""],["MovieMasher::FloatUtil","","MovieMasher/FloatUtil.html","",""],["MovieMasher::Gain","","MovieMasher/Gain.html","",""],["MovieMasher::Graph","","MovieMasher/Graph.html","",""],["MovieMasher::GraphMash","","MovieMasher/GraphMash.html","",""],["MovieMasher::GraphRaw","","MovieMasher/GraphRaw.html","",""],["MovieMasher::Hashable","","MovieMasher/Hashable.html","","

    Mix-in functionality for mocking a Hash.\n"],["MovieMasher::Info","","MovieMasher/Info.html","",""],["MovieMasher::Input","","MovieMasher/Input.html","","

    An element in Job#inputs representing media to be included in the mashup,\nwhich is eventually rendered …\n"],["MovieMasher::Intermediate","","MovieMasher/Intermediate.html","",""],["MovieMasher::Job","","MovieMasher/Job.html","","

    Represents a single transcoding operation. Once #process is called all of\nthe job's #inputs are downloaded …\n"],["MovieMasher::Layer","","MovieMasher/Layer.html","",""],["MovieMasher::LayerColor","","MovieMasher/LayerColor.html","",""],["MovieMasher::LayerModule","","MovieMasher/LayerModule.html","",""],["MovieMasher::LayerRaw","","MovieMasher/LayerRaw.html","",""],["MovieMasher::LayerRawImage","","MovieMasher/LayerRawImage.html","",""],["MovieMasher::LayerRawVideo","","MovieMasher/LayerRawVideo.html","",""],["MovieMasher::LayerTheme","","MovieMasher/LayerTheme.html","",""],["MovieMasher::LayerTransition","","MovieMasher/LayerTransition.html","",""],["MovieMasher::Mash","","MovieMasher/Mash.html","","

    Input#source of mash inputs, representing a collection #media arranged on\n#audio and #video tracks. …\n"],["MovieMasher::Method","","MovieMasher/Method.html","",""],["MovieMasher::Output","","MovieMasher/Output.html","","

    Represents a single rendered version of the mashup, including all\nformatting parameters and quality settings. …\n"],["MovieMasher::Path","","MovieMasher/Path.html","",""],["MovieMasher::Source","","MovieMasher/Source.html","","

    A Transfer object used for Input#source and Media#source, describing how to\nretrieve an audio, image, …\n"],["MovieMasher::TimeRange","","MovieMasher/TimeRange.html","",""],["MovieMasher::Transfer","","MovieMasher/Transfer.html","","

    Base class for Callback and Source as well as used directly to resolve\nInput and Output relative paths …\n"],["<<","MovieMasher::Chain","MovieMasher/Chain.html#method-i-3C-3C","(filter)",""],["[]","MovieMasher::Hashable","MovieMasher/Hashable.html#method-i-5B-5D","(symbol)","

    Convenience getter for underlying data Hash.\n

    symbol — Symbol key into hash.\n\n

    Returns value of key or nil if …\n"],["[]=","MovieMasher::Hashable","MovieMasher/Hashable.html#method-i-5B-5D-3D","(symbol, value)","

    Convenience setter for underlying data Hash.\n

    symbol — Symbol key into hash.\n

    value — Object to set at key.\n"],["__coerce","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__coerce","(s)",""],["__command_name_value","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__command_name_value","(name, value, scope, job_output)",""],["__filter_dimension_keys","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__filter_dimension_keys","(filter_id)",""],["__filter_is_source?","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__filter_is_source-3F","(filter_id)",""],["__filter_parse_scope_value","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__filter_parse_scope_value","(scope, value_str, job_output = nil)",""],["__filter_scope_binding","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-__filter_scope_binding","(scope)",""],["__filter_trim_input","MovieMasher::LayerRawVideo","MovieMasher/LayerRawVideo.html#method-i-__filter_trim_input","()",""],["add_new_layer","MovieMasher::GraphMash","MovieMasher/GraphMash.html#method-i-add_new_layer","(input)",""],["add_new_layer","MovieMasher::LayerTransition","MovieMasher/LayerTransition.html#method-i-add_new_layer","(clip)",""],["add_slash_end","MovieMasher::Path","MovieMasher/Path.html#method-c-add_slash_end","(s)",""],["add_slash_start","MovieMasher::Path","MovieMasher/Path.html#method-c-add_slash_start","(s)",""],["add_slashes","MovieMasher::Path","MovieMasher/Path.html#method-c-add_slashes","(s)",""],["audio","MovieMasher::Mash","MovieMasher/Mash.html#method-i-audio","()","

    Array — One or more Track objects.\n\n"],["audio_bitrate","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_bitrate","()",""],["audio_bitrate=","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_bitrate-3D","(value)","

    String — FFmpeg -b:a switch, placed before #audio_rate.\n

    Integer — The character 'k' will be appended. …\n"],["audio_codec","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_codec","()",""],["audio_codec=","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_codec-3D","(value)","

    String — FFmpeg -c:a switch, placed after #audio_rate.\n

    Default — aac -strict experimental\n

    Types — TypeAudio …\n"],["audio_rate","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_rate","()",""],["audio_rate=","MovieMasher::Output","MovieMasher/Output.html#method-i-audio_rate-3D","(value)","

    String — FFmpeg -r:a switch, placed after #audio_bitrate and before #audio_codec.\n

    Default — 44100\n

    Types — TypeAudio …\n"],["av","MovieMasher::Input","MovieMasher/Input.html#method-i-av","()","

    String — The AV type.\n

    Constant — AV::Audio, AV::Video, AV::Both, or AV::Neither if an error was encountered\n…\n"],["av","MovieMasher::Output","MovieMasher/Output.html#method-i-av","()","

    String — The AV type.\n

    Constant — AV::Audio, AV::Video or AV::Both.\n

    Default — Based on #type and #no_audio.\n"],["backcolor","MovieMasher::Output","MovieMasher/Output.html#method-i-backcolor","()",""],["backcolor=","MovieMasher::Output","MovieMasher/Output.html#method-i-backcolor-3D","(value)","

    String — Six character hex, rgb(0,0,0) or standard color name.\n

    Default — FFFFFF for TypeWaveform, black for …\n"],["base_source","MovieMasher::Input","MovieMasher/Input.html#method-i-base_source","()","

    Transfer — Resolves relative URLs.\n

    Default — Job#base_source\n

    Types — Just TypeMash.\n"],["base_source","MovieMasher::Job","MovieMasher/Job.html#method-i-base_source","()","

    Transfer — Resolves relative paths within Input#source and Media#source String values.\n\n"],["bucket","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-bucket","()",""],["bucket=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-bucket-3D","(value)","

    String — Name of AWS S3 bucket where file is stored.\n

    Types — Just TypeS3.\n\n"],["callbacks","MovieMasher::Job","MovieMasher/Job.html#method-i-callbacks","()","

    Array — Zero or more Callback objects.\n\n"],["chain_command","MovieMasher::Chain","MovieMasher/Chain.html#method-i-chain_command","(scope, job_output)",""],["chain_command","MovieMasher::ChainModule","MovieMasher/ChainModule.html#method-i-chain_command","(scope, job_output)",""],["chain_command","MovieMasher::ChainScaler","MovieMasher/ChainScaler.html#method-i-chain_command","(scope, job_output)",""],["class_symbol","MovieMasher::Hashable","MovieMasher/Hashable.html#method-i-class_symbol","()","

    Returns Symbol of lowercased class name without namespace qualifiers.\n"],["clip_has_audio","MovieMasher::Mash","MovieMasher/Mash.html#method-c-clip_has_audio","(clip)",""],["clips_having_audio","MovieMasher::Mash","MovieMasher/Mash.html#method-c-clips_having_audio","(mash)",""],["clips_in_range","MovieMasher::Mash","MovieMasher/Mash.html#method-c-clips_in_range","(mash, range, track_type)",""],["cmp","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-cmp","(f1, f2, digits = 3)",""],["color_value","MovieMasher::Graph","MovieMasher/Graph.html#method-c-color_value","(color)",""],["command_parameters","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-command_parameters","(scope, job_output)",""],["concat","MovieMasher::Path","MovieMasher/Path.html#method-c-concat","(s1, s2)",""],["configuration","MovieMasher","MovieMasher.html#method-c-configuration","()","

    Returns the configuration Hash with Symbol keys.\n"],["configure","MovieMasher","MovieMasher.html#method-c-configure","(hash_or_path)","

    hash_or_path — Set one or more configuration options. If supplied a String, it's\nassumed to be a path …\n\n"],["create","MovieMasher::Callback","MovieMasher/Callback.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create","MovieMasher::Input","MovieMasher/Input.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create","MovieMasher::Output","MovieMasher/Output.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create","MovieMasher::Source","MovieMasher/Source.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create","MovieMasher::Transfer","MovieMasher/Transfer.html#method-c-create","(hash)","

    Returns a new instance.\n"],["create_layer","MovieMasher::Graph","MovieMasher/Graph.html#method-i-create_layer","(input)",""],["data","MovieMasher::Callback","MovieMasher/Callback.html#method-i-data","()",""],["data=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-data-3D","(value)","

    Hash/Array - Values to recursively evaluate and parse into request body.\n

    Default — nil\n\n"],["destination","MovieMasher::Job","MovieMasher/Job.html#method-i-destination","()","

    Transfer — Shared by all Output objects that don't have one of their own.\n\n"],["destination","MovieMasher::Output","MovieMasher/Output.html#method-i-destination","()",""],["destination=","MovieMasher::Output","MovieMasher/Output.html#method-i-destination-3D","(value)","

    Transfer — Describes where to upload this output.\n

    Default — Job#destination\n\n"],["dimensions","MovieMasher::Input","MovieMasher/Input.html#method-i-dimensions","()",""],["dimensions","MovieMasher::Output","MovieMasher/Output.html#method-i-dimensions","()",""],["dimensions=","MovieMasher::Input","MovieMasher/Input.html#method-i-dimensions-3D","(value)","

    String — WIDTHxHEIGHT of element.\n

    Default — Probed from downloaded.\n

    Types — TypeImage and TypeVideo.\n"],["dimensions=","MovieMasher::Output","MovieMasher/Output.html#method-i-dimensions-3D","(value)","

    String — Output pixel size formatted as WIDTHxHEIGHT.\n

    Default — 512x288 for TypeVideo, 8000x32 for TypeWaveform …\n"],["directory","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-directory","()",""],["directory=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-directory-3D","(value)","

    String — Added to URL after #directory and before #name, with slash on either side.\n

    Default — Nil means do …\n"],["dup","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-dup","()",""],["duration","MovieMasher::Graph","MovieMasher/Graph.html#method-i-duration","()",""],["duration","MovieMasher::Input","MovieMasher/Input.html#method-i-duration","()",""],["duration","MovieMasher::Mash","MovieMasher/Mash.html#method-c-duration","(mash)",""],["duration=","MovieMasher::Input","MovieMasher/Input.html#method-i-duration-3D","(value)","

    Float — Seconds of input available for presentation.\n

    Default — Probed from downloaded.\n

    Types — All except TypeImage …\n"],["end_seconds","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-end_seconds","()",""],["equals?","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-equals-3F","(range)",""],["equation","MovieMasher::Evaluate","MovieMasher/Evaluate.html#method-c-equation","(s, raise_on_fail = nil)",""],["error","MovieMasher::Job","MovieMasher/Job.html#method-i-error","()","

    Problem encountered during #new or #process. If the source of the problem\nis a command line application …\n"],["extension","MovieMasher::Callback","MovieMasher/Callback.html#method-i-extension","()",""],["extension","MovieMasher::Output","MovieMasher/Output.html#method-i-extension","()",""],["extension","MovieMasher::Source","MovieMasher/Source.html#method-i-extension","()",""],["extension=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-extension-3D","(value)","

    String — Added to file path after #name, with period inserted between.\n\n"],["extension=","MovieMasher::Output","MovieMasher/Output.html#method-i-extension-3D","(value)","

    String — Extension for rendered file, also implies format.\n

    Default — Removed from #name if present, otherwise …\n\n"],["extension=","MovieMasher::Source","MovieMasher/Source.html#method-i-extension-3D","(value)","

    String — Appended to file path after #name, with period inserted between.\n\n"],["fill","MovieMasher::Input","MovieMasher/Input.html#method-i-fill","()",""],["fill=","MovieMasher::Input","MovieMasher/Input.html#method-i-fill-3D","(value)","

    String — How to size in relation to Output#dimensions.\n

    Constant — Fill::Crop, Fill::None, Fill::Scale or …\n"],["filter_command","MovieMasher::Filter","MovieMasher/Filter.html#method-i-filter_command","(scope, job_output)",""],["filter_command","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-i-filter_command","(scope = nil, job_output = nil)",""],["filter_command","MovieMasher::FilterHash","MovieMasher/FilterHash.html#method-i-filter_command","(scope = nil, job_output = nil)",""],["filter_command","MovieMasher::FilterSource","MovieMasher/FilterSource.html#method-i-filter_command","(scope, job_output)",""],["filter_command","MovieMasher::FilterSourceColor","MovieMasher/FilterSourceColor.html#method-i-filter_command","(scope, job_output)",""],["filter_name","MovieMasher::Filter","MovieMasher/Filter.html#method-i-filter_name","()",""],["filter_name","MovieMasher::FilterSourceColor","MovieMasher/FilterSourceColor.html#method-i-filter_name","()",""],["filter_name","MovieMasher::FilterSourceMovie","MovieMasher/FilterSourceMovie.html#method-i-filter_name","()",""],["forecolor","MovieMasher::Output","MovieMasher/Output.html#method-i-forecolor","()",""],["forecolor=","MovieMasher::Output","MovieMasher/Output.html#method-i-forecolor-3D","(value)","

    String — Six character Hex color.\n

    Default — 000000\n

    Types — Only TypeWaveform.\n"],["gain","MovieMasher::Input","MovieMasher/Input.html#method-i-gain","()",""],["gain=","MovieMasher::Input","MovieMasher/Input.html#method-i-gain-3D","(value)","

    Float — Multiplier to adjust volume of audio when mixed into mashup.\n

    Array — Duple Float values signifying …\n"],["gain_changes","MovieMasher::Mash","MovieMasher/Mash.html#method-c-gain_changes","(gain)",""],["goodbye","MovieMasher","MovieMasher.html#method-c-goodbye","()","

    Returns valediction for command line apps.\n"],["graph_command","MovieMasher::Graph","MovieMasher/Graph.html#method-i-graph_command","(output, job = nil)",""],["graph_command","MovieMasher::GraphMash","MovieMasher/GraphMash.html#method-i-graph_command","(output, job = nil)",""],["graph_command","MovieMasher::GraphRaw","MovieMasher/GraphRaw.html#method-i-graph_command","(output, job = nil)",""],["graph_scope","MovieMasher::Graph","MovieMasher/Graph.html#method-i-graph_scope","()",""],["graph_scope","MovieMasher::GraphMash","MovieMasher/GraphMash.html#method-i-graph_scope","()",""],["gtr","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-gtr","(big, small, digits = 3)",""],["gtre","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-gtre","(big, small, digits = 3)",""],["has_audio?","MovieMasher::Mash","MovieMasher/Mash.html#method-c-has_audio-3F","(mash)",""],["has_video?","MovieMasher::Mash","MovieMasher/Mash.html#method-c-has_video-3F","(mash)",""],["hash","MovieMasher::FilterHash","MovieMasher/FilterHash.html#method-i-hash","()",""],["hash?","MovieMasher::Mash","MovieMasher/Mash.html#method-c-hash-3F","(hash)",""],["hello","MovieMasher","MovieMasher.html#method-c-hello","()","

    Returns salutation for command line apps.\n"],["host","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-host","()",""],["host=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-host-3D","(value)","

    String — Remote server name or IP address where file is stored.\n

    Types — TypeHttp and TypeHttps.\n\n"],["id","MovieMasher::Job","MovieMasher/Job.html#method-i-id","()","

    String — user supplied identifier.\n

    Default — Nil, or messageId if the Job originated from an SQS message. …\n\n"],["identifier","MovieMasher::Hashable","MovieMasher/Hashable.html#method-i-identifier","()","

    String — Unique identifier for object.\n\n"],["includes?","MovieMasher::AV","MovieMasher/AV.html#method-c-includes-3F","(has, desired)",""],["initialize_chains","MovieMasher::Layer","MovieMasher/Layer.html#method-i-initialize_chains","()",""],["initialize_chains","MovieMasher::LayerRawImage","MovieMasher/LayerRawImage.html#method-i-initialize_chains","()",""],["initialize_chains","MovieMasher::LayerRawVideo","MovieMasher/LayerRawVideo.html#method-i-initialize_chains","()",""],["initialize_chains","MovieMasher::LayerTheme","MovieMasher/LayerTheme.html#method-i-initialize_chains","()",""],["initialize_chains","MovieMasher::LayerTransition","MovieMasher/LayerTransition.html#method-i-initialize_chains","()",""],["initialize_filters","MovieMasher::Chain","MovieMasher/Chain.html#method-i-initialize_filters","()",""],["initialize_filters","MovieMasher::ChainEffects","MovieMasher/ChainEffects.html#method-i-initialize_filters","()",""],["initialize_filters","MovieMasher::ChainModule","MovieMasher/ChainModule.html#method-i-initialize_filters","()",""],["initialize_filters","MovieMasher::ChainOverlay","MovieMasher/ChainOverlay.html#method-i-initialize_filters","()",""],["input_scope","MovieMasher::ChainModule","MovieMasher/ChainModule.html#method-i-input_scope","(scope)",""],["inputs","MovieMasher::Job","MovieMasher/Job.html#method-i-inputs","()","

    Array — One or more Input objects.\n\n"],["intersection","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-intersection","(range)",""],["keys","MovieMasher::Hashable","MovieMasher/Hashable.html#method-i-keys","()",""],["layer_command","MovieMasher::Layer","MovieMasher/Layer.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerColor","MovieMasher/LayerColor.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerRaw","MovieMasher/LayerRaw.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerRawImage","MovieMasher/LayerRawImage.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerRawVideo","MovieMasher/LayerRawVideo.html#method-i-layer_command","(scope, job_output)",""],["layer_command","MovieMasher::LayerTransition","MovieMasher/LayerTransition.html#method-i-layer_command","(scope, job_output)",""],["layer_scope","MovieMasher::Layer","MovieMasher/Layer.html#method-i-layer_scope","(scope, job_output)",""],["layer_scope","MovieMasher::LayerModule","MovieMasher/LayerModule.html#method-i-layer_scope","(scope, job_output)",""],["length","MovieMasher::Input","MovieMasher/Input.html#method-i-length","()",""],["length","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-length","()",""],["length=","MovieMasher::Input","MovieMasher/Input.html#method-i-length-3D","(value)","

    Float — Seconds the input appears in the mashup.\n

    Default — #duration - #offset\n\n"],["length=","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-length-3D","(n)",""],["length_seconds","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-length_seconds","(precision = 3)",""],["less","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-less","(small, big, digits = 3)",""],["log","MovieMasher::Job","MovieMasher/Job.html#method-i-log","()","

    String — Current content of the job's log file.\n\n"],["log_entry","MovieMasher::Job","MovieMasher/Job.html#method-i-log_entry","(type, &proc)","

    Output to the job's log file. If type is :error then\njob will be halted and its #error will be set …\n"],["loop","MovieMasher::Input","MovieMasher/Input.html#method-i-loop","()",""],["loop=","MovieMasher::Input","MovieMasher/Input.html#method-i-loop-3D","(value)","

    Integer — Number of times to loop input.\n

    Types — Just TypeAudio.\n\n"],["max","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-max","(a, b, digits = 3)",""],["media","MovieMasher::Mash","MovieMasher/Mash.html#method-c-media","(mash, ob_or_id)",""],["media","MovieMasher::Mash","MovieMasher/Mash.html#method-i-media","()","

    Array — One or more Media objects.\n\n"],["media_count_for_clips","MovieMasher::Mash","MovieMasher/Mash.html#method-c-media_count_for_clips","(mash, clips, referenced)",""],["media_search","MovieMasher::Mash","MovieMasher/Mash.html#method-c-media_search","(type, ob_or_id, mash)",""],["merge","MovieMasher::AV","MovieMasher/AV.html#method-c-merge","(type1, type2)",""],["merger_command","MovieMasher::Layer","MovieMasher/Layer.html#method-i-merger_command","(scope)",""],["method","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-method","()",""],["method=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-method-3D","(value)","

    String — How to retrieve the file.\n

    Constant — Method::Copy, Method::Move or Method::Symlink.\n

    Default — Method::Symlink …\n"],["min","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-min","(a, b, digits = 3)",""],["mm_cmp","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_cmp","(param_string, mash, scope, output = nil)",""],["mm_dir_horz","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_dir_horz","(param_string, mash, scope, output = nil)",""],["mm_dir_vert","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_dir_vert","(param_string, mash, scope, output = nil)",""],["mm_fontfamily","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_fontfamily","(param_string, mash, scope, output = nil)",""],["mm_fontfile","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_fontfile","(param_string, mash, scope, output = nil)",""],["mm_horz","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_horz","(param_string, mash = nil, scope = nil, output = nil)",""],["mm_max","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_max","(param_string, mash, scope, output = nil)",""],["mm_min","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_min","(param_string, mash, scope, output = nil)",""],["mm_paren","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_paren","(param_string, mash, scope, output = nil)",""],["mm_textfile","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_textfile","(param_string, mash, scope, output = nil)",""],["mm_vert","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-mm_vert","(param_string, mash = nil, scope = nil, output = nil)",""],["module_for_type","MovieMasher::Defaults","MovieMasher/Defaults.html#method-c-module_for_type","(type, media_id = nil)",""],["module_source","MovieMasher::Input","MovieMasher/Input.html#method-i-module_source","()","

    Transfer — Resolves relative font URLs for modules.\n

    Default — Job#module_source\n

    Types — Just TypeMash.\n"],["module_source","MovieMasher::Job","MovieMasher/Job.html#method-i-module_source","()","

    Transfer — Resolves relative font paths within Media#source String values.\n

    Default — #base_source\n\n"],["name","MovieMasher::Callback","MovieMasher/Callback.html#method-i-name","()",""],["name","MovieMasher::Output","MovieMasher/Output.html#method-i-name","()",""],["name","MovieMasher::Source","MovieMasher/Source.html#method-i-name","()",""],["name=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-name-3D","(value)","

    String — The full or basename of file added to URL after #path. If full, #extension\nwill be set and removed …\n\n"],["name=","MovieMasher::Output","MovieMasher/Output.html#method-i-name-3D","(value)","

    String — Basename for rendered file.\n

    Default — #type, or empty for TypeSequence.\n

    Types — All, but TypeSequence …\n"],["name=","MovieMasher::Source","MovieMasher/Source.html#method-i-name-3D","(value)","

    String — The full or basename of file appended to file path. If full, #extension\nwill be set and removed …\n\n"],["new","MovieMasher::Chain","MovieMasher/Chain.html#method-c-new","(input = nil, job_input = nil)",""],["new","MovieMasher::ChainModule","MovieMasher/ChainModule.html#method-c-new","(mod_input, mash_input, applied_input)",""],["new","MovieMasher::ChainOverlay","MovieMasher/ChainOverlay.html#method-c-new","(job_output)",""],["new","MovieMasher::ChainScaler","MovieMasher/ChainScaler.html#method-c-new","(input = nil, job_input = nil)",""],["new","MovieMasher::Error::JobRender","MovieMasher/Error/JobRender.html#method-c-new","(ffmpeg_result, msg = \"failed to render\")",""],["new","MovieMasher::Error::Runtime","MovieMasher/Error/Runtime.html#method-c-new","(msg = nil)",""],["new","MovieMasher::Filter","MovieMasher/Filter.html#method-c-new","(id = nil)",""],["new","MovieMasher::FilterEvaluated","MovieMasher/FilterEvaluated.html#method-c-new","(filter_config, mash_input = nil, applied_input = nil)",""],["new","MovieMasher::FilterHash","MovieMasher/FilterHash.html#method-c-new","(id, hash = nil)",""],["new","MovieMasher::FilterSetpts","MovieMasher/FilterSetpts.html#method-c-new","(expr = 'PTS-STARTPTS')",""],["new","MovieMasher::FilterSource","MovieMasher/FilterSource.html#method-c-new","(id, hash, dimensions = nil)",""],["new","MovieMasher::FilterSourceColor","MovieMasher/FilterSourceColor.html#method-c-new","(duration, color)",""],["new","MovieMasher::FilterSourceMovie","MovieMasher/FilterSourceMovie.html#method-c-new","(input, job_input)",""],["new","MovieMasher::Graph","MovieMasher/Graph.html#method-c-new","(job_input, render_range = nil, label_name = 'layer')",""],["new","MovieMasher::GraphMash","MovieMasher/GraphMash.html#method-c-new","(mash_input, render_range, label_name = 'layer')",""],["new","MovieMasher::GraphRaw","MovieMasher/GraphRaw.html#method-c-new","(input)",""],["new","MovieMasher::Hashable","MovieMasher/Hashable.html#method-c-new","(hash)","

    Set the actual Hash when creating.\n"],["new","MovieMasher::Job","MovieMasher/Job.html#method-c-new","(hash_or_path, configuration = nil)","

    Create a new Job object from a nested structure or a file path.\n

    hash_or_path — Hash or String expected to …\n\n"],["new","MovieMasher::Layer","MovieMasher/Layer.html#method-c-new","(input, job_input)",""],["new","MovieMasher::LayerColor","MovieMasher/LayerColor.html#method-c-new","(duration, color)",""],["new","MovieMasher::LayerTransition","MovieMasher/LayerTransition.html#method-c-new","(input, job_input, job)",""],["new","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-c-new","(start = 0, rate = 0, length = 1)",""],["no_audio","MovieMasher::Input","MovieMasher/Input.html#method-i-no_audio","()",""],["no_audio","MovieMasher::Output","MovieMasher/Output.html#method-i-no_audio","()",""],["no_audio=","MovieMasher::Input","MovieMasher/Input.html#method-i-no_audio-3D","(value)","

    Boolean — If true, audio in input will be ignored.\n

    Default — Initially based on #type, but could change after …\n"],["no_audio=","MovieMasher::Output","MovieMasher/Output.html#method-i-no_audio-3D","(value)","

    Boolean — If true, audio in inputs will not be included.\n

    Default — FALSE\n

    Types — Just TypeVideo, but accessible …\n"],["no_video","MovieMasher::Input","MovieMasher/Input.html#method-i-no_video","()",""],["no_video=","MovieMasher::Input","MovieMasher/Input.html#method-i-no_video-3D","(value)","

    Boolean — If true, video in input will be ignored.\n

    Default — Initially based on #type, but could change after …\n"],["object","MovieMasher::Evaluate","MovieMasher/Evaluate.html#method-c-object","(data, scope = nil)",""],["offset","MovieMasher::Input","MovieMasher/Input.html#method-i-offset","()",""],["offset=","MovieMasher::Input","MovieMasher/Input.html#method-i-offset-3D","(value)","

    Float — Seconds to remove from beginning of input.\n

    Default — 0.0 means nothing removed.\n

    Types — TypeAudio and …\n"],["outputs","MovieMasher::Job","MovieMasher/Job.html#method-i-outputs","()","

    Array — One or more Output objects.\n\n"],["parameters","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-parameters","()",""],["parameters=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-parameters-3D","(value)","

    Hash — Query string parameters to send with request for file. The values\nareevaluated, with Job and Input …\n"],["pass","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-pass","()",""],["pass=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-pass-3D","(value)","

    String — Password for standard HTTP authentication.\n

    Default — Nil means do not provide authenticating details. …\n"],["path","MovieMasher::Output","MovieMasher/Output.html#method-i-path","()",""],["path","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-path","()",""],["path=","MovieMasher::Output","MovieMasher/Output.html#method-i-path-3D","(value)","

    String — Prepended to #name during upload.\n

    Default — empty\n\n"],["path=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-path-3D","(value)","

    String — Added to URL after #directory and before #name, with slash on either side.\n

    Default — Nil means do …\n"],["port","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-port","()",""],["port=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-port-3D","(value)","

    Integer — Port number to contact #host on.\n

    Constant — Method::Copy, Method::Move or Method::Symlink.\n

    Default … — "],["precision","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-precision","(f, digits = 3)",""],["precision","MovieMasher::Output","MovieMasher/Output.html#method-i-precision","()",""],["precision=","MovieMasher::Output","MovieMasher/Output.html#method-i-precision-3D","(value)","

    Integer — Number of decimal places that Job#duration and #duration must match by for\nsuccessful rendering. …\n"],["process","MovieMasher","MovieMasher.html#method-c-process","(object_or_path)","

    object_or_path — Job object or String/Hash to be passed to Job.new along with\n::configuration. After the …\n\n"],["process","MovieMasher::Job","MovieMasher/Job.html#method-i-process","()","

    Downloads assets for each Input, renders each Output and uploads\nto#destination or Output#destination …\n"],["process_jobs","MovieMasher","MovieMasher.html#method-c-process_jobs","(array)","

    Calls process for each item in array\n"],["process_queues","MovieMasher","MovieMasher.html#method-c-process_queues","(process_seconds = nil)","

    Loops for process_seconds searching for the oldest JSON or\nYML formatted job file in queue_directory …\n"],["progress","MovieMasher::Job","MovieMasher/Job.html#method-i-progress","()","

    Current status of processing. The following keys are available:\n

    :downloading — number of files referenced …\n"],["progress_seconds","MovieMasher::Callback","MovieMasher/Callback.html#method-i-progress_seconds","()",""],["progress_seconds=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-progress_seconds-3D","(value)","

    Integer — Seconds to wait before making requests.\n

    Default — 44100\n

    Triggers — Only TriggerProgress.\n"],["quality","MovieMasher::Output","MovieMasher/Output.html#method-i-quality","()",""],["quality=","MovieMasher::Output","MovieMasher/Output.html#method-i-quality-3D","(value)","

    Integer — FFmpeg -q:v switch, 1 (best) to 32 (worst).\n

    Default — 1\n

    Types — TypeImage and TypeSequence.\n"],["range","MovieMasher::Layer","MovieMasher/Layer.html#method-i-range","()",""],["range","MovieMasher::LayerColor","MovieMasher/LayerColor.html#method-i-range","()",""],["rate","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-rate","()",""],["rate=","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-rate-3D","(n)",""],["region","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-region","()",""],["region=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-region-3D","(value)","

    String — Global AWS geographical region code.\n

    Default — Nil means us-east-1 standard region.\n

    Types — Just TypeS3 …\n"],["required","MovieMasher::Output","MovieMasher/Output.html#method-i-required","()",""],["required=","MovieMasher::Output","MovieMasher/Output.html#method-i-required-3D","(value)","

    Boolean — Whether or not Job should halt if output cannot be rendered or uploaded.\n

    Default — nil\n\n"],["resolved_hash","MovieMasher::Job","MovieMasher/Job.html#method-c-resolved_hash","(hash_or_path)",""],["resolved_string","MovieMasher::Job","MovieMasher/Job.html#method-c-resolved_string","(hash_or_path)",""],["rgb","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-rgb","(param_string, mash = nil, scope = nil, output = nil)",""],["rgba","MovieMasher::FilterHelpers","MovieMasher/FilterHelpers.html#method-c-rgba","(param_string, mash = nil, scope = nil, output = nil)",""],["sort","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-sort","(a, b)",""],["source","MovieMasher::Input","MovieMasher/Input.html#method-i-source","()",""],["source=","MovieMasher::Input","MovieMasher/Input.html#method-i-source-3D","(value)","

    Describes the download request for the element, as either a URL or\nHash/Source. If the URL is relative …\n"],["start","MovieMasher::Input","MovieMasher/Input.html#method-i-start","()",""],["start","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-start","()",""],["start=","MovieMasher::Input","MovieMasher/Input.html#method-i-start-3D","(value)","

    Float — Seconds from start of mashup to introduce the input.\n

    Default — -1.0 means after previous audio in …\n"],["start=","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-start-3D","(n)",""],["start_seconds","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-start_seconds","(precision = 3)",""],["stop","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-stop","()",""],["string","MovieMasher::FloatUtil","MovieMasher/FloatUtil.html#method-c-string","(f, digits = 3)",""],["string_type","MovieMasher::Job","MovieMasher/Job.html#method-c-string_type","(hash_or_path)",""],["strip_slash_end","MovieMasher::Path","MovieMasher/Path.html#method-c-strip_slash_end","(s)",""],["strip_slash_start","MovieMasher::Path","MovieMasher/Path.html#method-c-strip_slash_start","(s)",""],["strip_slashes","MovieMasher::Path","MovieMasher/Path.html#method-c-strip_slashes","(s)",""],["synchronize","MovieMasher::TimeRange","MovieMasher/TimeRange.html#method-i-synchronize","(time, rounding = :round)",""],["to_hash","MovieMasher::Hashable","MovieMasher/Hashable.html#method-i-to_hash","()","

    Return deep copy of underlying Hash.\n"],["to_json","MovieMasher::Hashable","MovieMasher/Hashable.html#method-i-to_json","(state = nil)","

    Return underlying Hash in JSON format.\n"],["to_s","MovieMasher::Error::Runtime","MovieMasher/Error/Runtime.html#method-i-to_s","()",""],["trigger","MovieMasher::Callback","MovieMasher/Callback.html#method-i-trigger","()",""],["trigger=","MovieMasher::Callback","MovieMasher/Callback.html#method-i-trigger-3D","(value)","

    String — The event that fires the request.\n

    Constant — TriggerInitiate, TriggerProgress, TriggerError or TriggerComplete …\n"],["trim_command","MovieMasher::Layer","MovieMasher/Layer.html#method-i-trim_command","(render_range, job_output)",""],["trim_command","MovieMasher::LayerColor","MovieMasher/LayerColor.html#method-i-trim_command","(render_range, job_output)",""],["type","MovieMasher::Input","MovieMasher/Input.html#method-i-type","()",""],["type","MovieMasher::Output","MovieMasher/Output.html#method-i-type","()",""],["type","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-type","()",""],["type=","MovieMasher::Input","MovieMasher/Input.html#method-i-type-3D","(value)","

    String — The kind of input.\n

    Constant — TypeAudio, TypeImage, TypeMash or TypeVideo.\n

    Default — Probed from downloaded. …\n"],["type=","MovieMasher::Output","MovieMasher/Output.html#method-i-type-3D","(value)","

    String — The kind of output.\n

    Constant — TypeAudio, TypeImage, TypeSequence, TypeVideo or TypeWaveform.\n

    Default … — "],["type=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-type-3D","(value)","

    String — The kind of transfer.\n

    Constant — TypeFile, TypeHttp, TypeHttps or TypeS3.\n

    Default — TypeFile\n"],["user","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-user","()",""],["user=","MovieMasher::Transfer","MovieMasher/Transfer.html#method-i-user-3D","(value)","

    String — Username for standard HTTP authentication.\n

    Default — Nil means do not provide authenticating details. …\n"],["value","MovieMasher::Evaluate","MovieMasher/Evaluate.html#method-c-value","(v, scope)",""],["values","MovieMasher::Hashable","MovieMasher/Hashable.html#method-i-values","()",""],["video","MovieMasher::Mash","MovieMasher/Mash.html#method-i-video","()","

    Array — One or more Track objects.\n\n"],["video_bitrate","MovieMasher::Output","MovieMasher/Output.html#method-i-video_bitrate","()",""],["video_bitrate=","MovieMasher::Output","MovieMasher/Output.html#method-i-video_bitrate-3D","(value)","

    String — FFmpeg -b:v switch, placed after #video_codec and before #video_rate.\n

    Integer — The character 'k' …\n"],["video_codec","MovieMasher::Output","MovieMasher/Output.html#method-i-video_codec","()",""],["video_codec=","MovieMasher::Output","MovieMasher/Output.html#method-i-video_codec-3D","(value)","

    String — FFmpeg -c:v switch, placed after #video_format and before #video_bitrate.\n

    Default — libx264 -level …\n"],["video_format","MovieMasher::Output","MovieMasher/Output.html#method-i-video_format","()",""],["video_format=","MovieMasher::Output","MovieMasher/Output.html#method-i-video_format-3D","(value)","

    String — FFmpeg -f:v switch, placed after #dimensions and before #video_codec.\n

    Default — nil\n

    Types — Only TypeVideo …\n"],["video_ranges","MovieMasher::Mash","MovieMasher/Mash.html#method-c-video_ranges","(mash)",""],["Documentation","","Documentation_md.html","","

    moviemasher.js | angular-moviemasher | moviemasher.rb\n

    Ruby library for mashing up video, images and audio …\n"]]}} \ No newline at end of file diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index e71d4cd..3997725 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -26,22 +26,14 @@

    Table of Contents - RDoc Documentation

    Pages

    • - LICENSE -
    • -
    • - README + Documentation
    • @@ -72,6 +64,9 @@

      Classes/Modules

    • MovieMasher::ChainScaler +
    • +
    • + MovieMasher::Configuration
    • MovieMasher::Defaults @@ -162,6 +157,9 @@

      Classes/Modules

    • MovieMasher::GraphRaw +
    • +
    • + MovieMasher::Hashable
    • MovieMasher::Info @@ -174,9 +172,6 @@

      Classes/Modules

    • MovieMasher::Job -
    • -
    • - MovieMasher::JobHash
    • MovieMasher::Layer @@ -251,11 +246,11 @@

      Methods

    • ::configure — MovieMasher -
    • ::create — MovieMasher::Output +
    • ::create — MovieMasher::Transfer
    • ::create — MovieMasher::Source -
    • ::create — MovieMasher::Transfer +
    • ::create — MovieMasher::Output
    • ::create — MovieMasher::Callback @@ -267,6 +262,8 @@

      Methods

    • ::gain_changes — MovieMasher::Mash +
    • ::goodbye — MovieMasher +
    • ::gtr — MovieMasher::FloatUtil
    • ::gtre — MovieMasher::FloatUtil @@ -277,6 +274,8 @@

      Methods

    • ::hash? — MovieMasher::Mash +
    • ::hello — MovieMasher +
    • ::includes? — MovieMasher::AV
    • ::less — MovieMasher::FloatUtil @@ -317,17 +316,21 @@

      Methods

    • ::module_for_type — MovieMasher::Defaults -
    • ::new — MovieMasher::FilterSourceMovie +
    • ::new — MovieMasher::FilterEvaluated -
    • ::new — MovieMasher::FilterSource +
    • ::new — MovieMasher::FilterSourceColor + +
    • ::new — MovieMasher::LayerTransition
    • ::new — MovieMasher::Job -
    • ::new — MovieMasher::FilterSourceColor +
    • ::new — MovieMasher::Error::JobRender -
    • ::new — MovieMasher::LayerColor +
    • ::new — MovieMasher::FilterSourceMovie -
    • ::new — MovieMasher::Error::JobRender +
    • ::new — MovieMasher::FilterSource + +
    • ::new — MovieMasher::Graph
    • ::new — MovieMasher::FilterSetpts @@ -335,30 +338,26 @@

      Methods

    • ::new — MovieMasher::TimeRange -
    • ::new — MovieMasher::Graph -
    • ::new — MovieMasher::FilterHash -
    • ::new — MovieMasher::JobHash - -
    • ::new — MovieMasher::ChainModule - -
    • ::new — MovieMasher::ChainOverlay -
    • ::new — MovieMasher::GraphMash -
    • ::new — MovieMasher::LayerTransition +
    • ::new — MovieMasher::Hashable -
    • ::new — MovieMasher::ChainScaler +
    • ::new — MovieMasher::ChainModule
    • ::new — MovieMasher::GraphRaw -
    • ::new — MovieMasher::FilterEvaluated +
    • ::new — MovieMasher::ChainOverlay
    • ::new — MovieMasher::Layer
    • ::new — MovieMasher::Filter +
    • ::new — MovieMasher::LayerColor + +
    • ::new — MovieMasher::ChainScaler +
    • ::new — MovieMasher::Chain
    • ::object — MovieMasher::Evaluate @@ -367,8 +366,14 @@

      Methods

    • ::process — MovieMasher +
    • ::process_jobs — MovieMasher +
    • ::process_queues — MovieMasher +
    • ::resolved_hash — MovieMasher::Job + +
    • ::resolved_string — MovieMasher::Job +
    • ::rgb — MovieMasher::FilterHelpers
    • ::rgba — MovieMasher::FilterHelpers @@ -377,6 +382,8 @@

      Methods

    • ::string — MovieMasher::FloatUtil +
    • ::string_type — MovieMasher::Job +
    • ::strip_slash_end — MovieMasher::Path
    • ::strip_slash_start — MovieMasher::Path @@ -389,9 +396,9 @@

      Methods

    • #<< — MovieMasher::Chain -
    • #[] — MovieMasher::JobHash +
    • #[] — MovieMasher::Hashable -
    • #[]= — MovieMasher::JobHash +
    • #[]= — MovieMasher::Hashable
    • #__coerce — MovieMasher::FilterEvaluated @@ -407,10 +414,10 @@

      Methods

    • #__filter_trim_input — MovieMasher::LayerRawVideo -
    • #add_new_layer — MovieMasher::LayerTransition -
    • #add_new_layer — MovieMasher::GraphMash +
    • #add_new_layer — MovieMasher::LayerTransition +
    • #audio — MovieMasher::Mash
    • #audio_bitrate — MovieMasher::Output @@ -425,10 +432,10 @@

      Methods

    • #audio_rate= — MovieMasher::Output -
    • #av — MovieMasher::Output -
    • #av — MovieMasher::Input +
    • #av — MovieMasher::Output +
    • #backcolor — MovieMasher::Output
    • #backcolor= — MovieMasher::Output @@ -443,13 +450,13 @@

      Methods

    • #callbacks — MovieMasher::Job -
    • #chain_command — MovieMasher::ChainScaler +
    • #chain_command — MovieMasher::ChainModule
    • #chain_command — MovieMasher::Chain -
    • #chain_command — MovieMasher::ChainModule +
    • #chain_command — MovieMasher::ChainScaler -
    • #class_symbol — MovieMasher::JobHash +
    • #class_symbol — MovieMasher::Hashable
    • #command_parameters — MovieMasher::FilterEvaluated @@ -491,10 +498,10 @@

      Methods

    • #error — MovieMasher::Job -
    • #extension — MovieMasher::Output -
    • #extension — MovieMasher::Callback +
    • #extension — MovieMasher::Output +
    • #extension — MovieMasher::Source
    • #extension= — MovieMasher::Output @@ -507,22 +514,22 @@

      Methods

    • #fill= — MovieMasher::Input -
    • #filter_command — MovieMasher::FilterSourceColor - -
    • #filter_command — MovieMasher::FilterSource -
    • #filter_command — MovieMasher::FilterEvaluated
    • #filter_command — MovieMasher::FilterHash
    • #filter_command — MovieMasher::Filter -
    • #filter_name — MovieMasher::Filter +
    • #filter_command — MovieMasher::FilterSource -
    • #filter_name — MovieMasher::FilterSourceColor +
    • #filter_command — MovieMasher::FilterSourceColor + +
    • #filter_name — MovieMasher::Filter
    • #filter_name — MovieMasher::FilterSourceMovie +
    • #filter_name — MovieMasher::FilterSourceColor +
    • #forecolor — MovieMasher::Output
    • #forecolor= — MovieMasher::Output @@ -531,16 +538,16 @@

      Methods

    • #gain= — MovieMasher::Input +
    • #graph_command — MovieMasher::Graph +
    • #graph_command — MovieMasher::GraphRaw
    • #graph_command — MovieMasher::GraphMash -
    • #graph_command — MovieMasher::Graph +
    • #graph_scope — MovieMasher::GraphMash
    • #graph_scope — MovieMasher::Graph -
    • #graph_scope — MovieMasher::GraphMash -
    • #hash — MovieMasher::FilterHash
    • #host — MovieMasher::Transfer @@ -549,17 +556,19 @@

      Methods

    • #id — MovieMasher::Job -
    • #identifier — MovieMasher::JobHash +
    • #identifier — MovieMasher::Hashable
    • #initialize_chains — MovieMasher::LayerRawImage
    • #initialize_chains — MovieMasher::LayerTheme -
    • #initialize_chains — MovieMasher::Layer +
    • #initialize_chains — MovieMasher::LayerTransition
    • #initialize_chains — MovieMasher::LayerRawVideo -
    • #initialize_chains — MovieMasher::LayerTransition +
    • #initialize_chains — MovieMasher::Layer + +
    • #initialize_filters — MovieMasher::ChainOverlay
    • #initialize_filters — MovieMasher::Chain @@ -567,34 +576,34 @@

      Methods

    • #initialize_filters — MovieMasher::ChainModule -
    • #initialize_filters — MovieMasher::ChainOverlay -
    • #input_scope — MovieMasher::ChainModule
    • #inputs — MovieMasher::Job
    • #intersection — MovieMasher::TimeRange -
    • #layer_command — MovieMasher::LayerRaw +
    • #keys — MovieMasher::Hashable -
    • #layer_command — MovieMasher::LayerRawVideo +
    • #layer_command — MovieMasher::Layer
    • #layer_command — MovieMasher::LayerColor -
    • #layer_command — MovieMasher::LayerTransition +
    • #layer_command — MovieMasher::LayerRaw
    • #layer_command — MovieMasher::LayerRawImage -
    • #layer_command — MovieMasher::Layer +
    • #layer_command — MovieMasher::LayerRawVideo + +
    • #layer_command — MovieMasher::LayerTransition
    • #layer_scope — MovieMasher::Layer
    • #layer_scope — MovieMasher::LayerModule -
    • #length — MovieMasher::Input -
    • #length — MovieMasher::TimeRange +
    • #length — MovieMasher::Input +
    • #length= — MovieMasher::Input
    • #length= — MovieMasher::TimeRange @@ -621,26 +630,26 @@

      Methods

    • #module_source — MovieMasher::Job +
    • #name — MovieMasher::Source +
    • #name — MovieMasher::Callback
    • #name — MovieMasher::Output -
    • #name — MovieMasher::Source +
    • #name= — MovieMasher::Output
    • #name= — MovieMasher::Source
    • #name= — MovieMasher::Callback -
    • #name= — MovieMasher::Output -
    • #no_audio — MovieMasher::Output
    • #no_audio — MovieMasher::Input -
    • #no_audio= — MovieMasher::Input -
    • #no_audio= — MovieMasher::Output +
    • #no_audio= — MovieMasher::Input +
    • #no_video — MovieMasher::Input
    • #no_video= — MovieMasher::Input @@ -659,14 +668,14 @@

      Methods

    • #pass= — MovieMasher::Transfer -
    • #path — MovieMasher::Transfer -
    • #path — MovieMasher::Output -
    • #path= — MovieMasher::Output +
    • #path — MovieMasher::Transfer
    • #path= — MovieMasher::Transfer +
    • #path= — MovieMasher::Output +
    • #port — MovieMasher::Transfer
    • #port= — MovieMasher::Transfer @@ -687,10 +696,10 @@

      Methods

    • #quality= — MovieMasher::Output -
    • #range — MovieMasher::Layer -
    • #range — MovieMasher::LayerColor +
    • #range — MovieMasher::Layer +
    • #rate — MovieMasher::TimeRange
    • #rate= — MovieMasher::TimeRange @@ -707,10 +716,10 @@

      Methods

    • #source= — MovieMasher::Input -
    • #start — MovieMasher::TimeRange -
    • #start — MovieMasher::Input +
    • #start — MovieMasher::TimeRange +
    • #start= — MovieMasher::Input
    • #start= — MovieMasher::TimeRange @@ -721,9 +730,9 @@

      Methods

    • #synchronize — MovieMasher::TimeRange -
    • #to_hash — MovieMasher::JobHash +
    • #to_hash — MovieMasher::Hashable -
    • #to_json — MovieMasher::JobHash +
    • #to_json — MovieMasher::Hashable
    • #to_s — MovieMasher::Error::Runtime @@ -731,26 +740,28 @@

      Methods

    • #trigger= — MovieMasher::Callback -
    • #trim_command — MovieMasher::Layer -
    • #trim_command — MovieMasher::LayerColor -
    • #type — MovieMasher::Input +
    • #trim_command — MovieMasher::Layer
    • #type — MovieMasher::Transfer +
    • #type — MovieMasher::Input +
    • #type — MovieMasher::Output -
    • #type= — MovieMasher::Output +
    • #type= — MovieMasher::Transfer
    • #type= — MovieMasher::Input -
    • #type= — MovieMasher::Transfer +
    • #type= — MovieMasher::Output
    • #user — MovieMasher::Transfer
    • #user= — MovieMasher::Transfer +
    • #values — MovieMasher::Hashable +
    • #video — MovieMasher::Mash
    • #video_bitrate — MovieMasher::Output diff --git a/lib/constants/av.rb b/lib/constant/av.rb similarity index 100% rename from lib/constants/av.rb rename to lib/constant/av.rb diff --git a/lib/constant/configuration.rb b/lib/constant/configuration.rb new file mode 100644 index 0000000..fd44212 --- /dev/null +++ b/lib/constant/configuration.rb @@ -0,0 +1,167 @@ +require 'optparse' +require 'optparse/time' +require 'ostruct' +require_relative '../util/hashable' + +module MovieMasher +# Supported configuration keys: +# +# aws_access_key_id - Key identifier for transfers to and from S3. +# aws_secret_access_key - Key secret for transfers to and from S3. +# chmod_directory_new - Octal value indicating the permissions applied to any created directories. +# download_bytes - How large of a download cache to maintain. If a number, bytes is assumed. K, M or G at end signifies kilobytes, megabytes, or gigabytes. +# download_directory - Path to the directory used to cache media inputs. If empty, render_directory is used. +# error_directory - Path to the directory that problematic jobs are placed for debugging. If empty, such jobs are deleted or not based on render_save. +# log_directory - Path to directory where logs are placed. +# process_seconds - How long to look for queued jobs, in seconds. If zero, do not process. If -1, process one job. If -2 process until jobs done. If -3, process forever. +# queue_directory - Path to directory where job files might be. +# queue_url - SQS queue endpoint where job messages might be. +# queue_wait_seconds - How long to wait for SQS messages. +# render_directory - Path to directory where jobs are built. +# render_save - Boolean indicating whether or not jobs should be removed after processing. +# verbose - How much detail to include in logs. One of debug, info, warn or error. + class Configuration + include Hashable + + Descriptions = { + :aws_access_key_id => 'Key identifier for transfers to and from S3.', + :aws_secret_access_key => 'Key secret for transfers to and from S3.', + :chmod_directory_new => 'Octal value indicating the permissions applied to any created directories.', + :download_bytes => 'How large of a download cache to maintain. If a number, bytes is assumed. K, M or G at end signifies kilobytes, megabytes, or gigabytes.', + :download_directory => 'Path to the directory used to cache media inputs. If empty, render_directory is used.', + :error_directory => 'Path to the directory that problematic jobs are placed for debugging. If empty, such jobs are deleted or not based on render_save.', + :log_directory => 'Path to directory where logs are placed.', + :process_seconds => 'How long to look for queued jobs, in seconds. If zero, do not process. If -1, process one job. If -2 process until jobs done. If -3, process forever.', + :queue_directory => 'Path to directory where job files might be.', + :queue_url => 'SQS queue endpoint where job messages might be.', + :queue_wait_seconds => 'How long to wait for SQS messages.', + :render_directory => 'Path to directory where jobs are built.', + :render_save => 'Boolean indicating whether or not jobs should be removed after processing.', + :verbose => 'How much detail to include in logs. One of debug, info, warn or error.', + } + Inputs = { + :download_bytes => 'num', + :render_save => 'bool', + :chmod_directory_new => 'mode', + } + Defaults = { + :chmod_directory_new => '0775', + :download_directory => '', + :download_bytes => '0M', + :error_directory => '', + :queue_url => '', + :log_directory => '/var/log/moviemasher', + :verbose => 'info', + :process_seconds => 55, + :queue_directory => '/tmp/moviemasher/queue', + :queue_wait_seconds => 2, + :render_directory => '/tmp/moviemasher/temporary', + :render_save => false, + } + Switches = { + :verbose => 'v', + :aws_secret_access_key => 'k', + :aws_access_key_id => 'i', + :download_directory => 'd', + :chmod_directory_new => 'm', + } + + def self.init_switches + Descriptions.keys.sort.each do |key| + next unless Switches[key].nil? + key_s = key.to_s + chars = key_s.split('_').map{|w|w[0]} + ('a'..'z').to_a + char = nil + while not chars.empty? + char = chars.shift + break unless Switches.values.include? char + char = nil + end + Switches[key] = char if char + end + end + init_switches + def self.parse(args = [], hash = nil, command = nil) # command is hint for --help + # The options specified on the command line will be collected in *options*. + # We set default values here. + options = Hash.new + config = new hash + config.keys.each do |key| + options[key] = config[key] + end + opt_parser = OptionParser.new do |opts| + opts.banner = "Usage: moviemasher.rb [OPTIONS] [JOB]" + #opts.summary = "Overrides options specified in config/config.yml and/or executes a job." + opts.separator "" + opts.separator "Options:" + config.keys.each do |key| + input = config.input(key).upcase + short = "-#{config.switch key}#{input}" + long = "--#{key}=#{input}" + opts.on(short, long, config.describe(key)) do |opt| + puts "#{key} = #{opt}" + options[key] = opt + end + end + + # No argument, shows at tail. This will print an options summary. + opts.on("-h", "--help", "Display this message and exit.") do + return opts.to_s + end + opts.separator "" + opts.separator "Job: Path to a job file or JSON formatted job string." + end + opt_parser.parse!(args) + options + end + + def initialize hash = nil + hash = Hash.new unless hash + sym_hash = Hash.new + hash.each do |key,v| + key = key.to_sym unless key.is_a? Symbol + sym_hash[key] = v + end + super Defaults.merge sym_hash + end + def switch key + key = key.to_sym unless key.is_a? Symbol + Switches[key] + end + def describe_value value = nil + description = '(empty)' + if value + if value.is_a? String + description = value unless value.empty? + else + description = value.inspect + end + end + description + end + def input key + + key_s = key.to_s + last_bit = key_s.split('_').last + case last_bit + when 'directory' + 'dir' + when 'seconds' + 'secs' + else + + Inputs[key] || (Descriptions[key].is_a?(String) ? last_bit : 'num') + end + end + def describe key + key = key.to_sym unless key.is_a? Symbol + value = @hash[key] + description = "#{Descriptions[key]}" + description += " Default value of #{describe_value Defaults[key]}" + description += " overridden by #{describe_value value}" if value and value != Defaults[key] + description += '.' + description + end + + end +end diff --git a/lib/constants/defaults.rb b/lib/constant/defaults.rb similarity index 93% rename from lib/constants/defaults.rb rename to lib/constant/defaults.rb index f60e57c..434de65 100644 --- a/lib/constants/defaults.rb +++ b/lib/constant/defaults.rb @@ -21,7 +21,7 @@ def self.__font_default config[:source] = Hash.new config[:source][:method] = Method::Symlink config[:source][:type] = Transfer::TypeFile - config[:cached_file] = "#{__dir__}/../../config/font/theleagueof-blackout/webfonts/blackout_two_am-webfont.ttf" + config[:cached_file] = "#{File.dirname(__FILE__)}/../../config/font/theleagueof-blackout/webfonts/blackout_two_am-webfont.ttf" config[:family] = "Blackout Two AM" config end diff --git a/lib/constants/error.rb b/lib/constant/error.rb similarity index 100% rename from lib/constants/error.rb rename to lib/constant/error.rb diff --git a/lib/constants/fill.rb b/lib/constant/fill.rb similarity index 100% rename from lib/constants/fill.rb rename to lib/constant/fill.rb diff --git a/lib/constants/gain.rb b/lib/constant/gain.rb similarity index 100% rename from lib/constants/gain.rb rename to lib/constant/gain.rb diff --git a/lib/constants/info.rb b/lib/constant/info.rb similarity index 100% rename from lib/constants/info.rb rename to lib/constant/info.rb diff --git a/lib/constants/intermediate.rb b/lib/constant/intermediate.rb similarity index 100% rename from lib/constants/intermediate.rb rename to lib/constant/intermediate.rb diff --git a/lib/constants/method.rb b/lib/constant/method.rb similarity index 100% rename from lib/constants/method.rb rename to lib/constant/method.rb diff --git a/lib/input.rb b/lib/input.rb index a7ae31c..e4debf8 100644 --- a/lib/input.rb +++ b/lib/input.rb @@ -29,7 +29,7 @@ module MovieMasher # } # class Input - include JobHash + include Hashable TypeAudio = 'audio' TypeImage = 'image' TypeMash = 'mash' diff --git a/lib/job.rb b/lib/job.rb index 4561ac8..233b25a 100644 --- a/lib/job.rb +++ b/lib/job.rb @@ -16,7 +16,51 @@ module MovieMasher # job.progress # # => {:rendering=>1, :uploading=>1, :downloading=>1, :downloaded=>1, :rendered=>1, :uploaded=>1} class Job - include JobHash + include Hashable + def self.resolved_hash hash_or_path + data = Hash.new + if hash_or_path.is_a? String + hash_or_path = resolved_string hash_or_path + if hash_or_path + begin + case string_type hash_or_path + when 'yaml' + data = YAML::load hash_or_path + when 'json' + data = JSON.parse hash_or_path + else + data[:error] = "unsupported configuration file type #{hash_or_path}" + end + rescue Exception => e + data[:error] = "job file could not be parsed: #{e.message}" + end + else + data[:error] = "job file could not be found: #{hash_or_path}" + end + else + data = Marshal.load(Marshal.dump(hash_or_path)) if hash_or_path.is_a? Hash + end + __hash_keys_to_symbols! data + data + end + def self.resolved_string hash_or_path + case string_type hash_or_path + when 'json', 'yaml' + hash_or_path + else + (File.exists? hash_or_path ? File.read(hash_or_path) : nil) + end + end + def self.string_type hash_or_path + case hash_or_path[0] + when '{', '[' + 'json' + when '-' + 'yaml' + else + nil + end + end private def self.__audio_from_file path raise Error::Parameter.new "__audio_from_file with invalid path" unless path and (not path.empty?) and File.exists? path @@ -61,31 +105,7 @@ def self.__evaluated_path_for_transfer transfer, scope, output key = Path.concat key, file_name Evaluate.value key, scope end - def self.__hash_from_path hash_or_path - data = Hash.new - if hash_or_path.is_a? String - if File.exists? hash_or_path - begin - case File.extname hash_or_path - when '.yml' - data = YAML::load(File.open(hash_or_path)) - when '.json' - data = JSON.parse(File.read(hash_or_path)) - else - data[:error] = "unsupported configuration file type #{hash_or_path}" - end - rescue Exception => e - data[:error] = "job file could not be parsed: #{e.message}" - end - else - data[:error] = "job file could not be found: #{hash_or_path}" - end - else - data = Marshal.load(Marshal.dump(hash_or_path)) if hash_or_path.is_a? Hash - end - __hash_keys_to_symbols! data - data - end + def self.__file_info type, ffmpeg_output result = nil if ffmpeg_output and not ffmpeg_output.empty? @@ -634,12 +654,13 @@ def initialize hash_or_path, configuration = nil @audio_graphs = nil @video_graphs = nil @configuration = configuration || Hash.new - super Job.__hash_from_path hash_or_path + super Job.resolved_hash hash_or_path @outputs_desire = Job.__init_hash @hash path_job = __path_job __file_safe path_job # write massaged job json to job directory - File.write(Path.concat(path_job, 'job.json'), @hash.to_json) + path_job = Path.concat(path_job, 'job.json') + File.open(path_job, 'w') { |f| f << @hash.to_json } # if we encountered a parsing error, log it log_entry(:error) { @hash[:error] } if @hash[:error] end @@ -661,7 +682,7 @@ def log_entry type, &proc if logger_job and logger_job.send (type.id2name + '?').to_sym logger_job.send(type, &proc) end - puts proc.call if 'debug' == @configuration[:log_level] + puts proc.call if 'debug' == @configuration[:verbose] end # Array - One or more Output objects. def outputs; _get __method__; end @@ -789,6 +810,7 @@ def __audio_graphs @audio_graphs end def __cache_input input, input_url, base_src = nil, module_src = nil + cache_url_path = nil if input_url then cache_url_path = __cache_url_path input_url unless File.exists? cache_url_path then @@ -833,6 +855,7 @@ def __cache_input input, input_url, base_src = nil, module_src = nil end progress[:downloaded] += 1 __callback :progress + cache_url_path end def __cache_job_mash input mash = input[:source] @@ -878,7 +901,6 @@ def __cache_input_source input, source, input_url, out_file end end mime_type = response['content-type'] - #puts "MIME: #{mime_type}" __set_info(out_file, 'Content-Type', mime_type) if mime_type else log_entry(:warn) {"got #{response.code} response code from #{input_url}"} @@ -890,13 +912,12 @@ def __cache_input_source input, source, input_url, out_file bucket_key = Job.__path_for_transfer source object = bucket.objects[bucket_key] if @configuration[:s3_read_at_once] then - #puts "reading from S3 #{bucket_key}" object_read_data = object.read - File.open(out_file, 'wb') { |file| file.write(object_read_data) } if object_read_data + File.open(out_file, 'wb') { |f| f << object_read_data } if object_read_data else File.open(out_file, 'wb') do |file| object.read do |chunk| - file.write(chunk) + file << chunk end end end @@ -1018,6 +1039,7 @@ def __execute options @hash[:commands] << whole_cmd log_entry(:debug) { whole_cmd } result = Open3.capture3(whole_cmd).join "\n" + #Process.waitall if outputs_file and not out_file.include?('%') then unless File.exists?(out_file) and File.size?(out_file) log_entry(:debug) { result } @@ -1036,6 +1058,7 @@ def __execute options end end log_entry(:debug) { result } + #puts `ps aux | awk '{ print $8 " " $2 }' | grep -w Z` result end def __execute_output_command output, cmd_hash @@ -1045,7 +1068,7 @@ def __execute_output_command output, cmd_hash content = cmd_hash[:content] if content __file_safe File.dirname(out_path) - File.write(out_path, content) + File.open(out_path, 'w') { |f| f << content} else unless File.exists? out_path then cmd = cmd_hash[:command] @@ -1084,8 +1107,8 @@ def __file_mime path type = MIME::Types.of(path).first if type mime = type.simplified - else - mime = Rack::Mime.mime_type(File.extname(path)) + #else + # mime = Rack::Mime.mime_type(File.extname(path)) end #puts "LOOKING UP MIME: #{ext} #{mime}" __set_info(path, 'Content-Type', mime) if mime @@ -1094,7 +1117,11 @@ def __file_mime path end def __file_safe path options = Hash.new - options[:mode] = @configuration[:chmod_directory_new] if @configuration[:chmod_directory_new] + mod = @configuration[:chmod_directory_new] + if mod + mod = mod.to_i(8) if mod.is_a? String + options[:mode] = mod + end FileUtils.makedirs path, options end def __file_type path @@ -1176,7 +1203,7 @@ def __logger __file_safe log_dir @logger = Logger.new(Path.concat log_dir, 'log.txt') log_level = @hash[:log_level] - log_level = @configuration[:log_level] unless log_level and not log_level.empty? + log_level = @configuration[:verbose] unless log_level and not log_level.empty? log_level = 'info' unless log_level and not log_level.empty? log_level = log_level.upcase log_level = (Logger.const_defined?(log_level) ? Logger.const_get(log_level) : Logger::INFO) @@ -1468,8 +1495,9 @@ def __render_path output end def __s3 source unless source[:s3] - require 'aws-sdk' unless defined? AWS - source[:s3] = ((source[:region] and not source[:region].empty?) ? AWS::S3.new(:region => source[:region]) : AWS::S3.new) + #require 'aws-sdk' unless defined? AWS + region = ((source[:region] and not source[:region].empty?) ? source[:region] : nil) + source[:s3] = (region ? AWS::S3.new(:region => region) : AWS::S3.new) end source[:s3] end @@ -1479,7 +1507,7 @@ def __s3_bucket source def __scope object = nil scope = Hash.new scope[:job] = self - scope[object.class_symbol] = object if object and object.is_a? JobHash + scope[object.class_symbol] = object if object and object.is_a? Hashable scope end def __set_info(path, type, data) diff --git a/lib/mash.rb b/lib/mash.rb index a02d4e3..9b76131 100644 --- a/lib/mash.rb +++ b/lib/mash.rb @@ -3,7 +3,7 @@ module MovieMasher # # class Mash - include JobHash + include Hashable Audio = 'audio' Effect = 'effect' Font = 'font' diff --git a/lib/moviemasher.rb b/lib/moviemasher.rb index 66049ea..2bd79d4 100644 --- a/lib/moviemasher.rb +++ b/lib/moviemasher.rb @@ -1,19 +1,19 @@ + +require 'cgi' require 'digest/sha2' require 'fileutils' -require 'cgi' +require 'json' require 'logger' require 'mime/types' require 'net/http' require 'net/http/post/multipart' require 'open3' -require 'rack' require 'require_all' require 'uri' require 'uuid' require 'yaml' -require 'json' -require_all __dir__ +require_rel '.' # Handles global configuration and high level processing of Job objects. The # ::process_queues method will look for jobs in a directory and optionally an @@ -25,19 +25,7 @@ # MovieMasher.process './job.json' # # => # module MovieMasher - @@configuration = { - :download_directory => '', # defaults to render_directory - :download_directory_size => '0M', # K = kilobytes, M = megabytes, G = gigabytes, otherwise bytes - :chmod_directory_new => 0775, - :error_directory => '', - :render_keep => false, - :log_directory => '/var/log/moviemasher', - :log_level => 'info', - :process_queues_seconds => 55, - :queue_directory => '/tmp/moviemasher/queue', - :queue_wait_time_seconds => 2, - :render_directory => '/tmp/moviemasher/temporary', - } + @@configuration = Configuration::Defaults.dup @@job = nil @@logger = nil @@queue = nil @@ -49,23 +37,7 @@ def self.configuration end # hash_or_path - Set one or more configuration options. If supplied a String, # it's assumed to be a path to a JSON or YML file and converted to a Hash. The -# Hash can use a String or Symbol for each key. The following keys are -# supported: -# -# chmod_directory_new - Mode to use when creating directories, default: 0775 -# log_directory - Where to put log file, default: /var/log/moviemasher -# log_level - Logger output level (debug, info, warn, error), default: info -# download_directory - Where to downloaded files, default: *render_directory* -# download_directory_size - Integer/String target cache size, default: 0M -# render_directory - Where to build files, default: /tmp/moviemasher/temporary -# queue_directory - Where to look for job files, default: /tmp/moviemasher/queue -# process_queues_seconds - How long to watch queues for jobs, default: 55 -# aws_OPTIONS - passed to the AWS.config method if specified, default: empty -# queue_url - SQS queue endpoint to poll for jobs, default: empty -# queue_wait_time_seconds - How long to wait for SQS messages, default: 2 -# APP_path - Path to du, ecasound, ffmpeg, ffprobe, sox, wav2png, default: APP -# error_directory - Where to put failed job directories, default: empty -# render_keep - If false build files are removed, default: false +# Hash can use a String or Symbol for each key. See Config for supported keys. # # Returns nothing. # @@ -119,17 +91,24 @@ def self.configure hash_or_path AWS.config(aws_config) unless aws_config.empty? end end +# Returns valediction for command line apps. + def self.goodbye + "#{Time.now} #{self.name} done" + end +# Returns salutation for command line apps. + def self.hello + "#{Time.now} #{self.name} version #{VERSION}" + end # object_or_path - Job object or String/Hash to be passed to Job.new along # with ::configuration. After the MovieMasher::Job#process method is called, its render # directory is either moved to *error_directory* (if that option is not empty # and a problem arose during processing) or deleted (unless -# *render_keep* is true). The *download_directory* will also be pruned -# to assure its size is not greater than *download_directory_size*. +# *render_save* is true). The *download_directory* will also be pruned +# to assure its size is not greater than *download_bytes*. # # Returns Job object with *error* key set if problem arose. # Raises Error::Configuration if *render_directory* is empty. def self.process object_or_path - __log_transcoder(:debug) { "process called #{object_or_path}" } result = @@job = (object_or_path.is_a?(Job) ? object_or_path : Job.new(object_or_path, configuration)) begin # try to process job @@job.process unless @@job[:error] @@ -142,7 +121,7 @@ def self.process object_or_path if @@job[:error] and configuration[:error_directory] and not configuration[:error_directory].empty? then FileUtils.mv job_directory, configuration[:error_directory] else - FileUtils.rm_r job_directory unless configuration[:render_keep] + FileUtils.rm_r job_directory unless configuration[:render_save] end end rescue Exception => e @@ -153,13 +132,20 @@ def self.process object_or_path begin # try to flush the download directory directory = @@configuration[:download_directory] directory = @@configuration[:render_directory] unless directory and not directory.empty? - __flush_downloads directory, configuration[:download_directory_size] + __flush_downloads directory, configuration[:download_bytes] rescue Exception => e __log_exception e end result # what was @@job end -# Loops for *process_queues_seconds* searching for the oldest JSON or YML +# Calls process for each item in array + def self.process_jobs array # of job strings or paths + array.each do |job_str| + process job_str + end + (array.empty? ? nil : array.length) + end +# Loops for *process_seconds* searching for the oldest JSON or YML # formatted job file in *queue_directory*, as well as polling *queue_url* for an # SQS message. If the later is found its body is expected to be a JSON formatted # job and its identifier is used to populate the *id* key (if that's empty), as @@ -176,29 +162,38 @@ def self.process object_or_path # Returns nothing. # # Raises Error::Configuration if *queue_directory* or *render_directory* is empty. - def self.process_queues + def self.process_queues process_seconds = nil + process_seconds = configuration[:process_seconds] unless process_seconds + process_seconds = process_seconds.to_i raise Error::Configuration.new "queue_directory not found in configuration" unless configuration[:queue_directory] and not configuration[:queue_directory].empty? - run_seconds = configuration[:process_queues_seconds] start = Time.now - oldest_file = nil - working_file = "#{configuration[:queue_directory]}working.json" - while run_seconds > (Time.now - start) - if File.exists? working_file - # if this process didn't create it, we must have crashed on it in a previous run - __log_transcoder(:error) { "deleting previously active job:\n#{File.read working_file}" } unless oldest_file - File.delete working_file - end - oldest_file = Dir["#{configuration[:queue_directory]}*.json"].sort_by{ |f| File.mtime(f) }.first - if oldest_file then - __log_transcoder(:info) { "started #{oldest_file}" } - File.rename oldest_file, working_file + Dir[Path.concat configuration[:queue_directory], 'working.*'].each do |working_file| + # if this process didn't create it, we must have crashed on it in a previous run + __log_transcoder(:error) { "deleting previously active job:\n#{File.read working_file}" } + File.delete working_file + end + while (0 > process_seconds) or (process_seconds > (Time.now - start)) + job = Dir[Path.concat configuration[:queue_directory], '*'].sort_by{ |f| File.mtime(f) }.first + if job then + __log_transcoder(:info) { "starting #{job}" } + working_file = "#{File.dirname job}/working#{File.extname job}" + File.rename job, working_file process working_file - __log_transcoder(:info) { "finished #{oldest_file}" } + __log_transcoder(:info) { "finishing #{job}" } File.delete working_file - sleep 1 else # see if one can be copied from the queue - __sqs_request(run_seconds, start) unless configuration[:queue_url].nil? or configuration[:queue_url].empty? + if (0 > process_seconds) or (process_seconds > (Time.now + configuration[:queue_wait_seconds] - start)) + job = __sqs_request unless configuration[:queue_url].nil? or configuration[:queue_url].empty? + if job + __log_transcoder(:info) { "starting #{job[:id]}" } + process job + __log_transcoder(:info) { "finishing #{job[:id]}" } + end + end end + break if -1 == process_seconds + break if -2 == process_seconds and not found + sleep 0.01 end end private @@ -213,7 +208,11 @@ def self.__execute options def self.__file_safe path unless File.directory? path options = Hash.new - options[:mode] = @@configuration[:chmod_directory_new] if @@configuration[:chmod_directory_new] + mod = @@configuration[:chmod_directory_new] + if mod + mod = mod.to_i(8) if mod.is_a? String + options[:mode] = mod + end FileUtils.makedirs path, options end end @@ -289,7 +288,7 @@ def self.__flush_directory_bytes(dir) end def self.__log type, &proc @@job.log_entry(type, &proc) if @@job - __log_transcoder(type, &proc) if 'debug' == configuration[:log_level] + __log_transcoder(type, &proc) if 'debug' == configuration[:verbose] end def self.__logger unless @@logger @@ -297,7 +296,7 @@ def self.__logger if log_dir and not log_dir.empty? __file_safe log_dir @@logger = Logger.new(Path.concat(log_dir, 'moviemasher.rb.log'), 7, 1048576 * 100) - log_level = (@@configuration[:log_level] || 'info').upcase + log_level = (@@configuration[:verbose] || 'info').upcase @@logger.level = (Logger.const_defined?(log_level) ? Logger.const_get(log_level) : Logger::INFO) end end @@ -316,6 +315,9 @@ def self.__log_exception(rescued_exception, is_warning = false) nil # so we can assign in a oneliner end def self.__log_transcoder type, &proc + puts proc.call + #STDOUT.flush + logger = __logger if logger and logger.send((type.id2name + '?').to_sym) logger.send(type, proc.call) @@ -329,26 +331,20 @@ def self.__sqs_queue end @@queue end - def self.__sqs_request run_seconds, start - wait_time = configuration[:queue_wait_time_seconds] || 0 - if run_seconds > (Time.now + wait_time - start) then - message = __sqs_queue.receive_message(:wait_time_seconds => wait_time) - if message then - job = nil - begin - job_data = JSON.parse(message.body) - begin - job_data['id'] = message.id unless job_data['id'] and not job_data['id'].to_s.empty? - File.open("#{configuration[:queue_directory]}#{message.id}.json", 'w') { |file| file.write(job_data.to_json) } - message.delete - rescue Exception => e - __log_exception e - end - rescue Exception => e - __log_exception e - message.delete - end + def self.__sqs_request + job_hash = nil + message = __sqs_queue.receive_message(:wait_time_seconds => configuration[:queue_wait_seconds]) + if message then + message_body = message.body + job_hash = Job.resolved_hash message_body + if job_hash[:error] then + __log_transcoder(:error) { "SQS #{job_hash[:error]}: #{message_body}" } + job_hash = nil + else + job_hash[:id] = message.id unless job_hash[:id] and not job_hash[:id].to_s.empty? end + message.delete end + job_hash end end diff --git a/lib/output.rb b/lib/output.rb index d700c50..b259920 100644 --- a/lib/output.rb +++ b/lib/output.rb @@ -29,7 +29,7 @@ module MovieMasher # } class Output - include JobHash + include Hashable TypeAudio = 'audio' TypeImage = 'image' TypeSequence = 'sequence' diff --git a/lib/transfer.rb b/lib/transfer.rb index 4319948..4fcfd4b 100644 --- a/lib/transfer.rb +++ b/lib/transfer.rb @@ -14,7 +14,7 @@ module MovieMasher # When building file paths, #directory and #path will automatically have slashes # inserted between them as needed so trailing and leading slashes are optional. class Transfer - include JobHash + include Hashable TypeFile = 'file' TypeHttp = 'http' TypeHttps = 'https' diff --git a/lib/utils/eval.rb b/lib/util/eval.rb similarity index 92% rename from lib/utils/eval.rb rename to lib/util/eval.rb index 84411f9..4045c8e 100644 --- a/lib/utils/eval.rb +++ b/lib/util/eval.rb @@ -60,7 +60,7 @@ def self.value v, scope end private def self.__is_eval_object? object - (object.is_a?(Hash) or object.is_a?(Array) or object.is_a?(JobHash)) + (object.is_a?(Hash) or object.is_a?(Array) or object.is_a?(Hashable)) end def self.__scope_target split_bit, scope scope_child = nil diff --git a/lib/utils/filter_helpers.rb b/lib/util/filter_helpers.rb similarity index 100% rename from lib/utils/filter_helpers.rb rename to lib/util/filter_helpers.rb diff --git a/lib/utils/float_util.rb b/lib/util/float_util.rb similarity index 100% rename from lib/utils/float_util.rb rename to lib/util/float_util.rb diff --git a/lib/job_hash.rb b/lib/util/hashable.rb similarity index 88% rename from lib/job_hash.rb rename to lib/util/hashable.rb index 9f76700..99eed80 100644 --- a/lib/job_hash.rb +++ b/lib/util/hashable.rb @@ -1,7 +1,7 @@ module MovieMasher # Mix-in functionality for mocking a Hash. - module JobHash + module Hashable # Convenience getter for underlying data Hash. # # symbol - Symbol key into hash. @@ -29,7 +29,7 @@ def identifier; @identifier; end def initialize hash hash = Hash.new unless hash and hash.is_a? Hash @hash = hash - @identifier = UUID.new.generate + @identifier = UUID.new.generate if defined? UUID end # Return deep copy of underlying Hash. def to_hash @@ -39,6 +39,12 @@ def to_hash def to_json state = nil @hash.to_json state end + def keys + @hash.keys + end + def values + @hash.values + end protected def _set symbol, value self[symbol] = value diff --git a/lib/utils/path.rb b/lib/util/path.rb similarity index 100% rename from lib/utils/path.rb rename to lib/util/path.rb diff --git a/lib/utils/time_range.rb b/lib/util/time_range.rb similarity index 100% rename from lib/utils/time_range.rb rename to lib/util/time_range.rb diff --git a/lib/version.rb b/lib/version.rb new file mode 100755 index 0000000..3ea45e3 --- /dev/null +++ b/lib/version.rb @@ -0,0 +1,3 @@ +module MovieMasher + VERSION = "4.0.8" +end diff --git a/spec/aws_spec.rb b/spec/aws_spec.rb new file mode 100644 index 0000000..e6961f0 --- /dev/null +++ b/spec/aws_spec.rb @@ -0,0 +1,42 @@ + +require_relative 'helpers/clientside_aws' + +describe File.basename(__FILE__) do + before(:all) do + spec_start_redis + @directory = MovieMasher.configuration[:download_directory] + @directory = MovieMasher.configuration[:render_directory] unless @directory and not @directory.empty? + end + after(:all) do + spec_stop_redis + end + context "__cache_input" do + it "correctly saves cached file when source is s3 object" do + job = MovieMasher::Job.send(:__hash_keys_to_symbols!,spec_job_from_files('image_s3')) + input = job[:inputs].first + source = input[:source] + source_frag = MovieMasher::Path.concat source[:path], "#{source[:name]}.#{source[:extension]}" + source_path = "#{File.dirname(__FILE__)}/../spec/#{source_frag}" + job_object = MovieMasher::Job.new job, MovieMasher.configuration + #puts "BUCKET: #{source[:bucket]}" + s3 = job_object.send(:__s3, MovieMasher::Source.new(source)) + s3.buckets.create source[:bucket].to_s + bucket = s3.buckets[source[:bucket]] + path_name = Pathname.new("#{File.dirname(__FILE__)}/../spec/helpers/#{source_frag}") + path_name = File.expand_path path_name + #puts "path_name = #{path_name}" + #puts "source_frag = #{source_frag}" + expect(File.exists? path_name).to be_true + bucket.objects[source_frag].write(Pathname.new(path_name), :content_type => 'image/png') + input_url = MovieMasher::Job.send(:__url_for_input, input) + #puts "INPUT_URL: #{input_url}" + path = job_object.send(:__cache_input, input, input_url) + + expect(path).to eq job_object.send(:__cache_url_path, input_url) + #MovieMasher::Path.concat @directory, "#{url}/cached#{File.extname(source_frag)}" + expect(File.exists? path).to be_true + expect(FileUtils.identical? path, path_name).to be_true + end + + end +end \ No newline at end of file diff --git a/spec_aws/helpers/clientside_aws.rb b/spec/helpers/clientside_aws.rb similarity index 56% rename from spec_aws/helpers/clientside_aws.rb rename to spec/helpers/clientside_aws.rb index 82f0eee..36d395d 100644 --- a/spec_aws/helpers/clientside_aws.rb +++ b/spec/helpers/clientside_aws.rb @@ -1,18 +1,10 @@ +ENV['RACK_ENV'] = 'test' -# redis-server --port 6380 & -# cd /path/to/clientside_aws -# rvm gemset use clientside_aws -# RACK_ENV=test ruby ./index.rb -p 4568 & - -require 'redis' -require 'httparty' -require 'sinatra' - -require_relative '../../../clientside_aws/aws_mock' -require_relative '../../../clientside_aws/clientside_aws/s3' - +require 'bundler/setup' +require 'clientside_aws/mock' +require_relative 'spec_helper' +AWS.config :access_key_id => '...', :secret_access_key => '...' PIDS = Array.new -AWS_REDIS = Redis.new(:host => "localhost", :port => 6380, :driver => :hiredis) def spec_start_redis if PIDS.empty? then @@ -34,8 +26,8 @@ def spec_stop_redis PIDS.each do |pid| Process.kill("KILL", pid) end - Process.waitall PIDS.clear + #Process.waitall end rescue Exception => e puts "spec_stop_redis caught: #{e.message}" diff --git a/spec/helpers/config.yml b/spec/helpers/config.yml index e0f6fd0..fc6adb8 100644 --- a/spec/helpers/config.yml +++ b/spec/helpers/config.yml @@ -1,8 +1,8 @@ download_directory: log/cache -download_directory_size: 2M +download_bytes: 2M error_directory: log/error render_directory: log/temporary -render_keep: true +render_save: true log_directory: log/moviemasher log_level: warn s3_read_at_once: true diff --git a/spec/helpers/media/json/inputs/image_url.json b/spec/helpers/media/json/inputs/image_url.json index ed98253..1654a8c 100644 --- a/spec/helpers/media/json/inputs/image_url.json +++ b/spec/helpers/media/json/inputs/image_url.json @@ -1,5 +1,5 @@ { "type": "image", "id": "image_url", - "url": "http://test.localhost:4568/s3/media/image/small-1x1.png" + "url": "http://localhost:4567/s3/test/media/image/small-1x1.png" } \ No newline at end of file diff --git a/spec/helpers/spec_helper.rb b/spec/helpers/spec_helper.rb index 4d8ccdc..2c8dc2a 100644 --- a/spec/helpers/spec_helper.rb +++ b/spec/helpers/spec_helper.rb @@ -1,27 +1,17 @@ + require 'rspec' +require 'rack' require 'rack/test' include RSpec::Matchers # delete previous log directory !! -FileUtils.rm_rf "#{__dir__}/../../log" if File.directory? "#{__dir__}/../../log" +FileUtils.rm_rf "#{File.dirname(__FILE__)}/../../log" if File.directory? "#{File.dirname(__FILE__)}/../../log" require_relative '../../lib/moviemasher.rb' -MovieMasher.configure "#{__dir__}/config.yml" +MovieMasher.configure "#{File.dirname(__FILE__)}/config.yml" def spec_file dir, name - JSON.parse(File.read("#{__dir__}/media/json/#{dir}/#{name}.json")) -end -def spec_job(input_id, output_id = 'video_h264', destination = 'file_log') - job = spec_job_from_files input_id, output_id, destination - output = job['outputs'][0] - input = job['inputs'][0] - input['base_source'] = spec_file('sources', 'file_spec') - input['base_source']['directory'] = File.dirname __dir__ - destination = job['destination'] - #puts job.inspect - input['source']['directory'] = __dir__ - destination['directory'] = File.dirname(File.dirname __dir__) - job + JSON.parse(File.read("#{File.dirname(__FILE__)}/media/json/#{dir}/#{name}.json")) end def spec_job_from_files(input_id = nil, output_id = nil, destination_id = nil) job = Hash.new @@ -48,11 +38,8 @@ def spec_job_from_files(input_id = nil, output_id = nil, destination_id = nil) referenced.each do |media_id, reference| unless reference[:media] mod_media = spec_modular_media unless mod_media - if mod_media[media_id] - mash['media'] << mod_media[media_id] - else - raise "could not find or create media for #{media_id}" - end + return nil unless mod_media[media_id] + mash['media'] << mod_media[media_id] end end end @@ -63,7 +50,7 @@ def spec_job_from_files(input_id = nil, output_id = nil, destination_id = nil) ModularMedia = Hash.new def spec_modular_media if ModularMedia.empty? - js_dir = "#{__dir__}/../../../angular-moviemasher/app/module" + js_dir = "#{File.dirname(__FILE__)}/../../../angular-moviemasher/app/module" js_dirs = Dir["#{js_dir}/*/*.json"] js_dirs += Dir["#{js_dir}/*/*/*.json"] js_dirs.each do |json_file| @@ -87,7 +74,20 @@ def spec_job_output_path job dest_path end def spec_process_job_files(input_id, output = 'video_h264', destination = 'file_log') - job_data = spec_job input_id, output, destination + job_data = spec_job_from_files input_id, output, destination + unless job_data + puts "SKIPPED #{input_id} - put angular-moviemasher with moviemasher.rb to test modules" + return [] + end + output = job_data['outputs'][0] + input = job_data['inputs'][0] + input['base_source'] = spec_file('sources', 'file_spec') + input['base_source']['directory'] = File.dirname File.dirname(__FILE__) + destination = job_data['destination'] + #puts job_data.inspect + input['source']['directory'] = File.dirname(__FILE__) + destination['directory'] = File.dirname(File.dirname File.dirname(__FILE__)) + job = MovieMasher::Job.new job_data, MovieMasher.configuration output = job.outputs.first input = job.inputs.first diff --git a/spec_aws/README.txt b/spec_aws/README.txt deleted file mode 100644 index 9f41a34..0000000 --- a/spec_aws/README.txt +++ /dev/null @@ -1,8 +0,0 @@ - -To run these tests: - -* install https://github.com/perrystreetsoftware/clientside_aws in the - same directory as moviemasher.rb is installed -* follow instructions in its README -* uncomment last section in /Gemfile -* run bundle install to install required gems diff --git a/spec_aws/aws_spec.rb b/spec_aws/aws_spec.rb deleted file mode 100644 index 7c41fb7..0000000 --- a/spec_aws/aws_spec.rb +++ /dev/null @@ -1,49 +0,0 @@ - -require_relative '../spec/helpers/spec_helper' -require_relative 'helpers/clientside_aws' - -describe File.basename(__FILE__) do - before(:all) do - spec_start_redis - @directory = @configuration[:download_directory] - @directory = @configuration[:render_directory] unless @directory and not @directory.empty? - - end - after(:all) do - spec_stop_redis - end - context "__cache_input" do - it "correctly saves cached file when source is s3 object" do - job = MovieMasher::Job.send(:__hash_keys_to_symbols!,spec_job_from_files 'image_s3') - input = job[:inputs].first - source = input[:source] - source_frag = MovieMasher::Path.concat source[:path], "#{source[:name]}.#{source[:extension]}" - source_path = "#{__dir__}/../spec/#{source_frag}" - s3 = MovieMasher.send :__s3, source - s3.buckets.create source[:bucket] - bucket = s3.buckets[source[:bucket]] - path_name = Pathname.new("#{__dir__}/../spec/helpers/#{source_frag}") - path_name = File.expand_path path_name - #puts "path_name = #{path_name}" - expect(File.exists? path_name).to be_true - bucket.objects[source_frag].write(path_name, :content_type => 'image/jpeg') - path = MovieMasher.send :__cache_input, (input, MovieMasher.send :__url_for_input, (input)) - url = "#{source[:type]}://#{source[:bucket]}.s3.amazonaws.com/#{source_frag}" - url = Digest::SHA2.new(256).hexdigest url - expect(path).to eq MovieMasher::Path.concat @directory, "#{url}/cached#{File.extname(source_frag)}" - expect(File.exists? path).to be_true - expect(FileUtils.identical? path, path_name).to be_true - end - it "correctly saves cached file when source is url" do - # grab the file we saved to s3 via http - job = MovieMasher::Job.send(:__hash_keys_to_symbols!,spec_job_from_files 'image_url') - input = job[:inputs].first - input = MovieMasher::Job.send :__init_input, input - source = input[:source] - path = MovieMasher.send :__cache_input, (input, MovieMasher.send :__url_for_input, (input)) - url = Digest::SHA2.new(256).hexdigest source - expect(path).to eq MovieMasher::Path.concat @directory, "#{url}/cached#{File.extname(source)}" - expect(File.exists? path).to be_true - end - end -end \ No newline at end of file