예제 #1
0
파일: spc.cpp 프로젝트: xomniversex/foo_gep
static void parse_id666( service_ptr_t< file > & p_file, LPID666TAG lpTag, bool aligned, abort_callback & p_abort )
{
	while ( ! p_file->is_eof( p_abort ) )
	{
		t_uint8 id, type;
		t_uint16    data;

		p_file->read_object_t( id, p_abort );
		p_file->read_object_t( type, p_abort );
		p_file->read_lendian_t( data, p_abort );

		switch ( type )
		{
		case XTYPE_STR:
			{
				if ( data < 1 || data > 256 ) throw exception_io_data();

				switch ( id )
				{
				case XID_SONG:
					p_file->read_object( lpTag->szTitle, data, p_abort );
					break;

				case XID_GAME:
					p_file->read_object( lpTag->szGame, data, p_abort );
					break;

				case XID_ARTIST:
					p_file->read_object( lpTag->szArtist, data, p_abort );
					break;

				case XID_PUB:
					p_file->read_object( lpTag->szPublisher, data, p_abort );
					break;

				case XID_OST:
					p_file->read_object( lpTag->szOST, data, p_abort );
					break;

				case XID_DUMPER:
					p_file->read_object( lpTag->szDumper, data, p_abort );
					break;

				case XID_CMNTS:
					p_file->read_object( lpTag->szComment, data, p_abort );
					break;

				default:
					p_file->skip( data, p_abort );
					break;
				}

				if ( aligned && ( data & 3 ) ) p_file->skip( 4 - ( data & 3 ), p_abort );
			}
			break;

		case XTYPE_INT:
			{
				if ( data != 4 ) throw exception_io_data();

				t_uint32 value;
				p_file->read_lendian_t( value, p_abort );

				switch ( id )
				{
				case XID_DATE:
					SetDate( lpTag->szDate, ( value >> 16 ) & 255, ( value >> 8 ) & 255, value & 255 );
					break;

				case XID_INTRO:
					if ( value > 383999999 ) value = 383999999;
					lpTag->uSong_ms = value / 64;
					break;

				case XID_LOOP:
					if ( value > 383999999 ) value = 383999999;
					lpTag->uLoop_ms = value / 64;
					break;

				case XID_END:
					if ( value > 383999999 ) value = 383999999;
					lpTag->uEnd_ms = value / 64;
					break;

				case XID_FADE:
					if ( value > 3839999 ) value = 3839999;
					lpTag->uFade_ms = value / 64;
					break;

				case XID_AMP:
					if ( value < 32768 ) value = 32768;
					else if ( value > 524288 ) value = 524288;
					lpTag->uAmplification = value;
					break;
				}
			}
			break;

		case XTYPE_DATA:
			{
				switch ( id )
				{
				case XID_EMU:
					lpTag->bEmulator = t_uint8( data );
					break;

				case XID_DISC:
					lpTag->bDisc = t_uint8( data );
					if ( lpTag->bDisc > 9 ) lpTag->bDisc = 9;
					break;

				case XID_TRACK:
					if ( data > ( ( 100 << 8 ) - 1 ) ) data = 0;
					lpTag->wTrack = data;
					break;

				case XID_COPY:
					lpTag->wCopyright = data;
					break;

				case XID_MUTE:
					lpTag->bMute = t_uint8( data );
					break;

				case XID_LOOPX:
					if ( data < 1 ) data = 1;
					else if ( data > 9 ) data = 9;
					lpTag->uLoopCount = data;
					break;

				case XID_AMP:
					lpTag->uAmplification = data;
					lpTag->uAmplification <<= 12;
					if ( lpTag->uAmplification < 32768 ) lpTag->uAmplification = 32768;
					else if ( lpTag->uAmplification > 524288 ) lpTag->uAmplification = 524288;
					break;
				}
			}
			break;
		}
	}
}
예제 #2
0
void ipod_write_shadowdb_v2(ipod_device_ptr_ref_t p_ipod, const char * m_path, const ipod::tasks::load_database_t & p_library, threaded_process_v2_t & p_status,abort_callback & p_abort)
{
	pfc::string8 newpath;
	bool b_opened = false;
	//string_print_drive m_path(p_ipod->drive);

	try
	{
		pfc::string8 path = m_path, path_shuffle, path_pstate, path_stats;
		pfc::string8 backup_path;
		path << "\\iTunes\\" << "iTunesSD";
		path_shuffle << m_path << "\\iTunes\\" << "iTunesShuffle";
		path_pstate << m_path << "\\iTunes\\" << "iTunesPState";
		path_stats << m_path << "\\iTunes\\" << "iTunesStats";

		newpath << path << ".temp";

		t_size i, count_tracks = p_library.m_tracks.get_count(), count_playlists = p_library.m_playlists.get_count();

		const t_uint32 shdb_length = 0x40;
		const t_uint32 shtr_length = 372;
		const t_uint32 shth_length = (5 + count_tracks)*sizeof(t_uint32);

		iTunesSD2::writer header;

		header.write_lendian_t(iTunesSD2::shdb, p_abort);
		header.write_lendian_t(0x02000003, p_abort);
		header.write_lendian_t(shdb_length, p_abort);
		header.write_lendian_t(count_tracks, p_abort);
		header.write_lendian_t(count_playlists + 1, p_abort);
		header.write_lendian_t(t_uint32(0), p_abort);
		header.write_lendian_t(t_uint32(0), p_abort);
		header.write_lendian_t(t_uint8(0), p_abort);
		header.write_lendian_t(t_uint8(p_library.m_itunesprefs.m_voiceover_enabled ? 1 : 0), p_abort); //voiceover_enabled
		header.write_lendian_t(t_uint8(0), p_abort);
		header.write_lendian_t(t_uint8(0), p_abort);
		header.write_lendian_t(count_tracks, p_abort);
		header.write_lendian_t(shdb_length, p_abort); //shth offset
		header.write_lendian_t(shdb_length + shth_length + shtr_length*count_tracks, p_abort); //shph offset
		header.write_lendian_t(t_uint32(0), p_abort);
		header.write_lendian_t(t_uint32(0), p_abort);
		header.write_lendian_t(t_uint32(0), p_abort);
		header.write_lendian_t(t_uint32(0), p_abort);
		header.write_lendian_t(t_uint32(0), p_abort);

		{
			iTunesSD2::writer shth;
			shth.write_lendian_t(iTunesSD2::shth, p_abort);
			shth.write_lendian_t(shth_length, p_abort);
			shth.write_lendian_t(count_tracks, p_abort);
			shth.write_lendian_t(t_uint32(0), p_abort);
			shth.write_lendian_t(t_uint32(0), p_abort);
	
			for (i=0; i<count_tracks; i++)
				shth.write_lendian_t(shdb_length + shth_length + i*shtr_length, p_abort);

			header.write(shth, p_abort);
		}

		for (i=0; i<count_tracks; i++)
		{
			const pfc::rcptr_t<itunesdb::t_track> & p_track = p_library.m_tracks[i];
			iTunesSD2::writer shtr;
			shtr.write_lendian_t(iTunesSD2::shtr, p_abort);
			shtr.write_lendian_t(shtr_length, p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort); //start pos
			shtr.write_lendian_t(p_track->length, p_abort);

			int volume = 0;
			if (p_ipod->m_device_properties.m_SupportsSoundCheck)
			{
				unsigned sc = p_library.m_tracks[i]->soundcheck;
				int voli = p_library.m_tracks[i]->volume;
				double volf = (double)voli / 255.0 + 1.0;
				if (volf == 0.0)
				{
					volume = -144;
				}
				else
				{
					double scdb = sc ? 10.0*log10 (1000.0 / (double)sc) : 0; //apple limit to [-12,+12] dB .... but let's not :)
					double vol = 20.0 * log10(volf);
					volume = round_float_signed(vol + scdb);
					if (volume < -48)  volume = -144; //silencer ???
					else if (volume > 18) volume = 18;
				}
			}
			else
			{
				volume = 100 + round_float_signed(100.0 + (double)p_library.m_tracks[i]->volume/255.0);
				volume = min(volume, 200);
				volume = max(volume, 0);
			}

			shtr.write_lendian_t(t_int32(volume)/*p_track->volume*/, p_abort);

			t_uint32 type=0;
			pfc::string_extension ext(p_library.m_tracks[i]->location);
			if (!stricmp_utf8(ext, "mp3"))
				type = 0x1;
			else if (!stricmp_utf8(ext, "mp4") || !stricmp_utf8(ext, "m4a") || !stricmp_utf8(ext, "aa") || !stricmp_utf8(ext, "m4b"))
				type = 0x2;
			else if (!stricmp_utf8(ext, "wav"))
				type = 0x4;

			shtr.write_lendian_t(type, p_abort);

			pfc::string8 path = p_library.m_tracks[i]->location;

			path.truncate (256);
			path.replace_byte(':','/');

			t_size length_path = path.length();

			shtr.write(path.get_ptr(), length_path, p_abort);

			t_size padding = 256 - length_path;
			for (;padding;padding--)
				shtr.write_lendian_t(t_uint8(0), p_abort);

			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(t_uint8(!p_track->skip_on_shuffle), p_abort);
			shtr.write_lendian_t(t_uint8(p_track->remember_playback_position), p_abort);
			shtr.write_lendian_t(t_uint8(p_track->gapless_album), p_abort);
			shtr.write_lendian_t(t_uint8(0), p_abort);
			shtr.write_lendian_t(p_track->encoder_delay, p_abort);
			shtr.write_lendian_t(p_track->encoder_padding, p_abort);
			shtr.write_lendian_t(p_track->samplecount, p_abort);
			shtr.write_lendian_t(t_uint64(p_track->resync_frame_offset), p_abort);
			shtr.write_lendian_t(p_track->album_id, p_abort);
			shtr.write_lendian_t(t_uint16(p_track->tracknumber), p_abort);
			shtr.write_lendian_t(t_uint16(p_track->discnumber), p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(p_track->pid, p_abort);
			shtr.write_lendian_t(p_track->artist_id, p_abort);

			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort);
			shtr.write_lendian_t(t_uint32(0), p_abort);

			header.write(shtr, p_abort);
		}

		{
			const t_uint32 shph_length = (5+1+count_playlists)*sizeof(t_uint32);
			t_uint32 shpl_rolling_start = header.get_size()+shph_length;

			iTunesSD2::writer shph;
			shph.write_lendian_t(iTunesSD2::shph, p_abort);
			shph.write_lendian_t(shph_length, p_abort);
			shph.write_lendian_t(count_playlists+1, p_abort);
			shph.write_lendian_t(t_uint16(0xffff), p_abort); //wtf
			shph.write_lendian_t(t_uint16(0xffff), p_abort); //wtf
			shph.write_lendian_t(t_uint16(0xffff), p_abort); //wtf
			shph.write_lendian_t(t_uint16(0), p_abort); //wtf

			t_uint32 j;

			pfc::array_staticsize_t<iTunesSD2::writer> shpl_array(count_playlists + 1);

			{
				const t_uint32 shpl_size = (11 + count_tracks)*sizeof(t_uint32);

				iTunesSD2::writer & shpl = shpl_array[0];
				shpl.write_lendian_t(iTunesSD2::shpl, p_abort);
				shpl.write_lendian_t(shpl_size, p_abort);
				shpl.write_lendian_t(count_tracks, p_abort);
				shpl.write_lendian_t(count_tracks, p_abort);
				shpl.write_lendian_t(t_uint64(0), p_abort);
				shpl.write_lendian_t(t_uint32(1), p_abort);
				shpl.write_lendian_t(t_uint32(0), p_abort);
				shpl.write_lendian_t(t_uint32(0), p_abort);
				shpl.write_lendian_t(t_uint32(0), p_abort);
				shpl.write_lendian_t(t_uint32(0), p_abort);
				for (j=0; j<count_tracks; j++)
					shpl.write_lendian_t(t_uint32(j), p_abort);
			}

			mmh::permutation_t permuation_track_id(count_tracks);
			mmh::g_sort_get_permutation_qsort_v2(p_library.m_tracks.get_ptr(), permuation_track_id, ipod::tasks::load_database_t::g_compare_track_id, false, false);

			for (i=0; i<count_playlists; i++)
			{
				const pfc::rcptr_t<itunesdb::t_playlist> & p_playlist = p_library.m_playlists[i];
				t_size count_entries = p_playlist->items.get_count();

				pfc::array_t<t_uint32> indices;
				indices.set_size(count_entries);

				t_size k=0;
				for (j=0; j<count_entries; j++)
					if (!p_playlist->items[j].is_podcast_group)
					{
						t_size index;
						if (p_library.m_tracks.bsearch_permutation_t(ipod::tasks::load_database_t::g_compare_track_id_with_id, p_playlist->items[j].track_id, permuation_track_id, index))
							indices[k++] = index;
					}

				indices.set_size(k);

				const t_uint32 shpl_size = (11 + k)*sizeof(t_uint32);
				iTunesSD2::writer & shpl = shpl_array[1+i];
				shpl.write_lendian_t(iTunesSD2::shpl, p_abort);
				shpl.write_lendian_t(shpl_size, p_abort);
				shpl.write_lendian_t(k, p_abort);
				shpl.write_lendian_t(k, p_abort);
				shpl.write_lendian_t(p_library.m_playlists[i]->id, p_abort);
				shpl.write_lendian_t(t_uint32(2), p_abort);
				shpl.write_lendian_t(t_uint32(0), p_abort);
				shpl.write_lendian_t(t_uint32(0), p_abort);
				shpl.write_lendian_t(t_uint32(0), p_abort);
				shpl.write_lendian_t(t_uint32(0), p_abort);
				for (j=0; j<k; j++)
					shpl.write_lendian_t(indices[j], p_abort);
			}

			for (i=0; i<count_playlists+1; i++)
			{
				shph.write_lendian_t(shpl_rolling_start, p_abort);
				shpl_rolling_start += shpl_array[i].get_size();
			}
			for (i=0; i<count_playlists+1; i++)
				shph.write(shpl_array[i], p_abort);
			header.write(shph, p_abort);
		}

		service_ptr_t<file> p_file;
		filesystem::g_open_write_new(p_file, newpath, p_abort);
		b_opened=true;

		p_file->write(header.get_ptr(), header.get_size(), p_abort);


		p_file.release();
		b_opened=false;

		abort_callback_dummy p_dummy_abort;

		backup_path << path.get_ptr() << ".backup";
		if (filesystem::g_exists(backup_path, p_dummy_abort))
			filesystem::g_remove(backup_path, p_dummy_abort);

		if (filesystem::g_exists(path, p_dummy_abort))
			filesystem::g_move(path, backup_path, p_dummy_abort);
		filesystem::g_move(newpath, path, p_dummy_abort);

		if (filesystem::g_exists(path_shuffle, p_dummy_abort))
			filesystem::g_remove(path_shuffle, p_dummy_abort);

		if (filesystem::g_exists(path_pstate, p_dummy_abort))
			filesystem::g_remove(path_pstate, p_dummy_abort);

		if (filesystem::g_exists(path_stats, p_dummy_abort))
			filesystem::g_remove(path_stats, p_dummy_abort);
	}
	catch (const exception_aborted &) 
	{
		try
		{
			abort_callback_impl p_dummy_abort;
			if (b_opened)
				filesystem::g_remove(newpath, p_dummy_abort);
		}
		catch (const pfc::exception &) {}
		throw;
	}
	catch (const pfc::exception & ex)
	{
		try
		{
			abort_callback_impl p_dummy_abort;
			if (b_opened)
				filesystem::g_remove(newpath, p_dummy_abort);
		}
		catch (const pfc::exception &) {}
		throw pfc::exception
		//console::print
			(pfc::string_formatter() << "Error writing iTunesSD file : " << ex.what());
	}
}