Class: UPnP::Service::ContentDirectory
- Inherits:
-
UPnP::Service
- Object
- UPnP::Service
- UPnP::Service::ContentDirectory
- Defined in:
- lib/UPnP/service/content_directory.rb
Overview
A UPnP ContentDirectory service. See upnp.org for specifications.
Constant Summary collapse
- VERSION =
'1.0'
Instance Method Summary collapse
-
#add_directory(directory) ⇒ Object
Adds
directory
as a path searched by the content server. -
#add_object(name, parent) ⇒ Object
Adds object
name
to the directory tree underparent
. -
#Browse(object_id, browse_flag, filter, starting_index, requested_count, sort_criteria) ⇒ Object
Allows the caller to incrementally browse the hierarchy of the content directory, including information listing the classes of objects available in any container.
- #children_result(object_id) ⇒ Object
- #get_object(name, parent_id = nil) ⇒ Object
- #get_parent(object_id) ⇒ Object
-
#GetSearchCapabilities ⇒ Object
Returns the searching capabilities supported by the device.
-
#GetSortCapabilities ⇒ Object
Returns the CSV list of metadata tags that can be used in sortCriteria.
-
#GetSystemUpdateID ⇒ Object
Returns the current value of the SystemUpdateID state variable.
-
#initialize(*args) ⇒ ContentDirectory
constructor
A new instance of ContentDirectory.
- #item_class(mime_type) ⇒ Object
- #make_result ⇒ Object
- #metadata_result(object_id) ⇒ Object
- #mount_extra(http_server) ⇒ Object
- #on_init ⇒ Object
- #resource(xml, object, mime_type, stat) ⇒ Object
-
#resource_url(object) ⇒ Object
A URL to this object on this server.
- #result_container(xml, object, object_id, children, title) ⇒ Object
- #result_item(xml, object, object_id, title) ⇒ Object
- #result_object(xml, object, object_id, title) ⇒ Object
-
#root_for(object_id) ⇒ Object
Returns the root for
object_id
.
Constructor Details
#initialize(*args) ⇒ ContentDirectory
Returns a new instance of ContentDirectory.
124 125 126 127 128 |
# File 'lib/UPnP/service/content_directory.rb', line 124 def initialize(*args) @directories = [] super end |
Instance Method Details
#add_directory(directory) ⇒ Object
Adds directory
as a path searched by the content server
198 199 200 201 202 203 204 205 |
# File 'lib/UPnP/service/content_directory.rb', line 198 def add_directory(directory) return self if @directories.include? directory add_object directory, 0 @directories << directory self end |
#add_object(name, parent) ⇒ Object
Adds object name
to the directory tree under parent
183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/UPnP/service/content_directory.rb', line 183 def add_object(name, parent) object_id = @object_count @object_count += 1 @objects[object_id] = name @objects[name] = object_id @parents[object_id] = parent object_id end |
#Browse(object_id, browse_flag, filter, starting_index, requested_count, sort_criteria) ⇒ Object
Allows the caller to incrementally browse the hierarchy of the content directory, including information listing the classes of objects available in any container.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/UPnP/service/content_directory.rb', line 148 def Browse(object_id, browse_flag, filter, starting_index, requested_count, sort_criteria) filter = filter.split ',' object_id = object_id.to_i update_id = 0 case browse_flag when 'BrowseMetadata' then number_returned = 1 total_matches = 1 result = object_id when 'BrowseDirectChildren' then number_returned, total_matches, result = children_result object_id else raise "unknown BrowseFlag #{browse_flag}" end [nil, result, number_returned, total_matches, update_id] end |
#children_result(object_id) ⇒ Object
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/UPnP/service/content_directory.rb', line 207 def children_result(object_id) object = get_object object_id children = if object_id == 0 then @directories else Dir[File.join(object, '*')] end result = make_result do |xml| children.each do |child| child_id = get_object child, object_id result_object xml, child, child_id, File.basename(child) end end [children.length, children.length, result] end |
#get_object(name, parent_id = nil) ⇒ Object
227 228 229 230 231 232 233 234 235 |
# File 'lib/UPnP/service/content_directory.rb', line 227 def get_object(name, parent_id = nil) if @objects.key? name then @objects[name] elsif parent_id.nil? then raise Error, "object #{name} does not exist" else add_object name, parent_id end end |
#get_parent(object_id) ⇒ Object
237 238 239 240 241 242 243 |
# File 'lib/UPnP/service/content_directory.rb', line 237 def get_parent(object_id) if @parents.key? object_id then @parents[object_id] else raise Error, "invalid object id #{object_id}" end end |
#GetSearchCapabilities ⇒ Object
Returns the searching capabilities supported by the device
17 18 |
# File 'lib/UPnP/service/content_directory.rb', line 17 add_action 'GetSearchCapabilities', [OUT, 'SearchCaps', 'SearchCapabilities'] |
#GetSortCapabilities ⇒ Object
Returns the CSV list of metadata tags that can be used in sortCriteria
23 24 |
# File 'lib/UPnP/service/content_directory.rb', line 23 add_action 'GetSortCapabilities', [OUT, 'SortCaps', 'SortCapabilities'] |
#GetSystemUpdateID ⇒ Object
Returns the current value of the SystemUpdateID state variable. For use by clients that want to poll for any changes in the content directory instead of subscribing to events.
174 175 176 |
# File 'lib/UPnP/service/content_directory.rb', line 174 def GetSystemUpdateID [nil, @SystemUpdateID] end |
#item_class(mime_type) ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/UPnP/service/content_directory.rb', line 245 def item_class(mime_type) case mime_type when /^image/ then 'object.item.imageItem' when /^audio/ then 'object.item.audioItem' else puts "unhandled mime type #{mime_type}" 'object.item' end end |
#make_result ⇒ Object
257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/UPnP/service/content_directory.rb', line 257 def make_result result = [] xml = Builder::XmlMarkup.new :indent => 2, :target => result xml.tag! 'DIDL-Lite', 'xmlns' => 'urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/', 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/', 'xmlns:upnp' => 'urn:schemas-upnp-org:metadata-1-0/upnp/' do yield xml end result.join end |
#metadata_result(object_id) ⇒ Object
271 272 273 274 275 276 277 278 279 280 |
# File 'lib/UPnP/service/content_directory.rb', line 271 def (object_id) object = get_object object_id parent = get_parent object_id title = File.basename object make_result do |xml| result_object xml, object, object_id, title end end |
#mount_extra(http_server) ⇒ Object
282 283 284 285 286 287 288 289 290 291 |
# File 'lib/UPnP/service/content_directory.rb', line 282 def mount_extra(http_server) super @directories.each do |root| root_id = get_object root path = File.join service_path, root_id.to_s http_server.mount path, WEBrick::HTTPServlet::FileHandler, root end end |
#on_init ⇒ Object
130 131 132 133 134 135 136 137 138 139 |
# File 'lib/UPnP/service/content_directory.rb', line 130 def on_init @SystemUpdateID = 0 @object_count = 0 @objects = {} @parents = {} add_object 'root', -1 WEBrick::HTTPUtils::DefaultMimeTypes['mp3'] = 'audio/mpeg' end |
#resource(xml, object, mime_type, stat) ⇒ Object
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/UPnP/service/content_directory.rb', line 293 def resource(xml, object, mime_type, stat) info = nil url = nil case mime_type when /^audio\/(.*)/ then pn = case $1 when 'mpeg' then 'MP3' end pn = "DLNA.ORG_PN=#{pn}" additional = [pn, 'DLNA.ORG_OP=01', 'DLNA.ORG_CI=0'].compact.join ';' info = ['http-get', '*', mime_type, additional] when /^image\/(.*)/ then pn = case $1 when 'jpeg' then 'JPEG_LRG' end pn = "DLNA.ORG_PN=#{pn}" additional = [pn, 'DLNA.ORG_OP=01', 'DLNA.ORG_CI=0'].compact.join ';' info = ['http-get', '*', mime_type, additional] end if info then url = resource_url object attributes = { :protocolInfo => info.join(':'), :size => stat.size, } xml.res attributes, URI.escape(url) end end |
#resource_url(object) ⇒ Object
A URL to this object on this server. Correctly handles multi-homed servers.
338 339 340 341 342 343 344 345 346 347 |
# File 'lib/UPnP/service/content_directory.rb', line 338 def resource_url(object) _, port, host, addr = Thread.current[:WEBrickSocket].addr root = root_for object root_id = get_object root object = object.sub root, '' File.join "http://#{addr}:#{port}", service_path, root_id.to_s, object end |
#result_container(xml, object, object_id, children, title) ⇒ Object
361 362 363 364 365 366 367 |
# File 'lib/UPnP/service/content_directory.rb', line 361 def result_container(xml, object, object_id, children, title) xml.tag! 'container', :id => object_id, :parentID => get_parent(object_id), :restricted => true, :childCount => children do xml.dc :title, title xml.upnp :class, 'object.container' end end |
#result_item(xml, object, object_id, title) ⇒ Object
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
# File 'lib/UPnP/service/content_directory.rb', line 369 def result_item(xml, object, object_id, title) inn, out, = Open3.popen3('file', '-bI', object) inn.close mime_type = out.read.strip stat = File.stat object xml.tag! 'item', :id => object_id, :parentID => get_parent(object_id), :restricted => true, :childCount => 0 do xml.dc :title, title xml.dc :date, stat.ctime.iso8601 xml.upnp :class, item_class(mime_type) resource xml, object, mime_type, stat end end |
#result_object(xml, object, object_id, title) ⇒ Object
349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/UPnP/service/content_directory.rb', line 349 def result_object(xml, object, object_id, title) if object_id == 0 then result_container xml, object, object_id, @directories.length, title elsif File.directory? object then children = Dir[File.join(object, '*/')].length result_container xml, object, object_id, children, title else result_item xml, object, object_id, title end end |
#root_for(object_id) ⇒ Object
Returns the root for object_id
390 391 392 393 394 395 396 397 398 |
# File 'lib/UPnP/service/content_directory.rb', line 390 def root_for(object_id) object_id = get_object object_id unless Integer === object_id while (parent_id = get_parent(object_id)) != 0 do object_id = parent_id end get_object object_id end |