jeeves-pvr 0.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.
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/ruby18
2
+ #
3
+ # This file was generated by RubyGems.
4
+ #
5
+ # The application 'jeeves-pvr' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'rubygems'
10
+
11
+ version = ">= 0"
12
+
13
+ if ARGV.first
14
+ str = ARGV.first
15
+ str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
16
+ if str =~ /\A_(.*)_\z/
17
+ version = $1
18
+ ARGV.shift
19
+ end
20
+ end
21
+
22
+ #gem 'jeeves-pvr', version
23
+ #require 'jeeves'
24
+ executable = Gem.bin_path('jeeves-pvr', 'jeeves', version)
25
+ puts executable
26
+ load executable
@@ -0,0 +1,46 @@
1
+ #
2
+ # Configuration Options for: Jeeves::Config
3
+ #
4
+
5
+ # Add a file partition for Jeeves. Must have the following parameters:
6
+ # :path - valid file path to the partition to be added (not a device path),
7
+ # :key - the key given to the partition when it was initialised,
8
+ # :mountable - true if the partition should be mounted directly,
9
+ # :mounted_on - path of mount point if the partition is not one itself
10
+ #
11
+ # Use :mountable=>true to enable the partition to be mounted - needs to be an entry in /etc/fstab
12
+ # If the partition is not directly mountable but is on a mountable device partition that you also want
13
+ # mounted then use :mounted_on=>/path/to/partition instead
14
+ #add_partition
15
+ add_partition :path=>'/home/jeeves', :key=>'d1520a02b294db739bddb2324482310116f39d07'
16
+ add_partition :path=>'/home/jeeves_2', :key=>'9227567edca1bb8018d2c7bda592dbb69a89af35'
17
+
18
+ # Specify what to do if a specified partition cannot be added, e.g. because it has not been mounted
19
+ # Can be one of the following:
20
+ # :ignore - log an info message and carry on
21
+ # :warn - let the user know but carry on
22
+ # :fatal - do not continue without the partition
23
+ #
24
+ # The default is to warn but carry on. Jeeves should still be able to allocate a file even if there are
25
+ # missing partitions in the store
26
+ store_errors :warn
27
+
28
+ # Specify the environment within which Jeeves services (Jetuner etc) are expected
29
+ # to be operating. Should be one of :dev, :test or :prod
30
+ #environment :dev
31
+
32
+ # URL to the Jeeves listing/TV application that has info on programme listings
33
+ jeeves_tv_url 'http://tv.jeeves.osburn-sharp.ath.cx'
34
+
35
+ # Set the base rate for estimating data storage in kbytes per second. Note
36
+ # for some tuners this may need to be scaled, which can be done at the time
37
+ # of allocation.
38
+ #base_data_rate 416
39
+
40
+ # Specify a directory where jeeves can put working files etc. If you are working
41
+ # across a network then this directory needs to be shared across the network too.
42
+ working_dir '/home/jeeves/.jeeves'
43
+
44
+ # URL to the Jeeves video application to which recorded videos are referred etc
45
+ jeeves_url 'http://jeeves.osburn-sharp.ath.cx'
46
+
@@ -0,0 +1,68 @@
1
+ #
2
+ # Author:: R.J.Sharp
3
+ # Email:: robert(a)osburn-sharp.ath.cx
4
+ # Copyright:: Copyright (c) 2011
5
+ # License:: Open Software Licence v3.0
6
+ #
7
+ # This software is licensed for use under the Open Software Licence v. 3.0
8
+ # The terms of this licence can be found at http://www.opensource.org/licenses/osl-3.0.php
9
+ # and in the file LICENCE. Under the terms of this licence, all derivative works
10
+ # must themselves be licensed under the Open Software Licence v. 3.0
11
+ #
12
+ #
13
+ require 'jerbil/jerbil_service/base'
14
+ require 'jerbil/jerbil_service/support'
15
+ require 'jerbil/support'
16
+ require 'jerbil/config'
17
+
18
+ # pull in things to do with jeeves
19
+
20
+ require 'jeeves/listings'
21
+ require 'jeeves/store'
22
+ require 'jeeves/tags'
23
+ require 'jeeves/config'
24
+ require 'jeeves/errors'
25
+
26
+ #
27
+ # == Jeeves Service
28
+ #
29
+ # Synopsis of the whole service
30
+ #
31
+ module Jeeves
32
+
33
+ # add generic class methods
34
+ extend JerbilService::Support
35
+
36
+ # === Jeeves Service class
37
+ #
38
+ # Description of how the service class works
39
+ #
40
+ # class Service < JerbilService::Base
41
+ #
42
+ # # Document the constructor as required.
43
+ # #
44
+ # # pkey:: string - private key that must be used for
45
+ # # supervision calls (e.g. stop_callback)
46
+ # # options:: hash of options, preferably as created by Jeckyl. See documentation
47
+ # # on JerbilService::Base for assumed options re logging etc
48
+ # #
49
+ # def initialize(pkey, options)
50
+ #
51
+ # # do things that cannot be done when $SAFE > 0
52
+ #
53
+ # # the symbol should be the app name and must correspond to a service in /etc/services
54
+ # super(:jeeves, pkey, options)
55
+ #
56
+ # # DRb is now working, this process may have daemonized and $SAFE = 1
57
+ #
58
+ # end
59
+ #
60
+ # #
61
+ # # define additional class methods to make things happen
62
+ # #
63
+ #
64
+ # # do not redefine the superclass methods unless you are absolutely sure you know
65
+ # # what you are doing.
66
+ #
67
+ # end
68
+ end
@@ -0,0 +1,141 @@
1
+ #
2
+ #
3
+ # = Configuration settings for Jeeves Applications etc
4
+ #
5
+ # == Jeckyl config
6
+ #
7
+ # Author:: Robert Sharp
8
+ # Copyright:: Copyright (c) 2013 Robert Sharp
9
+ # License:: Open Software Licence v3.0
10
+ #
11
+ # This software is licensed for use under the Open Software Licence v. 3.0
12
+ # The terms of this licence can be found at http://www.opensource.org/licenses/osl-3.0.php
13
+ # and in the file copyright.txt. Under the terms of this licence, all derivative works
14
+ # must themselves be licensed under the Open Software Licence v. 3.0
15
+ #
16
+ #
17
+ #
18
+ require 'jeckyl'
19
+
20
+ module Jeeves
21
+
22
+ # define all of the configuration settings for Jeeves. Derived from
23
+ # Jellog to provide logging options for store operations
24
+ #
25
+ class Config < Jeckyl::Config
26
+
27
+ def configure_add_partition(params={})
28
+ comment "Add a file partition for Jeeves. Must have the following parameters:",
29
+ " :path - valid file path to the partition to be added (not a device path),",
30
+ " :key - the key given to the partition when it was initialised,",
31
+ " :mountable - true if the partition should be mounted directly,",
32
+ " :mounted_on - path of mount point if the partition is not one itself",
33
+ " ",
34
+ "Use :mountable=>true to enable the partition to be mounted - needs to be an entry in /etc/fstab",
35
+ "If the partition is not directly mountable but is on a mountable device partition that you also want",
36
+ "mounted then use :mounted_on=>/path/to/partition instead"
37
+
38
+ # ignore calls to get a default, which will not have the right params
39
+ return unless params.kind_of?(Hash)
40
+
41
+ @stores ||= Hash.new
42
+
43
+ if @stores.has_key?(params[:path]) then
44
+ # should not have defined the store already...
45
+ raise Jeckyl::ConfigError, "Duplicate store: #{params[:path]}"
46
+ end
47
+
48
+ # make sure this is a writable directory
49
+ # but if its not mounted it may not be!
50
+ #a_writable_dir(params[:path])
51
+
52
+ # if Jeeves.store_key(params[:path]) != params[:key] then
53
+ # # store has not been initialised with this key
54
+ # raise Jeckyl::ConfigError, "Incorrect/missing key for store: #{params[:path]}"
55
+ # end
56
+
57
+ @stores[params[:path]] = {:key=>params[:key]}
58
+
59
+ # check that both mount options have not been provided
60
+ if params[:mountable] then
61
+ if params.has_key?(:mounted_on) then
62
+ raise Jeckyl::ConfigError, "Please provide :mountable or :mounted_on but not both"
63
+ end
64
+ @stores[params[:path]][:mount_point] = params[:path]
65
+ end
66
+
67
+ if params.has_key?(:mounted_on) then
68
+ a_readable_file(params[:mounted_on]) # the directory may not be writable!
69
+ @stores[params[:path]][:mount_point] = params[:mounted_on]
70
+ end
71
+
72
+ return @stores
73
+
74
+ end
75
+
76
+ def configure_base_data_rate(kbpm)
77
+ default 25000 / 60 # reasonable rate for dvb
78
+ comment "Set the base rate for estimating data storage in kbytes per second. Note",
79
+ "for some tuners this may need to be scaled, which can be done at the time",
80
+ "of allocation."
81
+
82
+ a_type_of(kbpm, Integer) && in_range(kbpm, 100, 10000)
83
+
84
+ end
85
+
86
+ def configure_jeeves_url(url)
87
+ comment "URL to the Jeeves video application to which recorded videos are referred etc"
88
+
89
+ a_matching_string(url, /https?:\/\/[\S]+/)
90
+ end
91
+
92
+ def configure_jeeves_tv_url(url)
93
+ comment "URL to the Jeeves listing/TV application that has info on programme listings"
94
+
95
+ a_matching_string(url, /https?:\/\/[\S]+/)
96
+ end
97
+
98
+ def configure_jeeves_uri_timeout(timeout)
99
+ default 2 * 60 # 2 minutes
100
+ comment "Set the timeout on updating Jeeves TV with the listings data. This can",
101
+ "take a long time so usually it exceeds the default. Needs to be in seconds.",
102
+ "To set an infinite timeout, use 0"
103
+
104
+ a_type_of(timeout, Integer) && in_range(timeout, 0, 10000) # some very high upper limit
105
+
106
+ end
107
+
108
+ def configure_store_errors(symb)
109
+ default :warn
110
+ comment "Specify what to do if a specified partition cannot be added, e.g. because it has not been mounted",
111
+ "Can be one of the following:",
112
+ " :ignore - log an info message and carry on",
113
+ " :warn - let the user know but carry on",
114
+ " :fatal - do not continue without the partition",
115
+ "",
116
+ "The default is to warn but carry on. Jeeves should still be able to allocate a file even if there are",
117
+ "missing partitions in the store"
118
+
119
+ a_member_of(symb, [:ignore, :warn, :fatal])
120
+
121
+ end
122
+
123
+ def configure_working_dir(dir)
124
+ default '/tmp'
125
+ comment "Specify a directory where jeeves can put working files etc. If you are working",
126
+ "across a network then this directory needs to be shared across the network too."
127
+
128
+ a_writable_dir(dir)
129
+
130
+ end
131
+
132
+ def configure_environment(env)
133
+ default :dev
134
+ comment "Specify the environment within which Jeeves services (Jetuner etc) are expected",
135
+ "to be operating. Should be one of :dev, :test or :prod"
136
+ a_member_of(env, [:dev, :test, :prod])
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,70 @@
1
+ #
2
+ # Author:: R.J.Sharp
3
+ # Email:: robert(a)osburn-sharp.ath.cx
4
+ # Copyright:: Copyright (c) 2011
5
+ # License:: Open Software Licence v3.0
6
+ #
7
+ # This software is licensed for use under the Open Software Licence v. 3.0
8
+ # The terms of this licence can be found at http://www.opensource.org/licenses/osl-3.0.php
9
+ # and in the file LICENCE. Under the terms of this licence, all derivative works
10
+ # must themselves be licensed under the Open Software Licence v. 3.0
11
+ #
12
+ #
13
+ # This file groups together all the errors for jeeves.
14
+ # Preceed each class with a description of the error
15
+
16
+ module Jeeves
17
+
18
+ # A general class for all errors created by this project. All specific exceptions
19
+ # should be children of this class
20
+ class JeevesError < RuntimeError; end
21
+
22
+ class VersionError < JeevesError; end
23
+
24
+ # errors raised by the scheduler
25
+ class JscheduleError < JeevesError; end
26
+
27
+ #the tuner type for a scheduler is not valid
28
+ class InvalidTuner < JscheduleError; end
29
+
30
+ # the tuner does not have the given mode
31
+ class InvalidMode < JscheduleError; end
32
+
33
+ # a schedule request is missing a required parameter
34
+ class MissingParam < JscheduleError; end
35
+
36
+ # the tuner is busy
37
+ class TunerBusy < JscheduleError; end
38
+
39
+ # store related errors
40
+ class StoreError < JeevesError; end
41
+
42
+ class InvalidPartition < StoreError; end
43
+
44
+ class InvalidPartitionKey < StoreError; end
45
+
46
+ class DiskError < JeevesError; end
47
+
48
+ # listings related errors
49
+ class ListingError < JeevesError; end
50
+ class VideoError < JeevesError; end
51
+
52
+
53
+ class TaggerError < JeevesError; end
54
+
55
+ # A Jeckyl option that is needed has not been provided
56
+ class MissingOption < TaggerError; end
57
+
58
+ # the file provided cannot be read
59
+ class FileError < TaggerError; end
60
+
61
+ # the url does not work
62
+ class UrlError < TaggerError; end
63
+
64
+ # there was an error with the XML tags
65
+ class XMLError < TaggerError; end
66
+
67
+ # error creating matroska file
68
+ class MkvError < TaggerError; end
69
+
70
+ end
@@ -0,0 +1,116 @@
1
+ #
2
+ #
3
+ # = Xmltv
4
+ #
5
+ # == methods for interfacing xmltv with jeeves
6
+ #
7
+ # Author:: Robert Sharp
8
+ # Copyright:: Copyright (c) 2013 Robert Sharp
9
+ # License:: Open Software Licence v3.0
10
+ #
11
+ # This software is licensed for use under the Open Software Licence v. 3.0
12
+ # The terms of this licence can be found at http://www.opensource.org/licenses/osl-3.0.php
13
+ # and in the file copyright.txt. Under the terms of this licence, all derivative works
14
+ # must themselves be licensed under the Open Software Licence v. 3.0
15
+ #
16
+ #
17
+ #
18
+ require 'jeckyl/errors'
19
+ require 'jeeves/errors'
20
+
21
+ module Jeeves
22
+
23
+ # load the latest listings data into Jeeves
24
+ #
25
+ # jeeves will use existing listings data if it was downloaded
26
+ # less than 6 hours ago. This can be overriden with the :force option
27
+ #
28
+ # If the :reset option is set to true then the listings data will replace
29
+ # all existing data and not just append to it.
30
+ #
31
+ # @param [Hash] params to control the loading
32
+ # @option [String] :working_dir, see config
33
+ # @option [String] :jeeves_tv_url, see config
34
+ # @option [Boolean] :force - set to true to force new listings data
35
+ # @option [Boolean] :reset - set to true to reset all listings data
36
+ def Jeeves.update_listings(params={})
37
+
38
+ working_dir = params[:working_dir]
39
+ unless File.directory?(working_dir) && File.writable?(working_dir)
40
+ # if config file is used this should not be possible
41
+ raise Jeckyl::ConfigError, "Cannot write to #{working_dir}"
42
+ end
43
+
44
+ chan_txt_file = File.join(working_dir, 'channels.txt')
45
+ listings_file = File.join(working_dir, 'listings.xml')
46
+
47
+ age = 0
48
+ # see how old it is
49
+ age = Time.now - File.mtime(listings_file) if FileTest.exists?(listings_file)
50
+
51
+ age = 0 if params[:update_listings] == true
52
+
53
+ jeeves_tv_url = params[:jeeves_tv_url]
54
+
55
+ # check how old the listings file is
56
+ unless age > 0 && age < (60*60*6) then
57
+ # its more than 6 hours old, so renew it
58
+ # or you forced renewal!
59
+
60
+ # make sure it does not already exist
61
+ FileUtils.rm_f(chan_txt_file)
62
+ FileUtils.rm_f(listings_file)
63
+
64
+
65
+ # get the channels info from jeeves_tv
66
+ cmd = "/usr/bin/wget #{jeeves_tv_url}/bchannels.txt -O #{chan_txt_file}"
67
+
68
+
69
+ unless system(cmd)
70
+ raise ListingError, "#{cmd}\n failed with error #{$?}"
71
+ end
72
+
73
+ unless File.exists?(chan_txt_file)
74
+ raise ListingError, "Failed to create file: #{chan_txt_file}"
75
+ end
76
+
77
+ # now copy this file to where xmltv expects to find it.
78
+ # cheat with shell cos of ~
79
+ cmd = "cp #{chan_txt_file} ~/.xmltv/tv_grab_uk_rt.conf"
80
+ unless system(cmd)
81
+ raise ListingError, "Failed to copy file: #{cmd}"
82
+ end
83
+
84
+ cmd = "/usr/bin/tv_grab_uk_rt >#{listings_file}"
85
+ unless system(cmd)
86
+ raise ListingError, "Failed to grab listings: #{$?}\n #{cmd}"
87
+ end
88
+ end
89
+
90
+ listings_url = URI.encode(listings_file) # ensure it is OK as url
91
+
92
+ # and now poke jeeves-tv to let it know there is something to process
93
+ #cmd = "/usr/bin/wget #{jeeves_tv_url}/load?file=#{listings_url}"
94
+ url = "#{jeeves_tv_url}/load?file=#{listings_url}"
95
+ url << "&reset=true" if params[:reset_listings]
96
+
97
+ # unless system(cmd)
98
+ # raise ListingError, "Failed to load programme info: #{$?}\n#{cmd}"
99
+ # end
100
+
101
+ rto = params[:jeeves_uri_timeout]
102
+ rto = nil if rto == 0 # makes it infinite
103
+
104
+ response = Array.new
105
+ open(url, read_timeout:rto) do |resp|
106
+ resp.each_line do |line|
107
+ response << line
108
+ end
109
+ end
110
+
111
+ # test that the response was OK
112
+
113
+ return true
114
+ end
115
+
116
+ end