Media Indexer
Summary
This pages describes the ongoing work on creating a Media Indexer solution for the LuneOS project. We aim to have an indexer that populates the db8 kinds so they are compatible with legacy db8 kinds. This way we can make sure that legacy apps using Media Indexer will remain functioning. For example when sideloading the legacy com.palm.app.music app, but also 3rd party apps written in Enyo 1/2.
Architecture
We're going to create a single service solution rather than using three different services as legacy webOS did. Furthermore the idea is to write the full service as node.js service.
The service has the following tasks to do:
- watch specific directories for files added/changed/removed
- gather media information about the different files found (ID3 tags, Exif information, ...)
- save all media files as entry in the db8 database
The following node.js modules might be needed:
Db8 kinds and data
Media Indexer
The schemas below detail the layout of media JSON data objects kept in db8 device storage; 3rd party applications can access this data using db8 service calls, principally, find and search.
As with all service calls, developers have the following options:
- You can open a shell on a device through adb shell (actual device) or ssh (emulator) and use luna-send to test out accessing services at the command-line.
- Enyo apps can use PalmService.
- JavaScript apps and services can use Foundation library.
To access media data objects, you need to know the name of an object’s kind. Kind objects in db8 define the indexes and access control for stored JSON data objects. You must specify the kind when accessing data objects of that kind.
The Media Indexer has the following data objects and kinds. Note that the kind names are appended with a version number (i.e., ":1").
Data Type | Kind |
albumimage | com.palm.media.image.album:1 |
album | com.palm.media.audio.album:1 |
artist | com.palm.media.audio.artist:1 |
audio file | com.palm.media.audio.file:1 |
genre | com.palm.media.audio.genre:1 |
image | com.palm.media.image.file:1 |
playlist | com.palm.media.audio.playlist.object:1 |
thumbnail | |
video file | com.palm.media.video.file:1 |
User Permission
When launched, your app must get permission from the user to access media data objects. It can do this using the Media Permissions service.
Note about the 'luna-send 'examples
The luna-send examples shown below for each schema work because I created an app - com.palmdts.enyo.mediaidxr - that went through the process of getting permissions from the user. I then used the impersonate app option (-a com.palmdts.enyo.mediaidxr) to get luna-send to work. You cannot get app permissions using luna-send.
albumimage
Kind: com.palm.media.image.album:1
Schemad
{
"accountId" : string,
"modifiedTime" : number,
"name" : string,
"path" : string,
"searchKey" : string,
"showAlbum" : boolean,
"sortKey" : string,
"thumbnails" : thumbnail array
"toBeDeleted" : string,
"total": {
"images" : int,
"videos" : int
},
"type" : string
}
Elements
Element | Type | Description |
accountId | string | Account ID |
modifiedTime | long | The last time the album was updated in milliseconds since the epoch (Jan 1, Midnight, 1970) |
name | string | Display name for albums (local albums start off as folder name on disk) |
path | string | Path to directory on disk |
searchKey | string | Used for searching |
showAlbum | boolean | Show album flag |
sortKey | string | Used for correct sorting with priority |
thumbnails | thumbnail array | A pre-populated array of up to three thumbnails to use as previews pulled from the first images of the album |
total | inline object | Totals |
images | int | The total number of album images |
videos | int | The total number of album videos |
type | string | Album type |
Example
luna-send
luna-send -n 1 -f -a com.palmdts.enyo.mediaidxr luna://com.palm.db/find ’{"query":{"from":"com.palm.media.image.album:1"}}’
{
"returnValue": true,
"results": [
{
"_id": "++HdXBhUoqw7rwCP",
"_kind": "com.palm.media.image.album:1",
"_rev": 712,
"accountId": "",
"modifiedTime": 1310788496,
"name": "Wallpapers",
"path": "/media/internal/wallpapers",
"searchKey": "Wallpapers",
"showAlbum": true,
"sortKey": "900_Wallpapers",
"thumbnails": [
{
"_id": "2b3",
"data": {
"length": 0,
"offset": 0,
"path": "/media/internal/wallpapers/07.jpg"
},
"type": "embedded"
},
{
"_id": "2b1",
"data": {
"length": 0,
"offset": 0,
"path": "/media/internal/wallpapers/05.jpg"
},
"type": "embedded"
},
{
"_id": "2af",
"data": {
"length": 0,
"offset": 0,
"path": "/media/internal/wallpapers/01.jpg"
},
"type": "embedded"
}
],
"toBeDeleted": "",
"total": {
"images": 11,
"videos": 0
},
"type": "local"
},
]
}
album
Kind: com.palm.media.audio.album:1
Schema
{
"artist" : string,
"genre" : string,
"hasResizedThumbnails" : boolean,
"name" : string,
"serviced" : boolean,
"thumbnails": : thumbnail array,
"total": {
"tracks": int
}
}
Elements
Element | Type | Description |
artist | string | Artist name |
genre | string | Artist name |
hasResizedThumbnails | boolean | Has resized thumbnails flag |
name | string | Album name |
serviced | boolean | Serviced flag |
thumbnails | thumbnail array | Album thumbnails |
total | inline object | See element below |
tracks | int | Total number of tracks on album |
Example
luna-send
luna-send -n 1 -f -a com.palmdts.enyo.mediaidxr luna://com.palm.db/find ’{"query":{"from":"com.palm.media.audio.album:1"}}’
{
"returnValue": true,
"results": [
{
"_id": "++HdYJk8_Y4bg1JF",
"_kind": "com.palm.media.audio.album:1",
"_rev": 985,
"artist": "Muddy Waters",
"genre": "Blues",
"hasResizedThumbnails": false,
"name": "King Bee",
"serviced": false,
"thumbnails": [],
"total": {
"tracks": 1
}
}
]
}
artist
Kind: com.palm.media.audio.artist:1
Schema
[{
"name" : string,
"hasResizedThumbnails" : boolean,
"serviced" : boolean,
"thumbnails" : thumbnail array,
"total" : {
"tracks" : int,
"albums" : int
}
}]
Elements
Element | Type | Description |
name | string | Artist name |
hasResizedThumbnails | boolean | Has resized thumbnails flag |
serviced | boolean | Serviced flag |
thumbnails | thumbnail array | Thumbnails for artist |
total | inline object | See two elements below |
tracks | int | Total number of the artist’s audio tracks on the device |
albums | int | Total number of the artist’s audio albums on the device |
Example
luna-send
luna-send -n 1 -f -a com.palmdts.enyo.mediaidxr luna://com.palm.db/find ’{"query":{"from":"com.palm.media.audio.artist:1"}}’
{
"returnValue": true,
"results": [
{
"_id": "++HdYJkH2p0_n5wU",
"_kind": "com.palm.media.audio.artist:1",
"_rev": 1004,
"hasResizedThumbnails": false,
"name": "Led Zeppelin",
"serviced": false,
"thumbnails": [
<NULL>
],
"total": {
"albums": 1,
"tracks": 3
}
}
]
}
audio file
Kind: com.palm.media.audio.file:1
Schema
{
"album" : string,
"albumArtist" : string,
"artist" : string,
"bookmark" : number,
"createdTime" : number,
"disc": {
"position": int,
"total" : int
},
"duration" : number,
"genre" : string,
"hasResizedThumbnails" : boolean,
"isRingtone" : boolean,
"modifiedTime" : number,
"path" : string,
"searchKey" : string,
"serviced" : boolean,
"size" : number,
"sortKey": {
"albumArtistDiscAndTrack" : string,
"albumDiscAndTrack" : string,
"trackAndDisc" : int
},
"thumbnails" : thumbnail array,
"title" : string,
"track" : {
"position" : int,
"total" : int
}
}
Elements
Element | Type | Description |
album | string | Album name |
albumArtist | string | Album artist |
artist | string | Artist name |
bookmark | number | Bookmark |
createdTime | number | The time this song was created, expressed in seconds elapsed since midnight on January 1, 1970 (epoch) |
disc | inline object | |
position | int | Position on disc |
total | int | Total songs on disc |
duration | number | Duration in seconds |
genre | string | Song genre, i.e., country, blues, etc |
hasResizedThumbnails | boolean | Has resized thumbnails flag |
isRingtone | boolean | Is song a ringtone flag |
modifiedTime | number | Last modified time, in milliseconds since epoch (aka Unix time) |
path | string | Path to song on device |
searchKey | string | Used in searching |
serviced | boolean | Serviced flag |
size | number | File size in bytes |
sortKey | inline object | See three elements below |
albumArtistDiscAndTrack | string | Album artist disc and track |
albumDiscAndTrack | string | Album disc and track |
trackAndDisc | int | Track and disc number |
thumbnails | thumbnail array | Song thumbnails |
title | string | Audio file title |
track | inline object | See elements below |
position | int | Track position |
total | int | Total number of tracks on file’s album |
Example
luna-send
luna-send -n 1 -f -a com.palmdts.enyo.mediaidxr luna://com.palm.db/find ’{"query":{"from":"com.palm.media.audio.file:1"}}’
{
"returnValue":true,
"results":[
{
"_id": "++HdYJjvp8ZbM2qS",
"_kind": "com.palm.media.audio.file:1",
"_rev": 966,
"album": "King Bee",
"albumArtist": "Muddy Waters",
"artist": "Muddy Waters",
"bookmark": 0,
"createdTime": 0,
"disc": {
"position": 1,
"total": 1
},
"duration": 0,
"genre": "Blues",
"hasResizedThumbnails": false,
"isRingtone": false,
"modifiedTime": 1312324182,
"path": "/media/internal/HPMusic/Muddy Waters/King Bee/I’m A King Bee.mp3",
"searchKey": "Muddy Waters King Bee I’m A King Bee",
"serviced": false,
"size": 5555148,
"sortKey": {
"albumArtistDiscAndTrack": "King BeeMuddy Waters100001",
"albumDiscAndTrack": "King Bee100001",
"trackAndDisc": 100001
},
"thumbnails": [
],
"title": "I’m A King Bee",
"track": {
"position": 1,
"total": 0
}
}
]
}
genre
Kind: com.palm.media.audio.genre:1
Schema
{
"hasResizedThumbnails" : boolean,
"name" : string,
"serviced" : boolean,
"thumbnails" : thumbnail array
"total": {
"albums": int,
"tracks": int
}
}
Elements
Element | Type | Description |
hasResizedThumbnails | boolean | Has resized thumbnails flag |
name | string | Genre name |
serviced | boolean | Serviced flag |
thumbnails | thumbnail array | Genre’s thumbnails |
total | inline object | See two elements below |
tracks | int | Genre’s total number of tracks |
albums | int | Genre’s total number of albums |
Example
luna-send
luna-send -n 1 -f -a com.palmdts.enyo.mediaidxr luna://com.palm.db/find ’{"query":{"from":"com.palm.media.audio.genre:1"}}’
{
"returnValue":true,
"results":[
{
"_id":"++HdYJkJC7Fzgqhk",
"_kind":"com.palm.media.audio.genre:1",
"_rev":1017,
"hasResizedThumbnails":false,
"name":"Soul",
"serviced":false,
"thumbnails":[
<NULL>
],
"total":{
"albums":1,
"tracks":3
}
}
]
}
image
Kind: com.palm.media.image.file:1
Schema
{
"albumId" : string,
"albumPath" : string,
"appCacheComplete" : boolean,
"appGridThumbnail" : {
"cached" : boolean,
"dimensions" : {
"original-height" : int,
"original-width" : int,
"output-height" : int,
"output-width" : int
},
"path" : string
},
"createdTime" : number,
"mediaType" : string,
"path" : string,
"thumbnails" : thumbnail array,
"type" : string
}
Elements
Element | Type | Description |
albumId | string | Album ID |
albumPath | string | Path to album on device |
appCacheComplete | boolean | App cache complete flag |
appGridThumbnail | inline object | See fields below |
cached | boolean | Cached flag |
dimensions | inline object | See fields below |
original-height | int | Original height |
original-width | int | Original width |
output-height | int | Output height |
output-width | int | Output width |
path | string | Path |
createdTime | number | The metadata information for the created time in seconds |
mediaType | string | Media type |
path | string | Path |
thumbnails | thumbnail array | Thumbnails for this image |
type | string | Type |
Example
luna-send
luna-send -n 1 -f -a com.palmdts.enyo.mediaidxr luna://com.palm.db/find ’{"query":{"from":"com.palm.media.image.file:1"}}’
{
"returnValue":true,
"results":[
{
"_id":"++HdXBhuwlhB3+Yy",
"_kind":"com.palm.media.image.file:1",
"_rev":739,
"albumId":"++HdXBhUoqw7rwCP",
"albumPath":"/media/internal/wallpapers",
"appCacheComplete":true,
"appGridThumbnail":{
"cached":true,
"dimensions":{
"original-height":1024,
"original-width":1024,
"output-height":200,
"output-width":200
},
"path":"/media/internal/.photosApp/Generated/appGridThumbnail-++HdXBhuwlhB3+Yy-11.jpg"
},
"createdTime":0,
"mediaType":"image",
"path":"/media/internal/wallpapers/11.jpg",
"thumbnails":[
{
"_id":"2a9",
"data":{
"length":0,
"offset":0,
"path":"/media/internal/wallpapers/11.jpg"
},
"type":"embedded"
}
],
"type":"local"
}
]
}
playlist
Kind: com.palm.media.audio.playlist.object:1
Schema
{
"name" : string,
"songIds" : string array,
"thumbnails" : thumbnail array
}
Elements
Element | Required | Type | Description |
name | Yes | string | Playlist name. Not necessarily unique |
songIds | Yes | string array | In order array of db8 IDs of audiofile ("com.palm.media.audio.file:1") objects |
thumbnails | No | thumbnail array | Playlist thumbnails |
thumbnail
Schema
{
"type" : string,
"data" : {
"path" : string,
"offset" : int,
"length" : int
}
"cacheEntry" : {
"pathName" : string,
"aspect" : string,
"width" : int,
"height" : int
}
}
Elements
Element | Type | Description |
type | string | Thumbnail format - "external" or "embedded" (on device) |
data | inline object | See three fields below |
path | string | Location on device |
offset | int | Offset into path where data is contained |
length | int | Length of data in path (requires offset) |
cacheEntry | inline object | See four fields below |
pathName | string | Path determined from filecache/InsertCacheObject |
aspect | string | Aspect used to crop at width/height specified |
width | int | Cache entry width (less than or equal to this value) |
height | int | Cache entry height (less than or equal to this value) |
video file
Kind: com.palm.media.video.file:1
Schema
{
"albumId" : string,
"albumPath" : string,
"appCacheComplete" : boolean,
"appGridThumbnail" : {
"cached" : boolean,
"dimensions" : {
"original-height" : int,
"original-width" : int,
"output-height" : int,
"output-width" : int
},
"path" : string
},
"capturedOnDevice" : boolean,
"createdTime" : number,
"description" : string,
"duration" : number,
"mediaType" : string,
"modifiedTime" : number,
"path" : string,
"playbackPosition" : number,
"searchKey" : string,
"size" : number,
"thumbnails" : thumbnail array,
"title" : string,
"type" : string
}
Elements
Element | Type | Description |
albumId | string | Album ID |
albumPath | string | Path to album on device |
appCacheComplete | boolean | App cache complete flag |
appGridThumbnail | inline object | See fields below |
cached | boolean | Cached flag |
dimensions | inline object | See fields below |
original-height | int | Original height |
original-width | int | Original width |
output-height | int | Output height |
output-width | int | Output width |
path | string | Path |
capturedOnDevice | boolean | Was file captured on device flag |
createdTime | float | The time this video was created, expressed in seconds since midnight on January 1, 1970 (epoch) |
description | string | Video description |
duration | number | Video duration in milliseconds |
mediaType | string | Media type |
modifiedTime | float | The time this video was last modified, expressed in seconds since midnight on January 1, 1970 (epoch) |
path | string | Path on device |
playbackPosition | number | The last playback position in milliseconds |
searchKey | string | Used in searching |
size | int | File size in bytes |
thumbnails | thumbnail array | Video thumbnails |
title | string | Video title |
path | string | Path on device |
Example
luna-send
luna-send -n 1 -f -a com.palmdts.enyo.mediaidxr luna://com.palm.db/find ’{"query":{"from":"com.palm.media.video.file:1"}}’
{
"returnValue": true,
"results": [
{
"_id": "++HdXBgzxh0U_Raw",
"_kind": "com.palm.media.video.file:1",
"_rev": 726,
"albumId": "++HdXBhUxPpa5pdc",
"albumPath": "/media/internal/files",
"appCacheComplete": true,
"appGridThumbnail": {
"cached": true,
"dimensions": {
"original-height": 166,
"original-width": 111,
"output-height": 200,
"output-width": 134
},
"path": "/media/internal/.photosApp/Generated/appGridThumbnail-++HdXBgzxh0U_Raw-HaveFun.jpg"
},
"capturedOnDevice": false,
"createdTime": 1242988599,
"description": "",
"duration": 52.600000,
"mediaType": "video",
"modifiedTime": 1306445850,
"path": "/media/internal/files/HaveFun.mp4",
"playbackPosition": 0,
"searchKey": "Palm Pre",
"size": 6417725,
"thumbnails": [
{
"_id": "205",
"data": "/media/internal/files/HaveFun.mp4:6411842:3835",
"type": "embedded"
}
],
"title": "Palm Pre",
"type": "local"
}
]
}