static int write_mhni (Itdb_DB *db, Itdb_Thumb_Ipod_Item *item, iPodBuffer *buffer) { MhniHeader *mhni; unsigned int total_bytes; int bytes_written; iPodBuffer *sub_buffer; const Itdb_ArtworkFormat *format; if (item == NULL) { return -1; } mhni = (MhniHeader *)init_header (buffer, "mhni", sizeof (MhniHeader)); if (mhni == NULL) { return -1; } total_bytes = get_gint32 (mhni->header_len, buffer->byte_order); mhni->total_len = get_gint32 (total_bytes, buffer->byte_order); format = item->format; mhni->format_id = get_gint32 (format->format_id, buffer->byte_order); mhni->image_width = get_gint16 (item->width, buffer->byte_order); mhni->image_height = get_gint16 (item->height, buffer->byte_order); mhni->image_size = get_gint32 (item->size, buffer->byte_order); mhni->ithmb_offset = get_gint32 (item->offset, buffer->byte_order); mhni->vertical_padding = get_gint16 (item->vertical_padding, buffer->byte_order); mhni->horizontal_padding = get_gint16 (item->horizontal_padding, buffer->byte_order); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { return -1; } bytes_written = write_mhod_type_3 (item->filename, sub_buffer); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; } total_bytes += bytes_written; mhni = ipod_buffer_get_pointer (buffer); mhni->total_len = get_gint32 (total_bytes, buffer->byte_order); /* Only update number of children when all went well to try to get * something somewhat consistent when there are errors */ mhni->num_children = get_gint32 (1, buffer->byte_order); dump_mhni (mhni); return total_bytes; }
G_GNUC_INTERNAL int ipod_write_artwork_db (Itdb_iTunesDB *itdb) { iPodBuffer *buf; int bytes_written; char *filename; int id_max; Itdb_DB db; int status; db.db_type = DB_TYPE_ITUNES; db.db.itdb = itdb; id_max = itdb_prepare_thumbnails (itdb); /* First, let's write the .ithmb files, this will create the * various thumbnails as well */ status = itdb_write_ithumb_files (&db); if (status != 0) { return -1; } filename = ipod_db_get_artwork_db_path (itdb_get_mountpoint (itdb)); if (filename == NULL) { /* FIXME: the iTunesDB will be inconsistent wrt artwork_count * it might be better to 0 out this field in all tracks * when we encounter an error */ return -1; } buf = ipod_buffer_new (filename, itdb->device->byte_order, DB_TYPE_ITUNES); if (buf == NULL) { g_print ("Couldn't create %s\n", filename); g_free (filename); return -1; } bytes_written = write_mhfd (&db, buf, id_max); /* Refcount of the shared buffer should drop to 0 and this should * sync buffered data to disk */ ipod_buffer_destroy (buf); if (bytes_written == -1) { g_print ("Failed to save %s\n", filename); /* FIXME: maybe should unlink the file we may have created */ g_free (filename); return -1; } g_free (filename); return 0; }
static int write_mhfd (Itdb_DB *db, iPodBuffer *buffer, int id_max) { MhfdHeader *mhfd; unsigned int total_bytes; int bytes_written; int i; mhfd = (MhfdHeader *)init_header (buffer, "mhfd", sizeof (MhfdHeader)); if (mhfd == NULL) { return -1; } total_bytes = get_gint32 (mhfd->header_len, buffer->byte_order); mhfd->total_len = get_gint32 (total_bytes, buffer->byte_order); switch (buffer->db_type) { case DB_TYPE_PHOTO: mhfd->unknown2 = get_gint32 (2, buffer->byte_order); break; case DB_TYPE_ITUNES: mhfd->unknown2 = get_gint32 (2, buffer->byte_order); break; } mhfd->next_id = get_gint32 (id_max, buffer->byte_order); mhfd->unknown_flag1 = 2; for (i = 1 ; i <= 3; i++) { iPodBuffer *sub_buffer; sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { continue; } bytes_written = write_mhsd (db, sub_buffer, i); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; } total_bytes += bytes_written; mhfd = ipod_buffer_get_pointer (buffer); mhfd->total_len = get_gint32 (total_bytes, buffer->byte_order); mhfd->num_children = get_gint32 (i, buffer->byte_order); } dump_mhfd (mhfd); return total_bytes; }
static int write_mhsd (Itdb_DB *db, iPodBuffer *buffer, enum MhsdType type) { ArtworkDB_MhsdHeader *mhsd; unsigned int total_bytes; int bytes_written; iPodBuffer *sub_buffer; g_assert (type >= MHSD_TYPE_MHLI); g_assert (type <= MHSD_TYPE_MHLF); mhsd = (ArtworkDB_MhsdHeader *)init_header (buffer, "mhsd", sizeof (ArtworkDB_MhsdHeader)); if (mhsd == NULL) { return -1; } total_bytes = get_gint32 (mhsd->header_len, buffer->byte_order); mhsd->total_len = get_gint32 (total_bytes, buffer->byte_order); mhsd->index = get_gint16 (type, buffer->byte_order); bytes_written = -1; sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { return -1; } switch (type) { case MHSD_TYPE_MHLI: bytes_written = write_mhli (db, sub_buffer); break; case MHSD_TYPE_MHLA: bytes_written = write_mhla (db, sub_buffer); break; case MHSD_TYPE_MHLF: bytes_written = write_mhlf (db, sub_buffer); break; } ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; } else { total_bytes += bytes_written; mhsd = ipod_buffer_get_pointer (buffer); mhsd->total_len = get_gint32 (total_bytes, buffer->byte_order); } dump_mhsd (mhsd); return total_bytes; }
int ipod_write_photo_db (Itdb_PhotoDB *photodb) { iPodBuffer *buf; int bytes_written; char *filename; int id_max; Itdb_DB db; int status; db.db_type = DB_TYPE_PHOTO; db.db.photodb = photodb; filename = ipod_db_get_photos_db_path (db_get_mountpoint (&db)); status = itdb_write_ithumb_files (&db); if (status != 0) { return -1; } if (filename == NULL) { return -1; } buf = ipod_buffer_new (filename, photodb->device->byte_order, DB_TYPE_PHOTO); if (buf == NULL) { g_print ("Couldn't create %s\n", filename); g_free (filename); return -1; } id_max = itdb_get_max_photo_id( photodb ); bytes_written = write_mhfd (&db, buf, id_max+1); /* Refcount of the shared buffer should drop to 0 and this should * sync buffered data to disk */ ipod_buffer_destroy (buf); if (bytes_written == -1) { g_print ("Failed to save %s\n", filename); /* FIXME: maybe should unlink the file we may have created */ g_free (filename); return -1; } g_free (filename); return 0; }
static int write_mhla (Itdb_DB *db, iPodBuffer *buffer) { GList *it; MhlaHeader *mhla; iPodBuffer *sub_buffer; unsigned int total_bytes; mhla = (MhlaHeader *)init_header (buffer, "mhla", sizeof (MhlaHeader)); if (mhla == NULL) { return -1; } total_bytes = get_gint32 (mhla->header_len, buffer->byte_order); if (buffer->db_type == DB_TYPE_PHOTO) { unsigned int bytes_written; unsigned int num_children = 0; for (it = db_get_photodb(db)->photoalbums; it != NULL; it = it->next) { Itdb_PhotoAlbum *album = (Itdb_PhotoAlbum *)it->data; sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { return -1; } bytes_written = write_mhba (album, sub_buffer); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; } total_bytes += bytes_written; mhla = ipod_buffer_get_pointer (buffer); num_children++; mhla->num_children = get_gint32 (num_children, buffer->byte_order); } } dump_mhl ((MhlHeader *)mhla, "mhla"); return total_bytes; }
static int write_mhod (Itdb_DB *db, Itdb_Thumb_Ipod_Item *thumb, iPodBuffer *buffer) { ArtworkDB_MhodHeader *mhod; unsigned int total_bytes; int bytes_written; iPodBuffer *sub_buffer; if (thumb == NULL) { return -1; } mhod = (ArtworkDB_MhodHeader *) init_header (buffer, "mhod", sizeof (ArtworkDB_MhodHeader)); if (mhod == NULL) { return -1; } total_bytes = sizeof (ArtworkDB_MhodHeader); mhod->total_len = get_gint32 (total_bytes, buffer->byte_order); mhod->type = get_gint16 (MHOD_TYPE_LOCATION, buffer->byte_order); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { return -1; } bytes_written = write_mhni (db, thumb, sub_buffer); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; } total_bytes += bytes_written; mhod = ipod_buffer_get_pointer (buffer); mhod->total_len = get_gint32 (total_bytes, buffer->byte_order); dump_mhod (mhod); return total_bytes; }
static int write_mhlf (Itdb_DB *db, iPodBuffer *buffer) { MhlfHeader *mhlf; unsigned int total_bytes; int bytes_written; GList *formats; GList *it; unsigned int num_children; mhlf = (MhlfHeader *)init_header (buffer, "mhlf", sizeof (MhlfHeader)); if (mhlf == NULL) { return -1; } total_bytes = get_gint32 (mhlf->header_len, buffer->byte_order); num_children = 0; mhlf->num_files = get_gint32 (num_children, buffer->byte_order); formats = NULL; switch (buffer->db_type) { case DB_TYPE_ITUNES: formats = itdb_device_get_cover_art_formats(db_get_device(db)); break; case DB_TYPE_PHOTO: formats = itdb_device_get_photo_formats(db_get_device(db)); break; } if (formats == NULL) { return total_bytes; } for (it = formats; it != NULL; it = it->next) { const Itdb_ArtworkFormat *format; iPodBuffer *sub_buffer; format = (const Itdb_ArtworkFormat *)it->data; sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { g_list_free (formats); return -1; } bytes_written = write_mhif (db, sub_buffer, format); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; } total_bytes += bytes_written; mhlf = ipod_buffer_get_pointer (buffer); num_children++; /* Only update number of children when all went well to try * to get something somewhat consistent when there are errors */ mhlf->num_files = get_gint32 (num_children, buffer->byte_order); } dump_mhl ((MhlHeader *)mhlf, "mhlf"); g_list_free (formats); return total_bytes; }
static int write_mhba (Itdb_PhotoAlbum *album, iPodBuffer *buffer) { GList *it; MhbaHeader *mhba; iPodBuffer *sub_buffer; unsigned int total_bytes; unsigned int bytes_written; mhba = (MhbaHeader *)init_header (buffer, "mhba", sizeof (MhbaHeader)); if (mhba == NULL) { return -1; } mhba->num_mhods = get_gint32(1, buffer->byte_order); mhba->num_mhias = get_gint32(g_list_length (album->members), buffer->byte_order); mhba->album_id = get_gint32(album->album_id, buffer->byte_order); mhba->unk024 = get_gint32(album->unk024, buffer->byte_order); mhba->unk028 = get_gint16(album->unk028, buffer->byte_order); mhba->album_type = album->album_type; mhba->playmusic = album->playmusic; mhba->repeat = album->repeat; mhba->random = album->random; mhba->show_titles = album->show_titles; mhba->transition_direction = album->transition_direction; mhba->slide_duration = get_gint32(album->slide_duration, buffer->byte_order); mhba->transition_duration = get_gint32(album->transition_duration, buffer->byte_order); mhba->unk044 = get_gint32(album->unk044, buffer->byte_order); mhba->unk048 = get_gint32(album->unk048, buffer->byte_order); mhba->song_id = get_gint64(album->song_id, buffer->byte_order); mhba->prev_album_id = get_gint32(album->prev_album_id, buffer->byte_order); total_bytes = get_gint32 (mhba->header_len, buffer->byte_order); /* FIXME: Write other mhods */ /* Write album title */ sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { return -1; } bytes_written = write_mhod_type_1 (album->name, sub_buffer); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; } total_bytes += bytes_written; for (it = album->members; it != NULL; it = it->next) { Itdb_Artwork *photo = it->data; g_return_val_if_fail (photo, -1); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { return -1; } bytes_written = write_mhia (photo->id, sub_buffer); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; } total_bytes += bytes_written; } mhba = ipod_buffer_get_pointer (buffer); mhba->total_len = get_gint32( total_bytes, buffer->byte_order ); dump_mhba ( mhba ); return total_bytes; }
static int write_mhii (Itdb_DB *db, void *data, iPodBuffer *buffer) { MhiiHeader *mhii; unsigned int total_bytes; int bytes_written; int num_children; const GList *it = NULL; Itdb_Track *song; Itdb_Artwork *artwork; guint64 mactime; Itdb_Device *device = db_get_device (db); mhii = (MhiiHeader *)init_header (buffer, "mhii", sizeof (MhiiHeader)); if (mhii == NULL) { return -1; } total_bytes = get_gint32 (mhii->header_len, buffer->byte_order); switch( buffer->db_type) { case DB_TYPE_ITUNES: song = (Itdb_Track *)data; artwork = song->artwork; mhii->song_id = get_gint64 (song->dbid, buffer->byte_order); break; case DB_TYPE_PHOTO: artwork = (Itdb_Artwork *)data; mhii->song_id = get_gint64 (artwork->id + 2, buffer->byte_order); break; default: g_return_val_if_reached (-1); } mhii->image_id = get_guint32 (artwork->id, buffer->byte_order); mhii->unknown4 = get_gint32 (artwork->unk028, buffer->byte_order); mhii->rating = get_gint32 (artwork->rating, buffer->byte_order); mhii->unknown6 = get_gint32 (artwork->unk036, buffer->byte_order); mactime = device_time_time_t_to_mac (device, artwork->creation_date); mhii->orig_date = get_guint32 (mactime, buffer->byte_order); mactime = device_time_time_t_to_mac (device, artwork->digitized_date); mhii->digitized_date = get_guint32 (mactime, buffer->byte_order); mhii->orig_img_size = get_gint32 (artwork->artwork_size, buffer->byte_order); num_children = 0; /* Before trying to write the artwork or photo database, the ithmb * files have been written, which will have converted all thumbnails * attached to the tracks to ITDB_THUMB_TYPE_IPOD thumbnails. */ g_assert (artwork->thumbnail->data_type == ITDB_THUMB_TYPE_IPOD); for (it=itdb_thumb_ipod_get_thumbs ((Itdb_Thumb_Ipod *)artwork->thumbnail); it!=NULL; it=it->next) { iPodBuffer *sub_buffer; Itdb_Thumb_Ipod_Item *thumb; thumb = (Itdb_Thumb_Ipod_Item *)it->data; if (thumb->format == NULL) { /* skip this thumb */ continue; } mhii->num_children = get_gint32 (num_children, buffer->byte_order); mhii->total_len = get_gint32 (total_bytes, buffer->byte_order); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { return -1; } bytes_written = write_mhod (db, thumb, sub_buffer); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; } total_bytes += bytes_written; mhii = ipod_buffer_get_pointer (buffer); num_children++; } mhii->num_children = get_gint32 (num_children, buffer->byte_order); mhii->total_len = get_gint32 (total_bytes, buffer->byte_order); dump_mhii (mhii); return total_bytes; }