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:


 * https://github.com/mapbox/node-sqlite3
 * https://github.com/nikhilm/node-taglib

=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").

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 

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 

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 

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 

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 

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 

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 

thumbnail

Schema

{

"type" : string,

"data" : {

"path"  : string,

"offset" : int,

"length" : int

}

"cacheEntry" : {

"pathName" : string,

"aspect"  : string,

"width"   : int,

"height"  : int

}

}

Elements 

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 

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"

}

]

}