Section: User Contributed Perl Documentation (3)
Updated: 2004-09-01


Net::DAAP::DMAP - Perl module for reading and writing DAAP structures 


  use Net::DAAP::DMAP qw(:all);  $hash_ref = dmap_to_hash_ref($dmap);       # crude  $array_ref = dmap_to_array_ref($dmap);     # crude  $array_ref = dmap_unpack($dmap);           # knows about data types  $node      = dmap_seek($array_ref, $path);  $flattened = dmap_flatten($array_ref);     # convert to path = data formta  $flat_list = dmap_flat_list($array_ref);   # convert to [ path, data ] format  $xml       = dmap_to_xml($dmap);           # convert to XML fragment  $dmap      = dmap_pack($dmap);             # convert to DMAP packet  update_content_codes($unpacked_content_codes_response);




Until 2.0, I reserve the right to change the interface. Inparticular, I think "dmap_flatten", "dmap_to_hash_ref", and"dmap_to_array_ref" are likely to disappear. And I suspect the hivebrain of Perl can come up with a better data structure than I have. 

Back to the Description

A DMAP structure is a binary record used in Apple's DAAP protocol. ADMAP structure may contain other DMAP structures. Fields in a DMAPstructure are identified by a short name (``msdc''). The short name iswhat's in the binary record, but a content codes list gives a longname (``dmap.databasescount'') and a data type for the record (32-bitinteger).

A parsed DMAP structure is built out of arrays. For example:

  [    [      'dmap.loginresponse',      [         [           'dmap.status',           200         ],         [           'dmap.sessionid',            2393         ]      ]    ]  ]

("dmap_unpack" returns this kind of structure)

There are two rules here: a field is wrapped in an array, anda container's values are wrapped in an array. So the structureis programmatically built as:

  $status_field = [ 'dmap.status', 200 ];  $session_id_field = [ 'dmap.sessionid', 2393 ];  $response_value = [ $status_field, $session_id_field ];  $login_response_field = [ 'dmap.loginresponse', $response_value ];  $entire_response = [ $login_response_field ];

The outer array is necessary because not every response has only onetop-level container as this does.

In XML you'd write the response as:

  <dmap.loginresponse>      <dmap.status>200</dmap.status>      <dmap.sessionid>2393</dmap.sessionid>  </dmap.loginresponse>

This is what "dmap_to_xml" returns.

A much more convenient structure for representing this data wouldbe:

  {    'dmap.loginresponse' => {      { 'dmap.status' => 200,        'dmap.sessionid' => 2393,      },  }

This is the output of "dmap_to_hash_ref", but beware! This isn'tsuitable for every response. The hash is indexed by field name and astructure may contain many elements of the same name. For example,requesting the content codes list gives you a list of records thathave the field name "dmap.dictionary".

The array structure returned by "dmap_to_array_ref" is complex, butthe "dmap_seek" function makes it easier. This takes a structure anda path expressed as a slash-separated list of field names:


The return value is the the value of the first "dmap.sessionid" foundin the first "dmap.loginresponse" structure. In the case of thesample record above, it would be 2393.

Another way to handle these complex arrays is to "dmap_flatten" them.This returns an array of "path = value" lines, where path isa slash-separated path. For example:

  [    '/dmap.loginresponse/dmap.status = 200',    '/dmap.loginresponse/dmap.sessionid = 2393'  ]

You can use "grep" and regexps to find data if that's the way yourmind works.

"dmap_flatten" has a similar looking cousin called "dmap_flat_list",which returns an array of "path => value" pairs. For example:

  [    '/dmap.loginresponse/dmap.status' => 200,    '/dmap.loginresponse/dmap.sessionid' => 2393,  ]

You can then turn this into a hash (which may of course lose you thefirst elements), or iterate over it in pairs, if that's easier.

You can, but don't have to, update the tables of field names (``contentcodes'') and data types. DAAP offers a request that returns a packetof content codes. Feed that packet to "update_content_codes". 

Implementation Details

It's all implementation details. Here are the various data types.

 1, 3, 5, 7 = ints, size 8,16,32,64 bit 9 = string, 10 = time_t-style time 11 = version (two 16-bit ints, I think) 12 = container

This uses Math::BigInt for 64-bit quantities, as not every platformhas 64-bit int support available.

There's no support for types 2, 4, 6, 8 yet because nobody'd foundexamples of them in the field: are they endian changes, or signednesschanges. The assumption is that all numbers are unsigned (why allowthe possibility of a negative number of songs?). 


Nathan Torkington, <nathan AT>. For support, join theDAAP developers mailing list by sending mail to <daap-dev-subscribe>.

Richard Clamp <> is the current maintainer, andtook over in July 2004.



Back to the Description
Implementation Details

This document was created byman2html,using the manual pages.