new dmap atoms

This commit is contained in:
Ron Pedde 2006-03-14 07:28:59 +00:00
parent f0ee070937
commit 5163942322
2 changed files with 289 additions and 261 deletions

View File

@ -233,25 +233,27 @@ DAAP_ITEMS taglist[] = {
/* iTunes 5.0+ */ /* iTunes 5.0+ */
{ 0x01, "ascr", "daap.songcontentrating" }, { 0x01, "ascr", "daap.songcontentrating" },
{ 0x05, "f" "\x8d" "ch", "dmap.haschildcontainers" }, /* wtf - content codes says it's 1 */ { 0x01, "f" "\x8d" "ch", "dmap.haschildcontainers" },
/* iTunes 6.0.2+ */ /* iTunes 6.0.2+ */
{ 0x01, "aeHV", "com.apple.itunes.has-video" }, { 0x01, "aeHV", "com.apple.itunes.has-video" },
/* iTunes 6.0.4+ */ /* iTunes 6.0.4+ */
/* { 0x05, "msas", "dmap.authenticationschemes" },
daap.songcategory { 0x09, "asct", "daap.songcategory" },
daap.songcontentdescription { 0x09, "ascn", "daap.songcontentdescription" },
daap.songkeywords { 0x09, "aslc", "daap.songlongcontentdescription" },
com.apple.itunes.is-podcast { 0x09, "asky", "daap.songkeywords" },
com.apple.itunes.mediakind { 0x01, "apsm", "daap.playlistshufflemode" },
com.apple.itunes.series-name { 0x01, "aprm", "daap.playlistrepeatmode" },
com.apple.itunes.network-name { 0x01, "aePC", "com.apple.itunes.is-podcast" },
com.apple.itunes.episode-num-str { 0x01, "aePP", "com.apple.itunes.is-podcast-playlist" },
com.apple.itunes.episode-sort { 0x01, "aeMK", "com.apple.itunes.mediakind" },
com.apple.itunes.season-num { 0x09, "aeSN", "com.apple.itunes.series-name" },
com.apple.itunes.is-podcast-playlist { 0x09, "aeNN", "com.apple.itunes.network-name" },
*/ { 0x09, "aeEN", "com.apple.itunes.episode-num-str" },
{ 0x05, "aeES", "com.apple.itunes.episode-sort" },
{ 0x05, "aeSU", "com.apple.itunes.season-num" },
/* mt-daapd specific */ /* mt-daapd specific */
{ 0x09, "MSPS", "org.mt-daapd.smart-playlist-spec" }, { 0x09, "MSPS", "org.mt-daapd.smart-playlist-spec" },

View File

@ -118,12 +118,29 @@ DAAP_ITEMS taglist[] = {
{ 0x05, "aeSI", "com.apple.iTunes.itms-songid" }, { 0x05, "aeSI", "com.apple.iTunes.itms-songid" },
{ 0x05, "aeSF", "com.apple.iTunes.itms-storefrontid" }, { 0x05, "aeSF", "com.apple.iTunes.itms-storefrontid" },
/* iTunes 5.0+ */ /* iTunes 5.0+ */
{ 0x01, "ascr", "daap.songcontentrating" }, { 0x01, "ascr", "daap.songcontentrating" },
{ 0x05, "f" "\x8d" "ch", "dmap.haschildcontainers" }, /* wtf - content codes says it's 1 */ { 0x01, "f" "\x8d" "ch", "dmap.haschildcontainers" }, /* was 5? */
/* iTunes 6.0.2+ */ /* iTunes 6.0.2+ */
{ 0x01, "aeHV", "com.apple.itunes.has-video" }, { 0x01, "aeHV", "com.apple.itunes.has-video" },
/* iTunes 6.0.4+ */
{ 0x05, "msas", "dmap.authenticationschemes" },
{ 0x09, "asct", "daap.songcategory" },
{ 0x09, "ascn", "daap.songcontentdescription" },
{ 0x09, "aslc", "daap.songlongcontentdescription" },
{ 0x09, "asky", "daap.songkeywords" },
{ 0x01, "apsm", "daap.playlistshufflemode" },
{ 0x01, "aprm", "daap.playlistrepeatmode" },
{ 0x01, "aePC", "com.apple.itunes.is-podcast" },
{ 0x01, "aePP", "com.apple.itunes.is-podcast-playlist" },
{ 0x01, "aeMK", "com.apple.itunes.mediakind" },
{ 0x09, "aeSN", "com.apple.itunes.series-name" },
{ 0x09, "aeNN", "com.apple.itunes.network-name" },
{ 0x09, "aeEN", "com.apple.itunes.episode-num-str" },
{ 0x05, "aeES", "com.apple.itunes.episode-sort" },
{ 0x05, "aeSU", "com.apple.itunes.season-num" },
/* mt-daapd specific */ /* mt-daapd specific */
{ 0x09, "MSPS", "org.mt-daapd.smart-playlist-spec" }, { 0x09, "MSPS", "org.mt-daapd.smart-playlist-spec" },
@ -140,13 +157,13 @@ int lookup_tag(char *tag, char *descr, int *type) {
DAAP_ITEMS *current = taglist; DAAP_ITEMS *current = taglist;
while((current->tag) && (strcasecmp(current->tag,tag))) { while((current->tag) && (strcasecmp(current->tag,tag))) {
current++; current++;
} }
if(current->tag) { if(current->tag) {
strcpy(descr,current->description); strcpy(descr,current->description);
*type = current->type; *type = current->type;
return 1; return 1;
} }
return 0; return 0;
@ -163,124 +180,133 @@ int decode_tag(FILE *fout, char *current, int level, int len) {
char templine[4096]; char templine[4096];
while(len) { while(len) {
memset(tag,0,sizeof(tag)); memset(tag,0,sizeof(tag));
memcpy(tag,current,4); memcpy(tag,current,4);
current += 4; current += 4;
len -= 4; len -= 4;
memcpy((char*)&subtag_len,current,4); memcpy((char*)&subtag_len,current,4);
current += 4; current += 4;
len -= 4; len -= 4;
if(lookup_tag(tag,descr,&type)) { if(lookup_tag(tag,descr,&type)) {
memset(line,' ',sizeof(line)); memset(line,' ',sizeof(line));
sprintf((char*)&line[level * 2],"%02x %s (%s) - ", sprintf((char*)&line[level * 2],"%02x %s (%s) - ",
type,tag,descr); type,tag,descr);
switch(type) { switch(type) {
case 0x01: /* byte */ case 0x01: /* byte */
case 0x02: /* unsigned byte */ case 0x02: /* unsigned byte */
if(subtag_len != 1) { if(subtag_len != 1) {
printf("Foo! %s should have tag len 1, has %d\n", printf("Foo! %s should have tag len 1, has %d\n",
tag,subtag_len); tag,subtag_len);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
sprintf(templine,"%02x (%d)\n",*((char*)current),(int)(*((char*)current))); sprintf(templine,"%02x (%d)\n",*((char*)current),(int)(*((char*)current)));
current += 1; current += 1;
len -= 1; len -= 1;
break; break;
case 0x03: case 0x03:
if(subtag_len != 2) { if(subtag_len != 2) {
printf("Foo! %s should have tag len 2, has %d\n", printf("Foo! %s should have tag len 2, has %d\n",
tag,subtag_len); tag,subtag_len);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
sprintf(templine,"%02x %d\n",*((short int*)current),(int)(*((short int *)current))); sprintf(templine,"%02x %d\n",*((short int*)current),(int)(*((short int *)current)));
current += 2; current += 2;
len -= 2; len -= 2;
break; break;
break; break;
case 0x0A: case 0x0A:
case 0x05: case 0x05:
if(subtag_len != 4) { if(subtag_len != 4) {
printf("Foo! %s should have tag len 4, has %d\n", printf("Foo! %s should have tag len 4, has %d\n",
tag,subtag_len); tag,subtag_len);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
sprintf(templine,"%04x (%d)\n",*((int*)current),*((int*)current)); if(strcmp(tag,"mcnm") == 0) {
current += 4; sprintf(templine,"%c%c%c%c (%04x)\n",
len -= 4; *((char*)current),
break; *((char*)current+1),
*((char*)current+2),
*((char*)current+3),
*((int*)current));
} else {
sprintf(templine,"%04x (%d)\n",*((int*)current),*((int*)current));
}
current += 4;
len -= 4;
break;
case 0x07: case 0x07:
if(subtag_len != 8) { if(subtag_len != 8) {
printf("Foo! %s should have tag len 8, has %d\n", printf("Foo! %s should have tag len 8, has %d\n",
tag,subtag_len); tag,subtag_len);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
sprintf(templine,"%04x%04x (%lu)\n",*((int*)current),*((int*)current+4),*((long long*)current)); sprintf(templine,"%04x%04x (%lu)\n",*((int*)current),*((int*)current+4),*((long long*)current));
current += 8; current += 8;
len -= 8; len -= 8;
break; break;
case 0x09: case 0x09:
if(subtag_len == 0) { if(subtag_len == 0) {
strcpy(templine,"(empty)\n"); strcpy(templine,"(empty)\n");
} else { } else {
memset(templine,0,sizeof(templine)); memset(templine,0,sizeof(templine));
memcpy(templine,current,subtag_len); memcpy(templine,current,subtag_len);
strcat(templine,"\n"); strcat(templine,"\n");
} }
current += subtag_len; current += subtag_len;
len -= subtag_len; len -= subtag_len;
break; break;
case 0x0B: case 0x0B:
if(subtag_len != 4) { if(subtag_len != 4) {
printf("Foo! %s should have tag len 4, has %d\n", printf("Foo! %s should have tag len 4, has %d\n",
tag,subtag_len); tag,subtag_len);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
tempint = *((int*)current); tempint = *((int*)current);
sprintf(templine,"%d.%d\n",tempint >> 16 & 0xFFFF, sprintf(templine,"%d.%d\n",tempint >> 16 & 0xFFFF,
tempint & 0xFFFF); tempint & 0xFFFF);
current += 4; current += 4;
len -= 4; len -= 4;
break; break;
case 0x0C: case 0x0C:
sprintf(templine,"<container>\n"); sprintf(templine,"<container>\n");
break; break;
default: default:
printf("Foo! Bad tag: type %d\n",type); printf("Foo! Bad tag: type %d\n",type);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
fprintf(fout,"%s%s",line,templine); fprintf(fout,"%s%s",line,templine);
if(type == 0x0c) { if(type == 0x0c) {
if(decode_tag(fout, current,level+1,subtag_len)) { if(decode_tag(fout, current,level+1,subtag_len)) {
current += subtag_len; current += subtag_len;
len -= subtag_len; len -= subtag_len;
} else { } else {
return 0; return 0;
} }
} }
} else { } else {
printf("Bad tag: %s (%02x%02x%02x%02x)\n",tag,(unsigned char)tag[0],(unsigned char)tag[1], printf("Bad tag: %s (%02x%02x%02x%02x)\n",tag,(unsigned char)tag[0],(unsigned char)tag[1],
(unsigned char)tag[2],(unsigned char)tag[3]); (unsigned char)tag[2],(unsigned char)tag[3]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
return 0; return 0;
} }
} }
@ -297,7 +323,7 @@ void decode_dmap(int conv, char *uncompressed, long uncompressed_size) {
fout=fopen(buffer,"w"); fout=fopen(buffer,"w");
if(!decode_tag(fout,uncompressed,0,uncompressed_size)) { if(!decode_tag(fout,uncompressed,0,uncompressed_size)) {
printf("Foo! All screwed up!\n"); printf("Foo! All screwed up!\n");
} }
fclose(fout); fclose(fout);
} }
@ -309,16 +335,16 @@ int readline(int fd, char *buffer) {
current=buffer; current=buffer;
while(read(fd,&inchar,1) == 1) { while(read(fd,&inchar,1) == 1) {
switch(inchar) { switch(inchar) {
case '\r': case '\r':
break; break;
case '\n': case '\n':
*current='\0'; *current='\0';
return 0; return 0;
default: default:
*current++ = inchar; *current++ = inchar;
break; break;
} }
} }
return -1; return -1;
@ -352,148 +378,148 @@ int main(int argc, char *argv[]) {
int dmap=0; int dmap=0;
while((option=getopt(argc, argv, "d")) != -1) { while((option=getopt(argc, argv, "d")) != -1) {
switch(option) { switch(option) {
case 'd': case 'd':
dmap=1; dmap=1;
break; break;
default: default:
usage(); usage();
break; break;
} }
} }
if(optind == argc) { if(optind == argc) {
usage(); usage();
} }
fd=open(argv[optind],O_RDONLY); fd=open(argv[optind],O_RDONLY);
if(fd == -1) { if(fd == -1) {
perror("open"); perror("open");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(dmap) { if(dmap) {
out=fdopen(STDOUT_FILENO,"w"); out=fdopen(STDOUT_FILENO,"w");
uncompressed_size=lseek(fd,0,SEEK_END); uncompressed_size=lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET); lseek(fd,0,SEEK_SET);
uncompressed=(char*)malloc(uncompressed_size); uncompressed=(char*)malloc(uncompressed_size);
read(fd,uncompressed,uncompressed_size); read(fd,uncompressed,uncompressed_size);
decode_tag(out,uncompressed,0,uncompressed_size); decode_tag(out,uncompressed,0,uncompressed_size);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
while(!done) { while(!done) {
/* read in the headers */ /* read in the headers */
is_compressed=0; is_compressed=0;
printf("Reading headers for conv %d\n",conversation); printf("Reading headers for conv %d\n",conversation);
while(1) { while(1) {
if(readline(fd,buffer)) { if(readline(fd,buffer)) {
done=1; done=1;
break; break;
} }
printf("got %s\n",buffer); printf("got %s\n",buffer);
if(!strlen(buffer)) if(!strlen(buffer))
break; break;
if(strncasecmp(buffer,"Content-Encoding:",17) == 0) { if(strncasecmp(buffer,"Content-Encoding:",17) == 0) {
loc=buffer+17; loc=buffer+17;
while(*loc==' ') { while(*loc==' ') {
loc++; loc++;
} }
if(strncasecmp(loc,"gzip",4) == 0) { if(strncasecmp(loc,"gzip",4) == 0) {
is_compressed=1; is_compressed=1;
} }
} }
if(strncasecmp(buffer,"Content-Length:",15) == 0) { if(strncasecmp(buffer,"Content-Length:",15) == 0) {
compressed_size=atol((char*)&buffer[15]); compressed_size=atol((char*)&buffer[15]);
printf("Size of conv %d is %d\n",conversation,compressed_size); printf("Size of conv %d is %d\n",conversation,compressed_size);
} }
} }
if(done) if(done)
break; break;
printf("Headers complete for conversation %d\n",conversation); printf("Headers complete for conversation %d\n",conversation);
printf("Flow %s compressed\n",is_compressed ? "IS" : "IS NOT"); printf("Flow %s compressed\n",is_compressed ? "IS" : "IS NOT");
uncompressed_size = 10 * compressed_size; uncompressed_size = 10 * compressed_size;
compressed=(char*)malloc(compressed_size); compressed=(char*)malloc(compressed_size);
uncompressed=(char*)malloc(uncompressed_size); uncompressed=(char*)malloc(uncompressed_size);
if((!compressed) || (!uncompressed)) { if((!compressed) || (!uncompressed)) {
perror("malloc"); perror("malloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(read(fd,compressed,compressed_size) != compressed_size) { if(read(fd,compressed,compressed_size) != compressed_size) {
perror("read"); perror("read");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* dump the compressed data */ /* dump the compressed data */
sprintf(file,"compressed.%d",conversation); sprintf(file,"compressed.%d",conversation);
out_fd=open(file,O_CREAT | O_RDWR,0666); out_fd=open(file,O_CREAT | O_RDWR,0666);
if(out_fd == -1) { if(out_fd == -1) {
perror("open"); perror("open");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
write(out_fd,compressed,compressed_size); write(out_fd,compressed,compressed_size);
close(out_fd); close(out_fd);
if(is_compressed) { if(is_compressed) {
sprintf(file,"/sw/bin/zcat compressed.%d",conversation); sprintf(file,"/sw/bin/zcat compressed.%d",conversation);
stream=popen(file,"r"); stream=popen(file,"r");
if(!stream) { if(!stream) {
perror("popen"); perror("popen");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
err=fread(uncompressed,1,uncompressed_size,stream); err=fread(uncompressed,1,uncompressed_size,stream);
if(err == -1) { if(err == -1) {
perror("fread"); perror("fread");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(err == uncompressed_size) { if(err == uncompressed_size) {
printf("Error: buffer too small\n"); printf("Error: buffer too small\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
uncompressed_size = err; uncompressed_size = err;
pclose(stream); pclose(stream);
} else { } else {
uncompressed_size=compressed_size; uncompressed_size=compressed_size;
memcpy(uncompressed,compressed,compressed_size); memcpy(uncompressed,compressed,compressed_size);
} }
/* dump the uncompressed data */ /* dump the uncompressed data */
sprintf(file,"uncompressed.%d",conversation); sprintf(file,"uncompressed.%d",conversation);
out_fd=open(file,O_CREAT | O_RDWR,0666); out_fd=open(file,O_CREAT | O_RDWR,0666);
if(out_fd == -1) { if(out_fd == -1) {
perror("open"); perror("open");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
write(out_fd,uncompressed,uncompressed_size); write(out_fd,uncompressed,uncompressed_size);
close(out_fd); close(out_fd);
printf("Uncompressed size: %d\n",uncompressed_size); printf("Uncompressed size: %d\n",uncompressed_size);
/* now decode and print */ /* now decode and print */
decode_dmap(conversation, uncompressed, uncompressed_size); decode_dmap(conversation, uncompressed, uncompressed_size);
free(compressed); free(compressed);
free(uncompressed); free(uncompressed);
conversation++; conversation++;
} }
printf("Done"); printf("Done");