#ifndef MPLE_H #define MPLE_H #include /* I hate include files that aren't self-contained */ #include #include #include #include #include #include #define DEFAULT_PB_TEMPLATE "%s/esys/pblist%d.dat" #define DEFAULT_MP_TEMPLATE "%s/esys/nw-mp3/mp%04x.dat" #define DEFAULT_MASTER_PBLIST 1 #define MAX_TRACKS 40000 /* according to the manual */ /* On-disk data structures and magic */ #define PBLIST_MAGIC "\x00\x03\xce\xa0" #define MPDAT_MAGIC "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" /* This is used to find likely devices in HAL */ #define HAL_MAGIC "NETWORK WALKMAN" /* Header structure from pblist file [incomplete] */ typedef struct { guint8 signature[8]; /* "WMPLESYS", hence the name of the module */ guint32 timestamp; /* ctime of the ESYS folder */ guint32 msn; /* media serial number */ guint32 magic; /* no idea what this is */ guint32 folders; /* #folders */ guint32 tracks; /* number of tracks on the device */ /* XORing the header 32 bits at a time should result in this checksum, or XORing including this should result in zero */ guint32 checksum; /* XOR checksum */ } pblist_hdr; /* folder descriptor. complete. */ typedef struct { guint16 foldername[126]; /* name of this folder */ guint32 offset; /* offset from start of pblist file to track list */ } pblist_folder; #define FOLDER_OFFSET(x) (((pblist_folder *)x)->offset) /* track pointer in pblist. complete. */ typedef struct { guint16 filename[128]; guint16 title[128]; guint16 artist[128]; } pblist_track; /* Header structure from mp*.dat file. complete. */ typedef struct { guint8 signature[4]; /* "WMMP" */ guint32 size; /* size of file in bytes */ guint32 time; /* time in milliseconds */ guint32 frames; /* number of MP3 frames */ guint32 msn; /* media serial number */ guint8 magic[12]; } mpdat_hdr; /* and now, structures for passing the data around */ typedef enum _mple_aux_data { MPLE_MSN = 1, MPLE_TS = 2, MPLE_MAGIC = 4, } mple_aux_data; /* PRUNE ME */ typedef struct _mple_device { nw_device_t devdata; /* NW common data */ /* auxilliary information */ mple_aux_data aux; /* whether this data is valid */ guint32 msn; /* media serial number */ time_t timestamp; /* timestamp from master pblist, converted to time_t */ guint32 magic; /* magic from pblist file */ /* where to find files on the device */ gchar *pbtemplate; /* e.g. "%s/esys/pblist%d.dat" */ gchar *mptemplate; /* e.g. "%s/esys/nw-mp3/mp%04x.dat" */ guint16 master_pblist; /* probably 1 */ } mple_device; /* Actual API-like thing */ /* Initialise/Release the device structure */ nw_device_t *mple_dev_init( gchar * ); void mple_dev_free( nw_device_t * ); gboolean mple_dev_sync( nw_device_t * ); /* this is an attempt to cater for devices that differ in where they place files. */ void *mple_dev_set_pb_template( mple_device *, char * ); void *mple_dev_set_mp_template( mple_device *, char * ); /* Pull the entire contents of the pblist (directory) off the device */ GList *mple_parse_pblist( nw_device_t * ); /* add/del/move folder */ /* Since pos == 0 is reserved for "add at first available slot", folder indices are 1-based. */ /* - del nukes the ENTIRE folder including contents */ guint32 mple_add_folder( nw_device_t *, gchar *, guint32 pos ); gboolean mple_del_folder( nw_device_t *, guint32 pos ); guint32 mple_mv_folder( nw_device_t *, guint16 oldpos, guint16 newpos ); guint32 mple_ren_folder( nw_device_t *, guint32 pos, gchar * ); /* same interface for tracks, less 'find' */ /* ren allows rewriting all metadata for the track */ guint32 mple_add_track( nw_device_t *, char *filename, nw_track_t *, guint32 folder, guint32 pos ); gboolean mple_del_track( nw_device_t *, guint32 tracknum ); guint32 mple_mv_track( nw_device_t *, guint32 tracknum, guint32 folder, guint32 pos ); guint16 mple_ren_track( nw_device_t *, guint16 tracknum, pblist_track * ); gboolean mple_get_track_header( nw_device_t *, guint16 ); /* add an already-encoded track to a folder */ guint32 mple_add_to_folder( nw_device_t *, guint32 folder, nw_track_t *, guint32 tracknum, guint32 pos ); /* extract metadata from a file/filehandle into a pblist_track struct */ pblist_track *mple_get_metadata_FILE( FILE * ); pblist_track *mple_get_metadata_NAME( char * ); /* write a file to the device. returns the track number */ guint16 mple_write_file( nw_device_t *, char *, guint16, guint16 ); /* convert a WMMP file back into an MP3 and write it to a file descriptor. Doesn't restore ID3 data as yet. */ gboolean mple_convert_wmmp( nw_track_t *, int /*fd_t*/ ); /* read the media serial number from the specified device */ gboolean mple_get_media_serial_number( nw_device_t * ); /* get a list of likely NW devices on the system */ GList *mple_get_nw_devs( gchar *, GList * ); /* pull aux data from track file */ guint32 mple_track_size( nw_track_t * ); guint32 mple_track_time( nw_track_t * ); guint32 mple_track_frames( nw_track_t * ); /* filesystem-like support */ typedef struct _MPLEFILE { NWFILE nwfile; /* NW common data */ guint8 conv[256]; /* conversion array */ } MPLEFILE; NWFILE *mple_open( nw_device_t *, guint32, guint32, const gchar *, char *); int mple_close( NWFILE * ); int mple_seek( NWFILE *, long, int ); long mple_tell( NWFILE * ); size_t mple_read( void *, size_t, size_t, NWFILE *); size_t mple_write( void *, size_t, size_t, NWFILE *); int mple_stat( nw_device_t *, guint32, struct stat *buf ); /* convert mple strings into something more useful */ #include id3_utf8_t *utf8_from_utf16be( char *, size_t ); guint16 *utf8_to_utf16be( const id3_utf8_t *, size_t, size_t * ); /* convenience */ #define gchar_from_utf16be( c, s ) ((gchar *)utf8_from_utf16be( c, s )) #define gchar_to_utf16be( c, s, l ) (utf8_to_utf16be( (id3_utf8_t *)c, s, l )) #include gchar *mple_getstr( guint16 * ); wchar_t *guint16o_wchar( guint16 * ); #endif