Skip to content

Commit

Permalink
Merge branch 'scd'
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonChisholm committed Jun 23, 2017
2 parents f16a94d + 50d94ab commit 43ac429
Show file tree
Hide file tree
Showing 42 changed files with 5,915 additions and 31 deletions.
1 change: 1 addition & 0 deletions OpenHome/Av/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace OpenHome {
#define kSources kApplication3
#define kSongcast kApplication4
#define kVolume kApplication15
#define kScd kApplication24

} // namespace OpenHome

241 changes: 241 additions & 0 deletions OpenHome/Av/Scd/Receiver/OhMetadata.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
#include <OpenHome/Av/Scd/Receiver/OhMetadata.h>
#include <OpenHome/Types.h>
#include <OpenHome/Buffer.h>
#include <OpenHome/Av/Scd/ScdMsg.h>
#include <OpenHome/Media/Pipeline/Msg.h>
#include <OpenHome/Private/Ascii.h>
#include <OpenHome/Private/Converter.h>
#include <OpenHome/Private/Stream.h>

namespace OpenHome {
namespace Scd {

class Oh2DidlTagMapping
{
public:
Oh2DidlTagMapping(const TChar* aOhKey, const TChar* aDidlTag, const OpenHome::Brx& aNs)
: iOhKey(aOhKey)
, iDidlTag(aDidlTag)
, iNs(aNs)
, iRole(OpenHome::Brx::Empty())
{}
Oh2DidlTagMapping(const TChar* aOhKey, const TChar* aDidlTag, const OpenHome::Brx& aNs, const TChar* aRole)
: iOhKey(aOhKey)
, iDidlTag(aDidlTag)
, iNs(aNs)
, iRole(aRole)
{}
public:
Brn iOhKey;
Brn iDidlTag;
Brn iNs;
Brn iRole;
};

} // namespace Scd
} // namespace OpenHome

using namespace OpenHome;
using namespace OpenHome::Scd;

const Brn OhMetadata::kNsDc("dc=\"http://purl.org/dc/elements/1.1/\"");
const Brn OhMetadata::kNsUpnp("upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\"");
const Brn OhMetadata::kNsOh("oh=\"http://www.openhome.org\"");


Media::Track* OhMetadata::ToTrack(const OpenHomeMetadataBuf& aMetadata,
Media::TrackFactory& aTrackFactory)
{ // static
OhMetadata self(aMetadata);
try {
self.Parse();
}
catch (BufferOverflow&) {
self.iMetaDataDidl.Replace(Brx::Empty());
}
return aTrackFactory.CreateTrack(self.iUri, self.iMetaDataDidl);
}

void OhMetadata::ToDidlLite(const OpenHomeMetadataBuf& aMetadata, Bwx& aDidl)
{ // static
OhMetadata self(aMetadata);
try {
self.Parse();
aDidl.Replace(self.iMetaDataDidl);
}
catch (BufferOverflow&) {
aDidl.Replace(Brx::Empty());
}
}

OhMetadata::OhMetadata(const OpenHomeMetadataBuf& aMetadata)
: iMetadata(aMetadata)
{
}

void OhMetadata::Parse()
{
static const Oh2DidlTagMapping kOh2Didl[] = {
{ "artist", "upnp:artist", kNsUpnp },
{ "albumArtist", "upnp:artist", kNsUpnp, "AlbumArtist" },
{ "composer", "upnp:artist", kNsUpnp, "composer" },
{ "conductor", "upnp:artist", kNsUpnp, "conductor" },
{ "narrator", "upnp:artist", kNsUpnp, "narrator" },
{ "performer", "upnp:artist", kNsUpnp, "performer" },
{ "genre", "upnp:genre", kNsUpnp },
{ "albumGenre", "upnp:genre", kNsUpnp },
{ "author", "dc:author", kNsDc },
{ "title", "dc:title", kNsDc },
{ "year", "dc:date", kNsDc },
{ "albumTitle", "upnp:album", kNsUpnp },
{ "albumArtwork", "upnp:albumArtURI", kNsUpnp },
{ "provider", "oh:provider", kNsOh },
{ "artwork", "oh:artwork", kNsOh },
{ "track", "upnp:originalTrackNumber", kNsUpnp },
{ "tracks", "oh:originalTrackCount", kNsOh },
{ "disc", "oh:originalDiscNumber", kNsOh },
{ "discs", "oh:originalDiscCount", kNsOh },
{ "work", "oh:work", kNsOh },
{ "movement", "oh:movement", kNsOh },
{ "show", "oh:show", kNsOh },
{ "episode", "oh:episodeNumber", kNsOh },
{ "episodes", "oh:episodeCount", kNsOh },
{ "published", "oh:published", kNsOh },
{ "website", "oh:website", kNsOh },
{ "location", "oh:location", kNsOh },
{ "details", "oh:details", kNsOh },
{ "extensions", "oh:extensions", kNsOh },
{ "publisher", "dc:publisher", kNsDc },
{ "rating", "upnp:rating", kNsUpnp }
};
static const TUint kNumOh2DidlMappings = sizeof kOh2Didl / sizeof kOh2Didl[0];

iUri.Replace(Brx::Empty());
iMetaDataDidl.Replace(Brx::Empty());

Brn val;
if (TryGetValue("uri", val)) {
iUri.Replace(val);
}

TryAppend("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
TryAppend("<DIDL-Lite xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\">");
TryAppend("<item");
TryAddAttribute("id", "id");
TryAppend(" parentID=\"-1\" restricted=\"1\">");
for (TUint i=0; i<kNumOh2DidlMappings; i++) {
auto& mapping = kOh2Didl[i];
TryAddTag(mapping.iOhKey, mapping.iDidlTag, mapping.iNs, mapping.iRole);
}
TryAppend("<res");
if (TryGetValue("duration", val)) {
TryAppend(" duration=\"");
TUint duration = Ascii::Uint(val);
const TUint secs = duration % 60;
duration /= 60;
const TUint mins = duration % 60;
const TUint hours = duration / 60;
Bws<32> formatted;
formatted.AppendPrintf("%u:%02u:%02u.000", hours, mins, secs);
TryAppend(formatted);
TryAppend("\"");
}
if (TryGetValue("bitRate", val)) {
TryAppend(" bitrate=\"");
TUint bitRate = Ascii::Uint(val);
bitRate /= 8; // DIDL-Lite bitrate attribute actually refers to a byte rate!
Bws<Ascii::kMaxUintStringBytes> brBuf;
(void)Ascii::AppendDec(brBuf, bitRate);
TryAppend(brBuf);
TryAppend("\"");
}
TryAddAttribute("bitDepth", "bitsPerSample");
TryAddAttribute("sampleRate", "sampleFrequency");
TryAddAttribute("channels", "nrAudioChannels");
TryAddAttribute("mimeType", "protocolInfo");
TryAppend(">");
if (iUri.Bytes() > 0) {
WriterBuffer writer(iMetaDataDidl);
Converter::ToXmlEscaped(writer, iUri);
}
TryAppend("</res>");
if (TryGetValue("type", val)) {
TryAddTag(Brn("upnp:class"), kNsUpnp, Brx::Empty(),
Brn("object.item.audioItem.musicTrack"));
}
TryAppend("</item>");
TryAppend("</DIDL-Lite>");
}

TBool OhMetadata::TryGetValue(const TChar* aKey, Brn& aValue) const
{
Brn key(aKey);
return TryGetValue(key, aValue);
}

TBool OhMetadata::TryGetValue(const Brx& aKey, Brn& aValue) const
{
for (auto kvp : iMetadata) {
if (kvp.first== aKey) {
aValue.Set(kvp.second);
return true;
}
}
return false;
}

void OhMetadata::TryAddAttribute(const TChar* aOhKey, const TChar* aDidlAttr)
{
Brn key(aOhKey);
Brn val;
if (TryGetValue(key, val)) {
TryAppend(" ");
TryAppend(aDidlAttr);
TryAppend("=\"");
TryAppend(val);
TryAppend("\"");
}
}

void OhMetadata::TryAddTag(const Brx& aOhKey, const Brx& aDidlTag,
const Brx& aNs, const Brx& aRole)
{
Brn key(aOhKey);
Brn val;
if (TryGetValue(key, val)) {
TryAppendTag(aDidlTag, aNs, aRole, val);
}
}

void OhMetadata::TryAppendTag(const Brx& aDidlTag, const Brx& aNs,
const Brx& aRole, const Brx& aValue)
{
TryAppend("<");
TryAppend(aDidlTag);
TryAppend(" xmlns:");
TryAppend(aNs);
if (aRole.Bytes() > 0) {
TryAppend(" role=\"");
TryAppend(aRole);
TryAppend("\"");
}
TryAppend(">");
WriterBuffer writer(iMetaDataDidl);
Converter::ToXmlEscaped(writer, aValue);
TryAppend("</");
TryAppend(aDidlTag);
TryAppend(">");
}

void OhMetadata::TryAppend(const TChar* aStr)
{
Brn buf(aStr);
TryAppend(buf);
}

void OhMetadata::TryAppend(const Brx& aBuf)
{
if (!iMetaDataDidl.TryAppend(aBuf)) {
THROW(BufferOverflow);
}
}
40 changes: 40 additions & 0 deletions OpenHome/Av/Scd/Receiver/OhMetadata.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <OpenHome/Types.h>
#include <OpenHome/Buffer.h>
#include <OpenHome/Private/Standard.h>
#include <OpenHome/Av/Scd/ScdMsg.h>
#include <OpenHome/Media/Pipeline/Msg.h>

namespace OpenHome {
namespace Scd {

class OhMetadata : private INonCopyable
{
static const Brn kNsDc;
static const Brn kNsUpnp;
static const Brn kNsOh;
public:
static Media::Track* ToTrack(const OpenHomeMetadataBuf& aMetadata,
Media::TrackFactory& aTrackFactory);
static void ToDidlLite(const OpenHomeMetadataBuf& aMetadata, Bwx& aDidl);
private:
OhMetadata(const OpenHomeMetadataBuf& aMetadata);
void Parse();
TBool TryGetValue(const TChar* aKey, Brn& aValue) const;
TBool TryGetValue(const Brx& aKey, Brn& aValue) const;
void TryAddAttribute(const TChar* aOhKey, const TChar* aDidlAttr);
void TryAddTag(const Brx& aOhKey, const Brx& aDidlTag,
const Brx& aNs, const Brx& aRole);
void TryAppendTag(const Brx& aDidlTag, const Brx& aNs,
const Brx& aRole, const Brx& aValue);
void TryAppend(const TChar* aStr);
void TryAppend(const Brx& aBuf);
private:
const OpenHomeMetadataBuf& iMetadata;
Media::BwsTrackUri iUri;
Media::BwsTrackUri iMetaDataDidl;
};

} // namespace Scd
} // namespace OpenHome

0 comments on commit 43ac429

Please sign in to comment.