Initial import
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
racket/contract
|
||||
(file "../main.rkt")
|
||||
(file "../services/av-transport.rkt")))
|
||||
|
||||
@title{AVTransport}
|
||||
|
||||
@defmodule[@racketmodname[racket-upnp/services/av-transport] #:module-paths ((file "../services/av-transport.rkt"))]
|
||||
|
||||
AVTransport controls the playback state of a MediaRenderer. The media itself
|
||||
is normally fetched by the renderer from the URI supplied by the control
|
||||
point.
|
||||
|
||||
@defproc[(device-av-transport [device upnp-device?]) (or/c #f upnp-service?)]{Returns the device's AVTransport service.}
|
||||
@defproc[(av-transport? [value any/c]) boolean?]{Recognises an AVTransport service.}
|
||||
@defproc[(av-transport-set-uri! [transport av-transport?]
|
||||
[uri string?]
|
||||
[#:metadata metadata string? ""]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0])
|
||||
void?]{Sets the current transport URI and optional DIDL-Lite metadata.}
|
||||
@defproc[(av-transport-play! [transport av-transport?]
|
||||
[#:speed speed any/c 1]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0])
|
||||
void?]{Starts playback.}
|
||||
@defproc[(av-transport-pause! [transport av-transport?]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0]) void?]{Pauses playback.}
|
||||
@defproc[(av-transport-stop! [transport av-transport?]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0]) void?]{Stops playback.}
|
||||
@defproc[(av-transport-seek! [transport av-transport?]
|
||||
[seconds nonnegative-real?]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0]) void?]{Seeks using the UPnP @tt{REL_TIME} unit.}
|
||||
@defproc[(av-transport-status [transport av-transport?]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0]) symbol?]{Returns a state such as @racket['playing], @racket['paused], @racket['stopped], or @racket['unknown].}
|
||||
@defproc[(av-transport-position [transport av-transport?]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0]) transport-position?]{Returns the current track, position, duration, and URI.}
|
||||
|
||||
@section{Position values}
|
||||
|
||||
@defproc[(transport-position? [value any/c]) boolean?]{Recognises an AVTransport position value.}
|
||||
@defproc[(transport-position-track [position transport-position?]) (or/c #f exact-integer?)]{Returns the current track number.}
|
||||
@defproc[(transport-position-seconds [position transport-position?]) (or/c #f nonnegative-real?)]{Returns the current relative position in seconds.}
|
||||
@defproc[(transport-position-duration [position transport-position?]) (or/c #f nonnegative-real?)]{Returns the track duration in seconds.}
|
||||
@defproc[(transport-position-uri [position transport-position?]) (or/c #f string?)]{Returns the current track URI.}
|
||||
@@ -0,0 +1,21 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
racket/contract
|
||||
(file "../main.rkt")
|
||||
(file "../services/connection-manager.rkt")))
|
||||
|
||||
@title{ConnectionManager}
|
||||
|
||||
@defmodule[@racketmodname[racket-upnp/services/connection-manager] #:module-paths ((file "../services/connection-manager.rkt"))]
|
||||
|
||||
ConnectionManager reports supported transfer protocols and active connection
|
||||
identifiers. For a MediaRenderer, the sink protocol list indicates which media
|
||||
formats the renderer advertises as acceptable.
|
||||
|
||||
@defproc[(device-connection-manager [device upnp-device?]) (or/c #f upnp-service?)]{Returns the device's ConnectionManager service.}
|
||||
@defproc[(connection-manager? [value any/c]) boolean?]{Recognises a ConnectionManager service.}
|
||||
@defproc[(connection-manager-protocols [manager connection-manager?]) any]{Returns two values: source protocol-info strings and sink protocol-info strings.}
|
||||
@defproc[(connection-manager-source-protocols [manager connection-manager?]) (listof string?)]{Returns source protocol-info strings.}
|
||||
@defproc[(connection-manager-sink-protocols [manager connection-manager?]) (listof string?)]{Returns sink protocol-info strings.}
|
||||
@defproc[(connection-manager-connection-ids [manager connection-manager?]) (listof exact-integer?)]{Returns currently advertised connection identifiers.}
|
||||
@@ -0,0 +1,41 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
racket/contract
|
||||
(file "../main.rkt")
|
||||
(file "../services/content-directory.rkt")))
|
||||
|
||||
@title{ContentDirectory}
|
||||
|
||||
@defmodule[@racketmodname[racket-upnp/services/content-directory] #:module-paths ((file "../services/content-directory.rkt"))]
|
||||
|
||||
ContentDirectory is the low-level media-server service. Its browse and search
|
||||
operations return raw DIDL-Lite XML. Applications that want parsed containers,
|
||||
items, and resource URIs can use @racketmodname[racket-upnp/media-server].
|
||||
|
||||
@defproc[(content-directory? [value any/c]) boolean?]{Recognises a ContentDirectory service.}
|
||||
@defproc[(device-content-directory [device upnp-device?]) (or/c #f upnp-service?)]{Returns the device's ContentDirectory service.}
|
||||
@defproc[(content-directory-browse [directory content-directory?]
|
||||
[object-id string?]
|
||||
[#:metadata? metadata? boolean? #f]
|
||||
[#:filter filter string? "*"]
|
||||
[#:start start exact-nonnegative-integer? 0]
|
||||
[#:count count exact-nonnegative-integer? 0]
|
||||
[#:sort sort string? ""])
|
||||
content-result?]{Browses metadata or direct children and returns raw DIDL-Lite plus paging information.}
|
||||
@defproc[(content-directory-search [directory content-directory?]
|
||||
[container-id string?]
|
||||
[search-criteria string?]
|
||||
[#:filter filter string? "*"]
|
||||
[#:start start exact-nonnegative-integer? 0]
|
||||
[#:count count exact-nonnegative-integer? 0]
|
||||
[#:sort sort string? ""])
|
||||
content-result?]{Searches a media server and returns raw DIDL-Lite plus paging information.}
|
||||
|
||||
@section{Result values}
|
||||
|
||||
@defproc[(content-result? [value any/c]) boolean?]{Recognises a ContentDirectory result.}
|
||||
@defproc[(content-result-content [result content-result?]) string?]{Returns the raw DIDL-Lite XML.}
|
||||
@defproc[(content-result-number-returned [result content-result?]) (or/c #f exact-nonnegative-integer?)]{Returns the number of entries in this page.}
|
||||
@defproc[(content-result-total-matches [result content-result?]) (or/c #f exact-nonnegative-integer?)]{Returns the total number of matching entries.}
|
||||
@defproc[(content-result-update-id [result content-result?]) (or/c #f exact-nonnegative-integer?)]{Returns the ContentDirectory update identifier.}
|
||||
@@ -0,0 +1,33 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
(file "../main.rkt")
|
||||
(file "../media-renderer.rkt")
|
||||
(file "../media-server.rkt")
|
||||
(file "../services/av-transport.rkt")
|
||||
(file "../services/rendering-control.rkt")
|
||||
(file "../services/connection-manager.rkt")
|
||||
(file "../services/content-directory.rkt")))
|
||||
|
||||
@title{Introduction}
|
||||
|
||||
The @racketmodname[racket-upnp] collection implements a small UPnP control
|
||||
point. It discovers devices with SSDP, downloads their device descriptions,
|
||||
and represents devices and services as ordinary Racket values. Unknown
|
||||
vendor-specific device and service types are retained instead of discarded.
|
||||
|
||||
The public interface is divided into layers:
|
||||
|
||||
@itemlist[
|
||||
@item{The @racketmodname[racket-upnp] module provides discovery, device
|
||||
information, generic service inspection, and generic SOAP calls.}
|
||||
@item{Modules in the @tt{racket-upnp/services} subcollection provide
|
||||
typed interfaces for standard UPnP services.}
|
||||
@item{The @racketmodname[racket-upnp/media-renderer] and
|
||||
@racketmodname[racket-upnp/media-server] modules provide convenient
|
||||
device-oriented interfaces.}
|
||||
]
|
||||
|
||||
A normal application can use the device-oriented modules without dealing with
|
||||
SSDP, SOAP, service control URLs, or DIDL-Lite XML directly. The generic layer
|
||||
remains available for inspection and vendor-specific extensions.
|
||||
@@ -0,0 +1,103 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
racket/contract
|
||||
(file "../main.rkt")))
|
||||
|
||||
@title{UPnP Devices and Services}
|
||||
|
||||
@defmodule[@racketmodname[racket-upnp] #:module-paths ((file "../main.rkt"))]
|
||||
|
||||
The main module provides general UPnP device discovery and a generic service
|
||||
interface.
|
||||
|
||||
@section{Discovering devices}
|
||||
|
||||
@defproc[(query-upnp-devices
|
||||
[kinds (or/c 'all symbol? (listof symbol?)) 'all]
|
||||
[#:interface interface (or/c #f string?) #f]
|
||||
[#:dns? dns? boolean? #f])
|
||||
(listof upnp-device?)]{
|
||||
Discovers and describes matching UPnP devices.
|
||||
|
||||
@racket['all] returns all described devices. A symbol such as
|
||||
@racket['media-renderer] selects one known kind, and a list selects several
|
||||
kinds. When @racket[interface] is a local IPv4 address, SSDP multicast is sent
|
||||
through that interface. Reverse DNS lookup is only attempted when
|
||||
@racket[dns?] is true.
|
||||
}
|
||||
|
||||
@defproc[(upnp-device-kinds) (listof (cons/c symbol? string?))]{
|
||||
Returns the friendly device kinds understood by @racket[query-upnp-devices],
|
||||
together with short descriptions. Devices with an unrecognised device type
|
||||
are classified as @racket['unknown] and retain their original UPnP type.
|
||||
}
|
||||
|
||||
@section{Device values}
|
||||
|
||||
@defproc[(upnp-device? [value any/c]) boolean?]{Recognises a described UPnP device.}
|
||||
@defproc[(upnp-device-kind [device upnp-device?]) symbol?]{Returns a friendly kind such as @racket['media-renderer], @racket['scanner], or @racket['unknown].}
|
||||
@defproc[(upnp-device-name [device upnp-device?]) string?]{Returns the friendly name, with model name and address as fallbacks.}
|
||||
@defproc[(upnp-device-udn [device upnp-device?]) (or/c #f string?)]{Returns the Unique Device Name from the device description.}
|
||||
@defproc[(upnp-device-address [device upnp-device?]) string?]{Returns the address from which the SSDP response was received.}
|
||||
@defproc[(upnp-device-dns-name [device upnp-device?]) (or/c #f string?)]{Returns the optional reverse-DNS name.}
|
||||
@defproc[(upnp-device-manufacturer [device upnp-device?]) (or/c #f string?)]{Returns the advertised manufacturer.}
|
||||
@defproc[(upnp-device-model [device upnp-device?]) (or/c #f string?)]{Returns a combined model name and model number.}
|
||||
@defproc[(upnp-device-type [device upnp-device?]) (or/c #f string?)]{Returns the original device-type URN.}
|
||||
@defproc[(upnp-device-services [device upnp-device?]) (listof upnp-service?)]{Returns the services belonging directly to the device.}
|
||||
|
||||
@section{Generic services}
|
||||
|
||||
@defproc[(upnp-service? [value any/c]) boolean?]{Recognises a UPnP service.}
|
||||
@defproc[(upnp-service-kind [service upnp-service?]) symbol?]{Returns a friendly service kind or @racket['unknown].}
|
||||
@defproc[(upnp-service-type [service upnp-service?]) (or/c #f string?)]{Returns the original service-type URN.}
|
||||
@defproc[(upnp-service-id [service upnp-service?]) (or/c #f string?)]{Returns the advertised service identifier.}
|
||||
@defproc[(upnp-service-kinds) (listof (cons/c symbol? string?))]{Returns the known friendly service kinds and descriptions.}
|
||||
|
||||
@defproc[(upnp-device-service [device upnp-device?] [kind symbol?])
|
||||
(or/c #f upnp-service?)]{
|
||||
Returns the highest advertised version of the requested service kind belonging
|
||||
to @racket[device], or @racket[#f] when the service is absent.
|
||||
}
|
||||
|
||||
@defproc[(upnp-service-actions [service upnp-service?]) (listof string?)]{
|
||||
Downloads the service's SCPD document and returns its advertised action names.
|
||||
The result is cached for the service value.
|
||||
}
|
||||
|
||||
@defproc[(upnp-service-supports-action? [service upnp-service?]
|
||||
[action (or/c string? symbol?)])
|
||||
boolean?]{
|
||||
Reports whether the SCPD advertises @racket[action].
|
||||
}
|
||||
|
||||
@defproc[(upnp-service-call [service upnp-service?]
|
||||
[action (or/c string? symbol?)]
|
||||
[arguments list? '()])
|
||||
hash?]{
|
||||
Invokes a SOAP action. @racket[arguments] is an association list containing
|
||||
UPnP argument names and values. The immutable result hash uses the exact
|
||||
output argument names as string keys. This function is intended for
|
||||
vendor-specific services and standard services for which no typed module has
|
||||
been written.
|
||||
|
||||
A failed SOAP request raises @racket[exn:fail:upnp?].
|
||||
}
|
||||
|
||||
@defproc[(exn:fail:upnp? [value any/c]) boolean?]{Recognises a UPnP SOAP error.}
|
||||
@defproc[(exn:fail:upnp-code [error exn:fail:upnp?]) (or/c #f exact-integer?)]{Returns the numeric UPnP error code, when supplied by the device.}
|
||||
@defproc[(exn:fail:upnp-description [error exn:fail:upnp?]) (or/c #f string?)]{Returns the UPnP error description, when supplied by the device.}
|
||||
|
||||
@section[#:tag "device-discovery-example"]{Example}
|
||||
|
||||
@racketblock[
|
||||
(define renderers
|
||||
(query-upnp-devices 'media-renderer
|
||||
#:interface "10.7.3.118"
|
||||
#:dns? #t))
|
||||
|
||||
(for ([device (in-list renderers)])
|
||||
(printf "~a (~a)\n"
|
||||
(upnp-device-name device)
|
||||
(upnp-device-address device)))
|
||||
]
|
||||
@@ -0,0 +1,51 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
racket/contract
|
||||
(file "../main.rkt")
|
||||
(file "../media-renderer.rkt")
|
||||
(file "../services/av-transport.rkt")))
|
||||
|
||||
@title{Media Renderer}
|
||||
|
||||
@defmodule[@racketmodname[racket-upnp/media-renderer] #:module-paths ((file "../media-renderer.rkt"))]
|
||||
|
||||
This module hides AVTransport and RenderingControl for common playback code.
|
||||
The returned renderer remains an @racket[upnp-device?], so generic service
|
||||
inspection is still available.
|
||||
|
||||
@defproc[(query-media-renderers [#:interface interface (or/c #f string?) #f]
|
||||
[#:dns? dns? boolean? #f]
|
||||
[#:dlna-only? dlna-only? boolean? #f])
|
||||
(listof upnp-device?)]{
|
||||
Discovers UPnP MediaRenderers. When @racket[dlna-only?] is true, only devices
|
||||
advertising an @tt{X_DLNADOC} value are returned.
|
||||
}
|
||||
|
||||
@defproc[(media-renderer? [value any/c]) boolean?]{Recognises a MediaRenderer device.}
|
||||
@defproc[(media-renderer-dlna? [renderer media-renderer?]) boolean?]{Reports whether the device description advertises a DLNA document identifier.}
|
||||
@defproc[(media-renderer-play-uri! [renderer media-renderer?]
|
||||
[uri string?]
|
||||
[#:metadata metadata string? ""]) void?]{Sets the URI and starts playback.}
|
||||
@defproc[(media-renderer-pause! [renderer media-renderer?]) void?]{Pauses playback.}
|
||||
@defproc[(media-renderer-stop! [renderer media-renderer?]) void?]{Stops playback.}
|
||||
@defproc[(media-renderer-seek! [renderer media-renderer?] [seconds nonnegative-real?]) void?]{Seeks to a relative time.}
|
||||
@defproc[(media-renderer-status [renderer media-renderer?]) symbol?]{Returns the abstracted transport state.}
|
||||
@defproc[(media-renderer-position [renderer media-renderer?]) transport-position?]{Returns current position information.}
|
||||
@defproc[(media-renderer-volume [renderer media-renderer?]) (or/c #f exact-integer?)]{Returns the device-specific volume value.}
|
||||
@defproc[(media-renderer-set-volume! [renderer media-renderer?] [volume (integer-in 0 65535)]) void?]{Sets the device-specific volume value.}
|
||||
@defproc[(media-renderer-muted? [renderer media-renderer?]) boolean?]{Returns the mute state.}
|
||||
@defproc[(media-renderer-set-muted! [renderer media-renderer?] [muted? boolean?]) void?]{Sets the mute state.}
|
||||
|
||||
@section[#:tag "media-renderer-example"]{Example}
|
||||
|
||||
@racketblock[
|
||||
(define renderer
|
||||
(car (query-media-renderers #:interface "10.7.3.118")))
|
||||
|
||||
(media-renderer-play-uri!
|
||||
renderer
|
||||
"http://10.7.3.32:50002/music/track.flac")
|
||||
|
||||
(media-renderer-set-volume! renderer 30)
|
||||
]
|
||||
@@ -0,0 +1,114 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
racket/contract
|
||||
racket/list
|
||||
(file "../main.rkt")
|
||||
(file "../media-server.rkt")))
|
||||
|
||||
@title{Media Server Browser}
|
||||
|
||||
@defmodule[@racketmodname[racket-upnp/media-server] #:module-paths ((file "../media-server.rkt"))]
|
||||
|
||||
This module turns the DIDL-Lite returned by
|
||||
@racketmodname[racket-upnp/services/content-directory] into ordinary Racket
|
||||
values. Containers are browsed one level at a time; the module does not
|
||||
recursively load an entire media library. This is suitable for a browser that
|
||||
requests children when the user expands a container.
|
||||
|
||||
The hierarchy is the logical hierarchy published by the media server. A server
|
||||
may offer views such as artist, album, genre, and physical folder, so a track
|
||||
can occur in more than one container.
|
||||
|
||||
@section{Browsing}
|
||||
|
||||
@defproc[(query-media-servers [#:interface interface (or/c #f string?) #f]
|
||||
[#:dns? dns? boolean? #f])
|
||||
(listof media-server?)]{
|
||||
Discovers UPnP MediaServer devices that provide a ContentDirectory service.
|
||||
}
|
||||
|
||||
@defproc[(media-server? [value any/c]) boolean?]{
|
||||
Recognises a MediaServer device with a ContentDirectory service.
|
||||
}
|
||||
|
||||
@defproc[(media-server-root [server media-server?]
|
||||
[#:start start exact-nonnegative-integer? 0]
|
||||
[#:count count exact-nonnegative-integer? 0])
|
||||
(listof media-entry?)]{
|
||||
Returns the direct children of ContentDirectory object @tt{0}. The optional
|
||||
paging arguments are passed to ContentDirectory. A count of zero asks the
|
||||
server to return all available children, subject to the server's own limits.
|
||||
}
|
||||
|
||||
@defproc[(media-server-browse [server media-server?]
|
||||
[container (or/c string? media-container?) "0"]
|
||||
[#:start start exact-nonnegative-integer? 0]
|
||||
[#:count count exact-nonnegative-integer? 0])
|
||||
(listof media-entry?)]{
|
||||
Returns the direct children of an object identifier or previously returned
|
||||
container.
|
||||
}
|
||||
|
||||
@defproc[(media-container-children [server media-server?]
|
||||
[container media-container?]
|
||||
[#:start start exact-nonnegative-integer? 0]
|
||||
[#:count count exact-nonnegative-integer? 0])
|
||||
(listof media-entry?)]{
|
||||
Convenience form of @racket[media-server-browse] for a container value.
|
||||
}
|
||||
|
||||
@section{Entries}
|
||||
|
||||
@defproc[(media-entry? [value any/c]) boolean?]{Recognises a media container or media item.}
|
||||
@defproc[(media-entry-id [entry media-entry?]) (or/c #f string?)]{Returns the ContentDirectory object identifier.}
|
||||
@defproc[(media-entry-parent-id [entry media-entry?]) (or/c #f string?)]{Returns the parent object identifier.}
|
||||
@defproc[(media-entry-title [entry media-entry?]) string?]{Returns the displayed title.}
|
||||
@defproc[(media-entry-class [entry media-entry?]) (or/c #f string?)]{Returns the original UPnP class, such as @tt{object.item.audioItem.musicTrack}.}
|
||||
@defproc[(media-entry-restricted? [entry media-entry?]) boolean?]{Reports whether the server marks the object as restricted.}
|
||||
|
||||
@defproc[(media-container? [value any/c]) boolean?]{Recognises a browsable container.}
|
||||
@defproc[(media-container-child-count [container media-container?]) (or/c #f exact-nonnegative-integer?)]{Returns the advertised number of children, when present.}
|
||||
@defproc[(media-container-searchable? [container media-container?]) boolean?]{Reports whether the container is advertised as searchable.}
|
||||
|
||||
@defproc[(media-item? [value any/c]) boolean?]{Recognises a media item.}
|
||||
@defproc[(media-item-creator [item media-item?]) (or/c #f string?)]{Returns the Dublin Core creator.}
|
||||
@defproc[(media-item-artists [item media-item?]) (listof string?)]{Returns the advertised artists.}
|
||||
@defproc[(media-item-album [item media-item?]) (or/c #f string?)]{Returns the album title.}
|
||||
@defproc[(media-item-genres [item media-item?]) (listof string?)]{Returns the advertised genres.}
|
||||
@defproc[(media-item-date [item media-item?]) (or/c #f string?)]{Returns the advertised date without imposing a date format.}
|
||||
@defproc[(media-item-album-art-uri [item media-item?]) (or/c #f string?)]{Returns the album-art URI. Relative URIs are resolved against the device-description URL.}
|
||||
@defproc[(media-item-resources [item media-item?]) (listof media-resource?)]{Returns all playable or retrievable resources. One item may advertise several encodings.}
|
||||
|
||||
@section{Resources}
|
||||
|
||||
@defproc[(media-resource? [value any/c]) boolean?]{Recognises a DIDL-Lite resource.}
|
||||
@defproc[(media-resource-uri [resource media-resource?]) string?]{Returns the resource URI, resolved to an absolute URI where possible.}
|
||||
@defproc[(media-resource-protocol-info [resource media-resource?]) (or/c #f string?)]{Returns the complete UPnP @tt{protocolInfo} value.}
|
||||
@defproc[(media-resource-content-type [resource media-resource?]) (or/c #f string?)]{Returns the content-format portion of @tt{protocolInfo}, such as @tt{audio/flac}.}
|
||||
@defproc[(media-resource-size [resource media-resource?]) (or/c #f exact-nonnegative-integer?)]{Returns the size in bytes.}
|
||||
@defproc[(media-resource-duration [resource media-resource?]) (or/c #f nonnegative-real?)]{Returns the duration in seconds.}
|
||||
@defproc[(media-resource-bitrate [resource media-resource?]) (or/c #f exact-nonnegative-integer?)]{Returns the advertised bitrate in bytes per second, as defined by DIDL-Lite.}
|
||||
@defproc[(media-resource-sample-frequency [resource media-resource?]) (or/c #f exact-nonnegative-integer?)]{Returns the sample frequency in hertz.}
|
||||
@defproc[(media-resource-bits-per-sample [resource media-resource?]) (or/c #f exact-nonnegative-integer?)]{Returns the advertised bits per sample.}
|
||||
@defproc[(media-resource-channels [resource media-resource?]) (or/c #f exact-nonnegative-integer?)]{Returns the number of audio channels.}
|
||||
@defproc[(media-resource-resolution [resource media-resource?]) (or/c #f string?)]{Returns an advertised image or video resolution.}
|
||||
|
||||
@section[#:tag "media-server-example"]{Example}
|
||||
|
||||
@racketblock[
|
||||
(define synology
|
||||
(car (query-media-servers #:interface "10.7.3.118")))
|
||||
|
||||
(define root (media-server-root synology))
|
||||
(define music
|
||||
(findf (lambda (entry)
|
||||
(and (media-container? entry)
|
||||
(string=? (media-entry-title entry) "Muziek")))
|
||||
root))
|
||||
|
||||
(for ([entry (in-list (media-container-children synology music))])
|
||||
(printf "~a: ~a\n"
|
||||
(if (media-container? entry) 'container 'item)
|
||||
(media-entry-title entry)))
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@title{racket-upnp}
|
||||
@author{Hans Dijkema}
|
||||
|
||||
@include-section["intro.scrbl"]
|
||||
@include-section["main.scrbl"]
|
||||
@include-section["media-renderer.scrbl"]
|
||||
@include-section["media-server.scrbl"]
|
||||
@include-section["av-transport.scrbl"]
|
||||
@include-section["rendering-control.scrbl"]
|
||||
@include-section["connection-manager.scrbl"]
|
||||
@include-section["content-directory.scrbl"]
|
||||
|
||||
@index-section[]
|
||||
@@ -0,0 +1,31 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
racket/contract
|
||||
(file "../main.rkt")
|
||||
(file "../services/rendering-control.rkt")))
|
||||
|
||||
@title{RenderingControl}
|
||||
|
||||
@defmodule[@racketmodname[racket-upnp/services/rendering-control] #:module-paths ((file "../services/rendering-control.rkt"))]
|
||||
|
||||
RenderingControl manages rendering properties such as volume and mute.
|
||||
|
||||
@defproc[(device-rendering-control [device upnp-device?]) (or/c #f upnp-service?)]{Returns the device's RenderingControl service.}
|
||||
@defproc[(rendering-control? [value any/c]) boolean?]{Recognises a RenderingControl service.}
|
||||
@defproc[(rendering-control-volume [control rendering-control?]
|
||||
[#:channel channel string? "Master"]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0])
|
||||
(or/c #f exact-integer?)]{Returns the device-specific UPnP volume value.}
|
||||
@defproc[(rendering-control-set-volume! [control rendering-control?]
|
||||
[volume (integer-in 0 65535)]
|
||||
[#:channel channel string? "Master"]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0])
|
||||
void?]{Sets the device-specific UPnP volume value. The device's SCPD determines the actual supported maximum.}
|
||||
@defproc[(rendering-control-muted? [control rendering-control?]
|
||||
[#:channel channel string? "Master"]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0]) boolean?]{Returns the mute state.}
|
||||
@defproc[(rendering-control-set-muted! [control rendering-control?]
|
||||
[muted? boolean?]
|
||||
[#:channel channel string? "Master"]
|
||||
[#:instance-id instance-id exact-nonnegative-integer? 0]) void?]{Sets the mute state.}
|
||||
Reference in New Issue
Block a user