framey 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +56 -0
- data/app/controllers/framey/videos_controller.rb +42 -0
- data/app/helpers/application_helper.rb +2 -0
- data/app/helpers/framey/videos_helper.rb +95 -0
- data/app/models/framey/video.rb +5 -0
- data/app/views/framey/videos/index.html.erb +34 -0
- data/app/views/framey/videos/new.html.erb +4 -0
- data/app/views/framey/videos/show.html.erb +29 -0
- data/app/views/layouts/framey.html.erb +21 -0
- data/config/routes.rb +15 -0
- data/lib/acts_as_video/base.rb +28 -0
- data/lib/{framey/api.rb → api.rb} +3 -16
- data/lib/application_controller.rb +12 -0
- data/lib/application_helper.rb +3 -0
- data/lib/engine.rb +30 -0
- data/lib/framey.rb +7 -8
- data/lib/rails/generators/framey/framey_generator.rb +87 -0
- data/lib/rails/generators/framey/templates/initializer.rb +14 -0
- data/lib/rails/generators/framey/templates/migration.rb +9 -0
- data/lib/rails/generators/framey/templates/schema.rb +19 -0
- data/lib/rails/railties/tasks.rake +8 -0
- data/lib/{framey/view_helpers.rb → view_helpers.rb} +4 -4
- data/public/images/cheese.jpg +0 -0
- data/public/javascripts/swfobject.js +4 -0
- data/public/player.swf +0 -0
- data/public/recorder.swf +0 -0
- data/public/stylesheets/framey.css +59 -0
- metadata +79 -78
- data/.gemtest +0 -0
- data/Manifest.txt +0 -7
- data/README.md +0 -127
- data/Rakefile +0 -19
- data/lib/framey/configuration.rb +0 -43
- data/test/test_framey.rb +0 -8
data/README.rdoc
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
== Overview
|
2
|
+
|
3
|
+
One of the things I was most looking forward to in rails 3 was the plugin / engine architecture. Recently, I sat down to figure out how to create my first engine and package it up as a gem and it took me awhile of time just to get the structure of the engine setup. It's missing a lot of the "rails" you get in a normal rails app.
|
4
|
+
|
5
|
+
In it's simplest form engines are quite easy, however for a full-featured engine (such as creating a forum) there are a lot of extras that you're going to want. These are the things I spent time figuring out that I've packaged up into an easy starting point:
|
6
|
+
|
7
|
+
* Namespacing models & controllers so they don't collide with those in the main app
|
8
|
+
* Creating a global layout within your engine that gets nested within your application layout
|
9
|
+
* Generating migrations from your engine
|
10
|
+
* Creating an "acts_as_[plugin]" declaration for use inside your main app's models
|
11
|
+
* Easy plugin configuration file editable from main app directory
|
12
|
+
* Rake tasks within engine
|
13
|
+
* Writing tests for models complete with fixtures
|
14
|
+
* Serving static assets within engine
|
15
|
+
* Packaging and distributing as a gem
|
16
|
+
* Code is here - I've created an engine stub that has all the things setup for you already. I want to see a lot more rails 3 engines get created, I hope this helps! I'd love to hear feedback from you if you try it out.
|
17
|
+
|
18
|
+
Here’s how you get ready to create your first gem by using this starting point:
|
19
|
+
|
20
|
+
* git clone http://github.com/krschacht/rails_3_engine_demo.git
|
21
|
+
* cd rails_3_engine_demo
|
22
|
+
* [edit test/database.yml]
|
23
|
+
* rake test (this will initialize your test database and run the basic test suite)
|
24
|
+
|
25
|
+
Now, create a plain rails app and set it up to use your engine. FYI: even though the engine's directory is 'rails_3_engine_demo', internally the engine is named 'cheese'
|
26
|
+
|
27
|
+
* cd .. [ this is to take you outside the 'rails_3_engine_demo' directory that was created above' ]
|
28
|
+
* rails new demo_app_to_use_gem -d mysql
|
29
|
+
* cd demo_app_to_use_gem
|
30
|
+
* [edit config/database.yml]
|
31
|
+
* [edit Gemfile, add line: ] gem ‘cheese’, :path => "../rails_3_engine_demo"
|
32
|
+
* rails generate cheese
|
33
|
+
* [examine config/initializers/cheese.rb to see basic config parameters]
|
34
|
+
* rake db:create
|
35
|
+
* rake db:migrate (one of the migrations that you'll see run came from the engine)
|
36
|
+
|
37
|
+
You have now setup a empty rails app that utilizes your engine. To test out the functionality, startup the demo app’s webserver:
|
38
|
+
|
39
|
+
* rails server
|
40
|
+
* Then visit: http://localhost:3000/cheese (this is a controller included within the engine)
|
41
|
+
* Watch the server logs as you're viewing this page and you'll see some output which is coming from an application before_filter which is executing from inside the engine (in lib/application_controller.rb)
|
42
|
+
* rake cheese:report (this is a a rake task that is included inside the engine)
|
43
|
+
|
44
|
+
Lastly, let's package up your engine as a real gem. You’ll need Jeweler installed for this:
|
45
|
+
|
46
|
+
* cd rails_3_engine_demo
|
47
|
+
* sudo gem install jeweler
|
48
|
+
* rake gemspec
|
49
|
+
* rake build
|
50
|
+
* rake install (you have now installed your engine as a gem locally)
|
51
|
+
* [ At this point if you wanted your demo app to use your installed gem, edit the Gemfile in your demo app and remove the 'path' option from your gem line. It should look like this: ] gem ‘cheese’
|
52
|
+
* rake gemcutter:release (this pushes your gem up to Gemcutter, a public gem repository)
|
53
|
+
|
54
|
+
Now you’re ready to start customizing this engine for your own purposes. Do a global find in your engine directory and replace every instance of "cheese" and "Cheese" with your engine name (be sure to preserve capitalization). Likewise, rename every directory and file that’s named "cheese" with your engine name. I should really automate this but I haven’t figured out how to create a rake task that I can run from within the engine directory itself.
|
55
|
+
|
56
|
+
P.S. Special thanks to Chrispy for helping figure out the application_controller includes!
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Framey
|
2
|
+
class VideosController < ApplicationController
|
3
|
+
|
4
|
+
unloadable
|
5
|
+
|
6
|
+
layout 'framey' # this allows you to have a gem-wide layout
|
7
|
+
|
8
|
+
def new
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
# framey callback
|
13
|
+
def callback
|
14
|
+
render :text => "" and return unless request.post? && params[:video]
|
15
|
+
|
16
|
+
video = Video.create!({
|
17
|
+
:name => params[:video][:name],
|
18
|
+
:filesize => params[:video][:filesize],
|
19
|
+
:duration => params[:video][:duration],
|
20
|
+
:state => params[:video][:state],
|
21
|
+
:views => params[:video][:views],
|
22
|
+
:flv_url => params[:video][:flv_url],
|
23
|
+
:mp4_url => params[:video][:mp4_url],
|
24
|
+
:small_thumbnail_url => params[:video][:small_thumbnail_url],
|
25
|
+
:medium_thumbnail_url => params[:video][:medium_thumbnail_url],
|
26
|
+
:large_thumbnail_url => params[:video][:large_thumbnail_url]
|
27
|
+
})
|
28
|
+
|
29
|
+
render :text => "" and return
|
30
|
+
end
|
31
|
+
|
32
|
+
def index
|
33
|
+
@videos = Framey::Video.paginate(:page => params[:page], :per_page => 10).order('created_at DESC')
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def show
|
38
|
+
@video = Framey::Video.find_by_name(params[:id])
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Framey
|
2
|
+
module VideosHelper
|
3
|
+
# This method renders the Framey video recorder from within an ActionView in your Rails app.
|
4
|
+
#
|
5
|
+
# Example Usage (assuming ERB):
|
6
|
+
# <%= javascript_include_tag "swfobject" %>
|
7
|
+
# <%= render_recorder({
|
8
|
+
# :id => "[some id]" # the id of the flash embed object (optional, random by default)
|
9
|
+
# :max_time => 60, # maximum allowed video length in seconds (optional, defaults to 30)
|
10
|
+
# :session_data => { # custom parameters to be passed along to your app later (optional)
|
11
|
+
# :user_id => <%= @user.id %> # you may, for example, want to relate this recording to a specific user in your system
|
12
|
+
# }
|
13
|
+
# }) %>
|
14
|
+
def render_recorder(opts={})
|
15
|
+
api_key = Framey::API_KEY
|
16
|
+
timestamp, signature = Framey::Api.sign
|
17
|
+
session_data = (opts[:session_data]||{}).map { |k,v| "#{k.to_s}=#{v.to_s}" }.join(",")
|
18
|
+
run_env = Framey::RUN_ENV
|
19
|
+
max_time = opts[:max_time] || 30
|
20
|
+
divid = "frameyRecorderContainer_#{(rand*999999999).to_i}"
|
21
|
+
objid = opts[:id] || "the#{divid}"
|
22
|
+
|
23
|
+
raw <<END_RECORDER
|
24
|
+
<div id="#{divid}"></div>
|
25
|
+
<script type="text/javascript">
|
26
|
+
var flashvars = {
|
27
|
+
api_key: "#{api_key}",
|
28
|
+
signature: "#{signature}",
|
29
|
+
time_stamp: "#{timestamp}",
|
30
|
+
session_data: "#{session_data}",
|
31
|
+
run_env: "#{run_env}",
|
32
|
+
max_time: "#{max_time.to_s}"
|
33
|
+
};
|
34
|
+
var params = {
|
35
|
+
'allowscriptaccess': 'always',
|
36
|
+
"wmode": "transparent"
|
37
|
+
};
|
38
|
+
var attributes = {
|
39
|
+
'id': "#{objid}",
|
40
|
+
'name': "#{objid}"
|
41
|
+
};
|
42
|
+
swfobject.embedSWF("/recorder.swf", "#{divid}", "340", "340", "8", "", flashvars, params, attributes);
|
43
|
+
</script>
|
44
|
+
END_RECORDER
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# This method renders the Framey video player from within an ActionView in your Rails app.
|
49
|
+
#
|
50
|
+
# Example Usage (assuming ERB):
|
51
|
+
# <%= javascript_include_tag "swfobject" %>
|
52
|
+
# <%= render_player({
|
53
|
+
# :video_url => "[video url]", # the video url received in the callback (required)
|
54
|
+
# :thumbnail_url => "[thumbnail url]", # the thumbnail url received in the callback (required)
|
55
|
+
# :progress_bar_color => "0x123456", # the desired color for the progress bar (optional, defaults to black)
|
56
|
+
# :volume_bar_color => "0x123456", # the desired color for the volume bar (optional, defaults to black)
|
57
|
+
# :id => "[some id]" # the id of the flash embed object (optional, random by default)
|
58
|
+
# }) %>
|
59
|
+
def render_player(opts={})
|
60
|
+
video_url = opts[:video_url] || "#{Framey::API_HOST}/videos/#{opts[:video_name]}/source.flv"
|
61
|
+
thumbnail_url = opts[:thumbnail_url] || "#{Framey::API_HOST}/videos/#{opts[:video_name]}/thumbnail.jpg"
|
62
|
+
|
63
|
+
divid = "frameyPlayerContainer_#{(rand*999999999).to_i}"
|
64
|
+
objid = opts[:id] || "the#{divid}"
|
65
|
+
|
66
|
+
progress_bar_color = "#{opts[:progress_bar_color]}"
|
67
|
+
volume_bar_color = "#{opts[:volume_bar_color]}"
|
68
|
+
|
69
|
+
raw <<END_PLAYER
|
70
|
+
<div id="#{divid}"></div>
|
71
|
+
<script type="text/javascript">
|
72
|
+
var flashvars = {
|
73
|
+
'video_url': "#{video_url}",
|
74
|
+
'thumbnail_url': "#{thumbnail_url}",
|
75
|
+
"progress_bar_color": "#{progress_bar_color}",
|
76
|
+
"volume_bar_color": "#{volume_bar_color}"
|
77
|
+
};
|
78
|
+
|
79
|
+
var params = {
|
80
|
+
'allowfullscreen': 'true',
|
81
|
+
'allowscriptaccess': 'always',
|
82
|
+
"wmode": "transparent"
|
83
|
+
};
|
84
|
+
|
85
|
+
var attributes = {
|
86
|
+
'id': "#{objid}",
|
87
|
+
'name': "#{objid}"
|
88
|
+
};
|
89
|
+
|
90
|
+
swfobject.embedSWF("/player.swf", "#{divid}", '340', '290', '9', 'false', flashvars, params, attributes);
|
91
|
+
</script>
|
92
|
+
END_PLAYER
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<h1> Previously recorded videos </h1>
|
2
|
+
|
3
|
+
<% if !@videos.empty? %>
|
4
|
+
<% @videos.each do |video|%>
|
5
|
+
|
6
|
+
<div class="framey_video_profile">
|
7
|
+
<span class="framey_video_thumbnail">
|
8
|
+
<a href="<%= framey_video_path(video.name)%>">
|
9
|
+
<%= image_tag video.medium_thumbnail_url%>
|
10
|
+
</a>
|
11
|
+
</span>
|
12
|
+
<span class="framey_video_info">
|
13
|
+
<div class="framey_video_name">
|
14
|
+
Name: <a href="<%= framey_video_path(video.name)%>"><%= video.name %></a>
|
15
|
+
</div>
|
16
|
+
<div class="framey_video_duration">
|
17
|
+
Length: <%= video.duration %> seconds
|
18
|
+
</div>
|
19
|
+
<div class="framey_video_filesize">
|
20
|
+
Filesize: <%= video.filesize / 1024 %> KB
|
21
|
+
</div>
|
22
|
+
<div class="framey_video_date">
|
23
|
+
Created at: <%= video.created_at %>
|
24
|
+
</div>
|
25
|
+
</span>
|
26
|
+
</div>
|
27
|
+
<hr/>
|
28
|
+
|
29
|
+
|
30
|
+
<%end%>
|
31
|
+
<% else %>
|
32
|
+
<h3>No videos were recorded, yet </h3>
|
33
|
+
<% end %>
|
34
|
+
<%= will_paginate @videos %>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<h1>Play Video</h1>
|
2
|
+
<div id="framey_player_container">
|
3
|
+
|
4
|
+
|
5
|
+
<%= render_player({
|
6
|
+
:video_url => @video.flv_url,
|
7
|
+
:thumbnail_url => @video.medium_thumbnail_url,
|
8
|
+
:progress_bar_color => "0x123456",
|
9
|
+
:volume_bar_color => "0x123456"
|
10
|
+
}) %>
|
11
|
+
|
12
|
+
|
13
|
+
<div class="framey_video_profile">
|
14
|
+
<span class="framey_video_info">
|
15
|
+
<div class="framey_video_name">
|
16
|
+
Name: <%= @video.name %>
|
17
|
+
</div>
|
18
|
+
<div class="framey_video_duration">
|
19
|
+
Length: <%= @video.duration %> seconds
|
20
|
+
</div>
|
21
|
+
<div class="framey_video_filesize">
|
22
|
+
Filesize: <%= @video.filesize / 1024 %> KB
|
23
|
+
</div>
|
24
|
+
<div class="framey_video_date">
|
25
|
+
Created at: <%= @video.created_at %>
|
26
|
+
</div>
|
27
|
+
</span>
|
28
|
+
</div>
|
29
|
+
</div>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Framey</title>
|
5
|
+
<%= stylesheet_link_tag("framey") %>
|
6
|
+
<%= javascript_include_tag "swfobject" %>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<div id="framey_bg">
|
10
|
+
<div id="framey_content_container">
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
<div id="framey_footer">
|
14
|
+
<%= link_to "record new", new_framey_video_path %> | <%= link_to "view videos", framey_videos_path %>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</body>
|
20
|
+
|
21
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Rails.application.routes.draw do |map|
|
2
|
+
|
3
|
+
mount_at = Framey::Engine.config.mount_at
|
4
|
+
|
5
|
+
match mount_at => 'framey/videos#index'
|
6
|
+
|
7
|
+
map.resources :videos, :only => [ :index, :show, :new],
|
8
|
+
:controller => "framey/videos",
|
9
|
+
:path_prefix => mount_at,
|
10
|
+
:name_prefix => "framey_"
|
11
|
+
post "/framey/callback" => "framey/videos#callback"
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Framey
|
2
|
+
module ActsAsVideo
|
3
|
+
|
4
|
+
## Define ModelMethods
|
5
|
+
module Base
|
6
|
+
def self.included(klass)
|
7
|
+
klass.class_eval do
|
8
|
+
extend Config
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Config
|
13
|
+
def acts_as_video
|
14
|
+
|
15
|
+
# This is where arbitrary code goes that you want to
|
16
|
+
# add to the class that declared "acts_as_widget"
|
17
|
+
|
18
|
+
has_many :videos, :class_name => 'Framey::Video'
|
19
|
+
|
20
|
+
include Framey::ActsAsVideo::Base::InstanceMethods
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
::ActiveRecord::Base.send :include, Framey::ActsAsVideo::Base
|
@@ -27,7 +27,7 @@ module Framey
|
|
27
27
|
|
28
28
|
params = params.merge({:time_stamp => timestamp, :signature => signature, :api_key => Framey.api_key})
|
29
29
|
res = begin
|
30
|
-
HTTParty.send(method,Framey
|
30
|
+
HTTParty.send(method,Framey::API_HOST + url,{:query => params})
|
31
31
|
rescue SocketError => e
|
32
32
|
nil
|
33
33
|
end
|
@@ -58,8 +58,8 @@ module Framey
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def self.sign
|
61
|
-
timestamp = (Time.now.utc + Framey
|
62
|
-
signature = Digest::MD5.hexdigest(Framey
|
61
|
+
timestamp = (Time.now.utc + Framey::API_TIMEOUT * 60).to_i
|
62
|
+
signature = Digest::MD5.hexdigest(Framey::SECRET + "&" + timestamp.to_s)
|
63
63
|
return timestamp.to_s, signature
|
64
64
|
end
|
65
65
|
|
@@ -85,18 +85,5 @@ module Framey
|
|
85
85
|
class InternalServerError < Error; end
|
86
86
|
end
|
87
87
|
|
88
|
-
class Video
|
89
|
-
attr_accessor :name, :flv_url, :mp4_url, :filesize, :duration, :state, :views, :data, :large_thumbnail_url, :medium_thumbnail_url, :small_thumbnail_url
|
90
|
-
|
91
|
-
def initialize(attrs={})
|
92
|
-
attrs.each do |k,v|
|
93
|
-
self.send("#{k.to_s}=",v)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def delete!
|
98
|
-
Framey::Api::delete_video(self.name)
|
99
|
-
end
|
100
|
-
end
|
101
88
|
end
|
102
89
|
|
data/lib/engine.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'framey'
|
2
|
+
require 'rails'
|
3
|
+
require 'action_controller'
|
4
|
+
require 'application_helper'
|
5
|
+
|
6
|
+
module Framey
|
7
|
+
class Engine < Rails::Engine
|
8
|
+
|
9
|
+
# Config defaults
|
10
|
+
config.video_factory_name = "default factory name"
|
11
|
+
config.mount_at = '/'
|
12
|
+
|
13
|
+
# Load rake tasks
|
14
|
+
rake_tasks do
|
15
|
+
load File.join(File.dirname(__FILE__), 'rails/railties/tasks.rake')
|
16
|
+
end
|
17
|
+
|
18
|
+
# Check the gem config
|
19
|
+
initializer "check config" do |app|
|
20
|
+
|
21
|
+
# make sure mount_at ends with trailing slash
|
22
|
+
config.mount_at += '/' unless config.mount_at.last == '/'
|
23
|
+
end
|
24
|
+
|
25
|
+
initializer "static assets" do |app|
|
26
|
+
app.middleware.use ::ActionDispatch::Static, "#{root}/public"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/framey.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
require 'framey/configuration'
|
2
|
-
require 'framey/api'
|
3
|
-
require 'framey/view_helpers'
|
4
|
-
|
5
1
|
module Framey
|
6
|
-
VERSION
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
require 'engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
3
|
+
require 'acts_as_video/base'
|
4
|
+
require 'application_controller'
|
5
|
+
require 'httparty'
|
6
|
+
require 'will_paginate'
|
7
|
+
require 'api'
|
8
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
class FrameyGenerator < Rails::Generators::Base
|
5
|
+
include Rails::Generators::Migration
|
6
|
+
|
7
|
+
argument :api_key, :type => :string, :required => false, :desc => "An API key is required to use famey. Get the api key from your account page on famey.com"
|
8
|
+
argument :api_secret, :type => :string, :required => false, :desc => "A secret key is required to use famey. Get the api key from your account page on famey.com"
|
9
|
+
|
10
|
+
def self.source_root
|
11
|
+
sources = File.join(File.dirname(__FILE__), 'templates')
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.next_migration_number(dirname) #:nodoc:
|
16
|
+
if ActiveRecord::Base.timestamped_migrations
|
17
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
18
|
+
else
|
19
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# Every method that is declared below will be automatically executed when the generator is run
|
25
|
+
|
26
|
+
def create_migration_file
|
27
|
+
f = File.open File.join(File.dirname(__FILE__), 'templates', 'schema.rb')
|
28
|
+
schema = f.read; f.close
|
29
|
+
|
30
|
+
schema.gsub!(/ActiveRecord::Schema.*\n/, '')
|
31
|
+
schema.gsub!(/^end\n*$/, '')
|
32
|
+
|
33
|
+
f = File.open File.join(File.dirname(__FILE__), 'templates', 'migration.rb')
|
34
|
+
migration = f.read; f.close
|
35
|
+
migration.gsub!(/SCHEMA_AUTO_INSERTED_HERE/, schema)
|
36
|
+
|
37
|
+
tmp = File.open "tmp/~migration_ready.rb", "w"
|
38
|
+
tmp.write migration
|
39
|
+
tmp.close
|
40
|
+
|
41
|
+
migration_template '../../../tmp/~migration_ready.rb',
|
42
|
+
'db/migrate/create_framey_tables.rb'
|
43
|
+
remove_file 'tmp/~migration_ready.rb'
|
44
|
+
end
|
45
|
+
|
46
|
+
def copy_initializer_file
|
47
|
+
|
48
|
+
if self.api_key and self.api_secret
|
49
|
+
f = File.open File.join(File.dirname(__FILE__), 'templates', 'initializer.rb')
|
50
|
+
initializer = f.read; f.close
|
51
|
+
|
52
|
+
initializer.gsub!(/API_KEY_VALUE/, self.api_key)
|
53
|
+
initializer.gsub!(/API_SECRET_VALUE/, self.api_secret)
|
54
|
+
|
55
|
+
tmp = File.open "tmp/~initializer_ready.rb", "w"
|
56
|
+
tmp.write initializer
|
57
|
+
tmp.close
|
58
|
+
|
59
|
+
copy_file '../../../tmp/~initializer_ready.rb',
|
60
|
+
'config/initializers/framey.rb'
|
61
|
+
remove_file 'tmp/~initializer_ready.rb'
|
62
|
+
else
|
63
|
+
copy_file 'initializer.rb', 'config/initializers/framey.rb'
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
def copy_views
|
69
|
+
copy_file '../../../../../app/views/framey/videos/index.html.erb', 'app/views/framey/videos/index.html.erb'
|
70
|
+
copy_file '../../../../../app/views/framey/videos/new.html.erb', 'app/views/framey/videos/new.html.erb'
|
71
|
+
copy_file '../../../../../app/views/framey/videos/show.html.erb', 'app/views/framey/videos/show.html.erb'
|
72
|
+
copy_file '../../../../../app/views/layouts/framey.html.erb', 'app/views/layouts/framey.html.erb'
|
73
|
+
end
|
74
|
+
|
75
|
+
def copy_controllers
|
76
|
+
copy_file '../../../../../app/controllers/framey/videos_controller.rb', 'app/controllers/framey/videos_controller.rb'
|
77
|
+
end
|
78
|
+
|
79
|
+
def copy_models
|
80
|
+
copy_file '../../../../../app/models/framey/video.rb', 'app/models/framey/video.rb'
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Framey
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
|
4
|
+
config.mount_at = '/framey'
|
5
|
+
config.video_factory_name = 'Factory Name'
|
6
|
+
|
7
|
+
end
|
8
|
+
|
9
|
+
API_HOST = "http://framey.com"
|
10
|
+
RUN_ENV = "production"
|
11
|
+
API_KEY = "API_KEY_VALUE"
|
12
|
+
SECRET = "API_SECRET_VALUE"
|
13
|
+
API_TIMEOUT = 15
|
14
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
|
3
|
+
create_table "framey_videos", :force => true do |t|
|
4
|
+
t.string "name"
|
5
|
+
t.integer "filesize", :default => 0
|
6
|
+
t.float "duration"
|
7
|
+
t.string "state"
|
8
|
+
t.integer "views"
|
9
|
+
t.string "data"
|
10
|
+
t.string "flv_url"
|
11
|
+
t.string "mp4_url"
|
12
|
+
t.string "medium_thumbnail_url"
|
13
|
+
t.string "large_thumbnail_url"
|
14
|
+
t.string "small_thumbnail_url"
|
15
|
+
t.datetime "created_at"
|
16
|
+
t.datetime "updated_at"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -41,7 +41,7 @@ raw <<END_RECORDER
|
|
41
41
|
'id': "#{objid}",
|
42
42
|
'name': "#{objid}"
|
43
43
|
};
|
44
|
-
swfobject.embedSWF("
|
44
|
+
swfobject.embedSWF("/recorder.swf", "#{divid}", "340", "340", "8", "", flashvars, params, attributes);
|
45
45
|
</script>
|
46
46
|
END_RECORDER
|
47
47
|
end
|
@@ -59,8 +59,8 @@ END_RECORDER
|
|
59
59
|
# :id => "[some id]" # the id of the flash embed object (optional, random by default)
|
60
60
|
# }) %>
|
61
61
|
def render_player(opts={})
|
62
|
-
video_url = opts[:video_url] || "#{Framey
|
63
|
-
thumbnail_url = opts[:thumbnail_url] || "#{Framey
|
62
|
+
video_url = opts[:video_url] || "#{Framey::API_HOST}/videos/#{opts[:video_name]}/source.flv"
|
63
|
+
thumbnail_url = opts[:thumbnail_url] || "#{Framey::API_HOST}/videos/#{opts[:video_name]}/thumbnail.jpg"
|
64
64
|
|
65
65
|
divid = "frameyPlayerContainer_#{(rand*999999999).to_i}"
|
66
66
|
objid = opts[:id] || "the#{divid}"
|
@@ -89,7 +89,7 @@ raw <<END_PLAYER
|
|
89
89
|
'name': "#{objid}"
|
90
90
|
};
|
91
91
|
|
92
|
-
swfobject.embedSWF("
|
92
|
+
swfobject.embedSWF("/player.swf", "#{divid}", '340', '290', '9', 'false', flashvars, params, attributes);
|
93
93
|
</script>
|
94
94
|
END_PLAYER
|
95
95
|
end
|
Binary file
|
@@ -0,0 +1,4 @@
|
|
1
|
+
/* SWFObject v2.2 <http://code.google.com/p/swfobject/>
|
2
|
+
is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
|
3
|
+
*/
|
4
|
+
var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
|
data/public/player.swf
ADDED
Binary file
|
data/public/recorder.swf
ADDED
Binary file
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#framey_recorder {
|
2
|
+
text-align: center;
|
3
|
+
}
|
4
|
+
|
5
|
+
body{
|
6
|
+
margin: 0px;
|
7
|
+
padding: 0px;
|
8
|
+
text-align: center;
|
9
|
+
}
|
10
|
+
h1{
|
11
|
+
margin-bottom: 50px;
|
12
|
+
}
|
13
|
+
|
14
|
+
#framey_footer{
|
15
|
+
|
16
|
+
text-align: center;
|
17
|
+
padding: 0px;
|
18
|
+
}
|
19
|
+
|
20
|
+
.framey_video_info{
|
21
|
+
float: left;
|
22
|
+
padding: 5px;
|
23
|
+
text-align: left;
|
24
|
+
}
|
25
|
+
#framey_player_container{
|
26
|
+
text-align: center;
|
27
|
+
margin-right:auto;
|
28
|
+
margin-left: auto;
|
29
|
+
width: 360px;
|
30
|
+
white-space: nowrap;
|
31
|
+
}
|
32
|
+
|
33
|
+
.framey_video_thumbnail{
|
34
|
+
float: left;
|
35
|
+
padding: 5px;
|
36
|
+
}
|
37
|
+
.framey_video_profile{
|
38
|
+
height: 125px;
|
39
|
+
margin-right:auto;
|
40
|
+
margin-left: auto;
|
41
|
+
width: 100%;
|
42
|
+
|
43
|
+
}
|
44
|
+
|
45
|
+
|
46
|
+
#framey_content_container{
|
47
|
+
border: solid 2px;
|
48
|
+
width: 500px;
|
49
|
+
font-family: "Arial";
|
50
|
+
text-align: center;
|
51
|
+
padding-bottom: 20px;
|
52
|
+
padding-right: 50px;
|
53
|
+
padding-left: 50px;
|
54
|
+
margin: 0 auto;
|
55
|
+
background: lightgray;
|
56
|
+
|
57
|
+
|
58
|
+
}
|
59
|
+
|
metadata
CHANGED
@@ -1,104 +1,105 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: framey
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 1.1.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
13
|
-
-
|
7
|
+
authors:
|
8
|
+
- Dave Renz
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-09-06 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: httparty
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &2156150860 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
- 7
|
32
|
-
- 7
|
33
|
-
version: 0.7.7
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
34
22
|
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: hoe
|
38
23
|
prerelease: false
|
39
|
-
|
24
|
+
version_requirements: *2156150860
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: will_paginate
|
27
|
+
requirement: &2156148300 !ruby/object:Gem::Requirement
|
40
28
|
none: false
|
41
|
-
requirements:
|
29
|
+
requirements:
|
42
30
|
- - ~>
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.0.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2156148300
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: jeweler
|
38
|
+
requirement: &2156147600 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
49
44
|
type: :development
|
50
|
-
|
51
|
-
|
52
|
-
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2156147600
|
47
|
+
description: TO DO
|
48
|
+
email: david@qlabs.com
|
53
49
|
executables: []
|
54
|
-
|
55
50
|
extensions: []
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
-
|
61
|
-
-
|
62
|
-
-
|
51
|
+
extra_rdoc_files:
|
52
|
+
- README.rdoc
|
53
|
+
files:
|
54
|
+
- app/controllers/framey/videos_controller.rb
|
55
|
+
- app/helpers/application_helper.rb
|
56
|
+
- app/helpers/framey/videos_helper.rb
|
57
|
+
- app/models/framey/video.rb
|
58
|
+
- app/views/framey/videos/index.html.erb
|
59
|
+
- app/views/framey/videos/new.html.erb
|
60
|
+
- app/views/framey/videos/show.html.erb
|
61
|
+
- app/views/layouts/framey.html.erb
|
62
|
+
- config/routes.rb
|
63
|
+
- lib/acts_as_video/base.rb
|
64
|
+
- lib/api.rb
|
65
|
+
- lib/application_controller.rb
|
66
|
+
- lib/application_helper.rb
|
67
|
+
- lib/engine.rb
|
63
68
|
- lib/framey.rb
|
64
|
-
- lib/framey/
|
65
|
-
- lib/framey/
|
66
|
-
- lib/framey/
|
67
|
-
-
|
68
|
-
- .
|
69
|
+
- lib/rails/generators/framey/framey_generator.rb
|
70
|
+
- lib/rails/generators/framey/templates/initializer.rb
|
71
|
+
- lib/rails/generators/framey/templates/migration.rb
|
72
|
+
- lib/rails/generators/framey/templates/schema.rb
|
73
|
+
- lib/rails/railties/tasks.rake
|
74
|
+
- lib/view_helpers.rb
|
75
|
+
- public/images/cheese.jpg
|
76
|
+
- public/javascripts/swfobject.js
|
77
|
+
- public/player.swf
|
78
|
+
- public/recorder.swf
|
79
|
+
- public/stylesheets/framey.css
|
80
|
+
- README.rdoc
|
69
81
|
homepage: http://framey.com
|
70
82
|
licenses: []
|
71
|
-
|
72
83
|
post_install_message:
|
73
|
-
rdoc_options:
|
74
|
-
|
75
|
-
- README.txt
|
76
|
-
require_paths:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
77
86
|
- lib
|
78
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
88
|
none: false
|
80
|
-
requirements:
|
81
|
-
- -
|
82
|
-
- !ruby/object:Gem::Version
|
83
|
-
|
84
|
-
|
85
|
-
- 0
|
86
|
-
version: "0"
|
87
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
94
|
none: false
|
89
|
-
requirements:
|
90
|
-
- -
|
91
|
-
- !ruby/object:Gem::Version
|
92
|
-
|
93
|
-
segments:
|
94
|
-
- 0
|
95
|
-
version: "0"
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
96
99
|
requirements: []
|
97
|
-
|
98
|
-
|
99
|
-
rubygems_version: 1.8.5
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 1.8.6
|
100
102
|
signing_key:
|
101
103
|
specification_version: 3
|
102
104
|
summary: A gem for easy Rails integration with the Framey video recording service.
|
103
|
-
test_files:
|
104
|
-
- test/test_framey.rb
|
105
|
+
test_files: []
|
data/.gemtest
DELETED
File without changes
|
data/Manifest.txt
DELETED
data/README.md
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
# The Framey Ruby Gem
|
2
|
-
|
3
|
-
This gem can be used for easy Rails integration with the Framey video recording service. See http://framey.com for more information.
|
4
|
-
|
5
|
-
# Dependencies:
|
6
|
-
|
7
|
-
* httparty (ruby gem)
|
8
|
-
* swfobject (javascript file)
|
9
|
-
|
10
|
-
# Installation
|
11
|
-
|
12
|
-
If not using bundler, do:
|
13
|
-
|
14
|
-
`gem install framey`
|
15
|
-
|
16
|
-
otherwise in your Gemfile:
|
17
|
-
|
18
|
-
`gem framey`
|
19
|
-
|
20
|
-
# User / Development Flow
|
21
|
-
|
22
|
-
* You make a page on your site that displays the Framey flash video recorder
|
23
|
-
* Your user visits that page and clicks record
|
24
|
-
* If your user likes the video she just recorded, she clicks "Publish"
|
25
|
-
* After a little while, Framey pings your servers at a specified callback url with a url to the video file
|
26
|
-
* You can choose to store those urls on your end, or just the id of the Framey video to access it later on Framey via an API call
|
27
|
-
* You then display the video to your user using either the Framey video player or your own favorite flash video player
|
28
|
-
|
29
|
-
# Usage
|
30
|
-
|
31
|
-
First, sign up at http://framey.com to get an API key and secret and to set your callback url.
|
32
|
-
|
33
|
-
Then in environment.rb do:
|
34
|
-
|
35
|
-
Framey.configure do |config|
|
36
|
-
config.api_key = "[YOUR API KEY]" # required
|
37
|
-
config.api_secret = "[YOUR API SECRET]" # required
|
38
|
-
config.api_timeout = [API SIGNATURE EXPIRATION IN MINUTES] # optional (15 by default)
|
39
|
-
config.max_recording_time = [DEFAULT MAXIMUM VIDEO LENGTH] # optional (30 by default)
|
40
|
-
end
|
41
|
-
|
42
|
-
To render the Framey video recorder in an ActionView (example assumes ERB) do:
|
43
|
-
|
44
|
-
<%= javascript_include_tag "swfobject" %>
|
45
|
-
<%= render_recorder({
|
46
|
-
:id => "myRecorder", # id for the flash embed object (optional, random by default)
|
47
|
-
:max_time => 60, # maximum allowed video length in seconds (optional, defaults to 30)
|
48
|
-
:session_data => { # custom parameters to be passed along to your app later (optional)
|
49
|
-
:user_id => <%= @user.id %> # you may, for example, want to relate this recording to a specific user in your system
|
50
|
-
}
|
51
|
-
}) %>
|
52
|
-
|
53
|
-
When your user then views this recorder, records a video, and clicks "Publish", your app receives a POST to the specified callback url with the following parameters:
|
54
|
-
|
55
|
-
{
|
56
|
-
:video => {
|
57
|
-
:name => [video name], # this is the video's UUID within the Framey system
|
58
|
-
:filesize => [filesize], # the filesize in bytes of the video
|
59
|
-
:duration => [duration], # the duration of the video in seconds
|
60
|
-
:state => [state], # the state of the video, in this case "uploaded"
|
61
|
-
:views => [number of views], # the number of times this video has been viewed, in this case 0
|
62
|
-
:data => [the data hash you specified], # this is the exact data you specified in the :session_data hash when rendering the recorder
|
63
|
-
:flv_url => [video url], # url to the flash video file on framey that you can feed into a video player later
|
64
|
-
:mp4_url => [h.264 video url], # url to the h.264 video file on framey that you can feed into a video player later
|
65
|
-
:large_thumbnail_url => [thumbnail url] # url to the large thumbnail image that was generated for this video
|
66
|
-
:medium_thumbnail_url => [thumbnail url] # url to the medium thumbnail image that was generated for this video
|
67
|
-
:small_thumbnail_url => [thumbnail url] # url to the small thumbnail image that was generated for this video
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
To render the Framey video player in an ActionView (example assumes ERB) do:
|
72
|
-
|
73
|
-
<%= javascript_include_tag "swfobject" %>
|
74
|
-
<%= render_player({
|
75
|
-
:id => "myPlayer", # id for the flash embed object (optional, random by default)
|
76
|
-
:video_url => "[video url]", # the video url received in the callback (required)
|
77
|
-
:thumbnail_url => "[thumbnail url]", # the thumbnail url received in the callback (required)
|
78
|
-
:progress_bar_color => "0x123456", # the desired color for the progress bar (optional, defaults to black)
|
79
|
-
:volume_bar_color => "0x123456", # the desired color for the volume bar (optional, defaults to black)
|
80
|
-
})%>
|
81
|
-
|
82
|
-
Note that you don't have to use the Framey video player, though, and can use any other flash video player you'd like.
|
83
|
-
|
84
|
-
To get updated stats information about a given video, do:
|
85
|
-
|
86
|
-
@video = Framey::Api.get_video("[framey video name]")
|
87
|
-
|
88
|
-
This returns a simple Framey::Video object, like so:
|
89
|
-
|
90
|
-
#<Framey::Video:0x1037b4450 @state="uploaded", @filesize=123456, @name="c96323e0-54b1-012e-9d34-7c6d628c53d4", @large_thumbnail_url="http://framey.com/thumbnails/c96323e0-54b1-012e-9d34-7c6d628c53d4.jpg", @medium_thumbnail_url="http://framey.com/thumbnails/c96323e0-54b1-012e-9d34-7c6d628c53d4.jpg", @small_thumbnail_url="http://framey.com/thumbnails/c96323e0-54b1-012e-9d34-7c6d628c53d4.jpg", @data={"user_id" => 1}, @flv_url="http://framey.com/videos/source/c96323e0-54b1-012e-9d34-7c6d628c53d4/source.flv", @mp4_url="http://framey.com/videos/source/c96323e0-54b1-012e-9d34-7c6d628c53d4/source.mp4", @views=12, @duration=15.62>
|
91
|
-
|
92
|
-
To delete a video on Framey, do:
|
93
|
-
|
94
|
-
@video.delete!
|
95
|
-
|
96
|
-
or:
|
97
|
-
|
98
|
-
Framey::Api.delete_video("[framey video name]")
|
99
|
-
|
100
|
-
# Other Documentation
|
101
|
-
|
102
|
-
* http://rubydoc.info/gems/framey/1.1.0/frames
|
103
|
-
|
104
|
-
# License
|
105
|
-
|
106
|
-
(The MIT License)
|
107
|
-
|
108
|
-
Copyright (c) 2011 FIX
|
109
|
-
|
110
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
111
|
-
a copy of this software and associated documentation files (the
|
112
|
-
'Software'), to deal in the Software without restriction, including
|
113
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
114
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
115
|
-
permit persons to whom the Software is furnished to do so, subject to
|
116
|
-
the following conditions:
|
117
|
-
|
118
|
-
The above copyright notice and this permission notice shall be
|
119
|
-
included in all copies or substantial portions of the Software.
|
120
|
-
|
121
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
122
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
123
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
124
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
125
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
126
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
127
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'hoe'
|
3
|
-
$:.unshift(File.dirname(__FILE__) + "/lib")
|
4
|
-
require 'framey'
|
5
|
-
|
6
|
-
Hoe.spec('framey') do |p|
|
7
|
-
p.name = "framey"
|
8
|
-
p.version = '1.1.0'
|
9
|
-
p.author = "Shaun Salzberg"
|
10
|
-
p.description = "A gem for easy Rails integration with the Framey video recording service."
|
11
|
-
p.email = 'shaun@qlabs.com'
|
12
|
-
p.summary = "A gem for easy Rails integration with the Framey video recording service."
|
13
|
-
p.url = "http://framey.com"
|
14
|
-
p.changes = p.paragraphs_of('CHANGELOG', 0..1).join("\n\n")
|
15
|
-
p.dependency("httparty",">= 0.7.7")
|
16
|
-
p.remote_rdoc_dir = '' # Release to root
|
17
|
-
end
|
18
|
-
|
19
|
-
|
data/lib/framey/configuration.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
module Framey
|
2
|
-
|
3
|
-
module Configuration
|
4
|
-
VERSION = '1.0.4'.freeze unless defined?(VERSION)
|
5
|
-
|
6
|
-
DEFAULT_API_HOST = "http://framey.com".freeze
|
7
|
-
DEFAULT_USER_AGENT = "Framey Ruby Gem #{VERSION}".freeze
|
8
|
-
DEFAULT_RUN_ENV = "production"
|
9
|
-
|
10
|
-
CONFIGURATION_OPTIONS = {
|
11
|
-
:api_key => nil,
|
12
|
-
:api_secret => nil,
|
13
|
-
:api_timeout => 15, # minutes
|
14
|
-
:max_recording_time => 30, # seconds
|
15
|
-
:api_host => DEFAULT_API_HOST,
|
16
|
-
:run_env => DEFAULT_RUN_ENV,
|
17
|
-
:user_agent => DEFAULT_USER_AGENT
|
18
|
-
}.freeze
|
19
|
-
|
20
|
-
attr_accessor *(CONFIGURATION_OPTIONS.map { |k,v| k })
|
21
|
-
|
22
|
-
def self.extended(base)
|
23
|
-
base.reset
|
24
|
-
end
|
25
|
-
|
26
|
-
def configure(&blk)
|
27
|
-
yield(self)
|
28
|
-
end
|
29
|
-
|
30
|
-
def options
|
31
|
-
options = {}
|
32
|
-
CONFIGURATION_OPTIONS.each{|k| options[k] = send(k) }
|
33
|
-
options
|
34
|
-
end
|
35
|
-
|
36
|
-
def reset
|
37
|
-
CONFIGURATION_OPTIONS.each do |k,v|
|
38
|
-
send("#{k}=",v)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|