void writeOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, const void * in,DWORD inBytes, abort_callback & abort) {
		abort.check();
		if (inBytes == 0) return;
		OVERLAPPED ol = {};
		fillOverlapped(ol, myEvent, position);
		ResetEvent(myEvent);
		DWORD bytesWritten;
		SetLastError(NO_ERROR);
		if (WriteFile( handle, in, inBytes, &bytesWritten, &ol)) {
			// succeeded already?
			if (bytesWritten != inBytes) throw exception_io();
			return;
		}
		
		{
			const DWORD code = GetLastError();
			if (code != ERROR_IO_PENDING) exception_io_from_win32(code);
		}
		const HANDLE handles[] = {myEvent, abort.get_abort_event()};
		SetLastError(NO_ERROR);
		DWORD state = WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE);
		if (state == WAIT_OBJECT_0) {
			try {
				WIN32_IO_OP( GetOverlappedResult(handle,&ol,&bytesWritten,TRUE) );
			} catch(...) {
				CancelIo(handle);
				throw;
			}
			if (bytesWritten != inBytes) throw exception_io();
			return;
		}
		CancelIo(handle);
		throw exception_aborted();
	}
Пример #2
0
	void run(threaded_process_status & p_status,abort_callback & p_abort) {
		try {
			const t_uint32 decode_flags = input_flag_no_seeking | input_flag_no_looping; // tell the decoders that we won't seek and that we don't want looping on formats that support looping.
			input_helper input;
			audio_hash.set_count(m_items.get_size());
			for(t_size walk = 0; walk < m_items.get_size(); ++walk) {

				p_abort.check(); // in case the input we're working with fails at doing this
				p_status.set_progress(walk, m_items.get_size());
				p_status.set_progress_secondary(0);
				p_status.set_item_path( m_items[walk]->get_path() );
				input.open(NULL, m_items[walk], decode_flags, p_abort);
				
				double length;
				{ // fetch the track length for proper dual progress display;
					file_info_impl info;
					// input.open should have preloaded relevant info, no need to query the input itself again.
					// Regular get_info() may not retrieve freshly loaded info yet at this point (it will start giving the new info when relevant info change callbacks are dispatched); we need to use get_info_async.
					if (m_items[walk]->get_info_async(info)) length = info.get_length();
					else length = 0;
				}

				memset( &ctx, 0, sizeof( sha1_context ) );
				sha1_starts( &ctx );
				audio_chunk_impl_temporary l_chunk;
				
				double decoded = 0;
				while(input.run(l_chunk, p_abort)) { // main decode loop
				    sha1_update(&ctx,(unsigned char*)l_chunk.get_data(),l_chunk.get_data_length());
					//m_peak = l_chunk.get_peak(m_peak);
					if (length > 0) { // don't bother for unknown length tracks
						decoded += l_chunk.get_duration();
						if (decoded > length) decoded = length;
						p_status.set_progress_secondary_float(decoded / length);
					}
					p_abort.check(); // in case the input we're working with fails at doing this
				}
				unsigned char sha1sum[20] ={0};
				sha1_finish(&ctx,sha1sum);
				pfc::string_formatter msg;
			    for(int i = 0; i < 20; i++ )
				{
				 
				  msg <<pfc::format_hex(sha1sum[i]);
				  audio_hash[walk] =msg;
				}
				



			}
		} catch(std::exception const & e) {
			m_failMsg = e.what();
		}
	}
Пример #3
0
void CMutex::AcquireByHandle( HANDLE hMutex, abort_callback & aborter ) {
	SetLastError(0);
	HANDLE hWait[2] = {hMutex, aborter.get_abort_event()};
	switch(WaitForMultipleObjects( 2, hWait, FALSE, INFINITE ) ) {
	case WAIT_FAILED:
		WIN32_OP_FAIL_CRITICAL("WaitForSingleObject");
	case WAIT_OBJECT_0:
		return;
	case WAIT_OBJECT_0 + 1:
		PFC_ASSERT( aborter.is_aborting() );
		throw exception_aborted();
	default:
		uBugCheck();
	}
}
Пример #4
0
	t_size MultiWaitAbortable_MsgLoop(const HANDLE * ev, t_size evCount, abort_callback & abort) {
		pfc::array_t<HANDLE> handles; handles.set_size(evCount + 1);
		handles[0] = abort.get_abort_event();
		pfc::memcpy_t(handles.get_ptr() + 1, ev, evCount);
		for(;;) {
			SetLastError(0);
			const DWORD status = MsgWaitForMultipleObjects(handles.get_count(), handles.get_ptr(), FALSE, INFINITE, QS_ALLINPUT);
			switch(status) {
				case WAIT_TIMEOUT:
					PFC_ASSERT(!"How did we get here?");
					uBugCheck();
				case WAIT_OBJECT_0:
					throw exception_aborted();
				case WAIT_FAILED:
					WIN32_OP_FAIL();
				default:
					{
						t_size index = (t_size)(status - (WAIT_OBJECT_0 + 1));
						if (index == evCount) {
							ProcessPendingMessages();
						} else if (index < evCount) {
							return index;
						} else {
							uBugCheck();
						}
					}
			}
		}
	}
Пример #5
0
bool input_helper::open_path(file::ptr p_filehint,const char * path,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints) {
	p_abort.check();

	if (!need_file_reopen(path)) return false;
	m_input.release();

	service_ptr_t<file> l_file = p_filehint;
	process_fullbuffer(l_file,path,m_fullbuffer,p_abort);

	TRACK_CODE("input_entry::g_open_for_decoding",
		input_entry::g_open_for_decoding(m_input,l_file,path,p_abort,p_from_redirect)
		);

	
	if (!p_skip_hints) {
		try {
			static_api_ptr_t<metadb_io>()->hint_reader(m_input.get_ptr(),path,p_abort);
		} catch(exception_io_data) {
			//Don't fail to decode when this barfs, might be barfing when reading info from another subsong than the one we're trying to decode etc.
			m_input.release();
			if (l_file.is_valid()) l_file->reopen(p_abort);
			TRACK_CODE("input_entry::g_open_for_decoding",
				input_entry::g_open_for_decoding(m_input,l_file,path,p_abort,p_from_redirect)
				);
		}
	}

	m_path = path;
	return true;
}
Пример #6
0
void input_helper::open(service_ptr_t<file> p_filehint,const playable_location & p_location,unsigned p_flags,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints) {
	p_abort.check();

	if (m_input.is_empty() || metadb::path_compare(p_location.get_path(),m_path) != 0)
	{
		m_input.release();

		service_ptr_t<file> l_file = p_filehint;
		process_fullbuffer(l_file,p_location.get_path(),m_fullbuffer,p_abort);

		TRACK_CODE("input_entry::g_open_for_decoding",
			input_entry::g_open_for_decoding(m_input,l_file,p_location.get_path(),p_abort,p_from_redirect)
			);

		
		if (!p_skip_hints) {
			try {
				static_api_ptr_t<metadb_io>()->hint_reader(m_input.get_ptr(),p_location.get_path(),p_abort);
			} catch(exception_io_data) {
				//don't fail to decode when this barfs
				m_input.release();
				if (l_file.is_valid()) l_file->reopen(p_abort);
				TRACK_CODE("input_entry::g_open_for_decoding",
					input_entry::g_open_for_decoding(m_input,l_file,p_location.get_path(),p_abort,p_from_redirect)
					);
			}
		}

		m_path = p_location.get_path();
	}

	TRACK_CODE("input_decoder::initialize",m_input->initialize(p_location.get_subsong_index(),p_flags,p_abort));
}
void stream_writer_buffered::write(const void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
	p_abort.check_e();
	const char * source = (const char*)p_buffer;
	t_size source_remaining = p_bytes;
	const t_size buffer_size = m_buffer.get_size();
	if (source_remaining >= buffer_size)
	{
		flush(p_abort);
		m_base->write_object(source,source_remaining,p_abort);
		return;
	}

	if (m_buffer_ptr + source_remaining >= buffer_size)
	{
		t_size delta = buffer_size - m_buffer_ptr;
		memcpy(m_buffer.get_ptr() + m_buffer_ptr, source,delta);
		source += delta;
		source_remaining -= delta;
		m_buffer_ptr += delta;
		flush(p_abort);
	}

	memcpy(m_buffer.get_ptr() + m_buffer_ptr, source,source_remaining);
	m_buffer_ptr += source_remaining;
}
Пример #8
0
void seekabilizer::seek(t_filesize p_position,abort_callback & p_abort) {
	assert(m_position_base >= m_buffer.get_depth());
	p_abort.check_e();

	if (m_size != filesize_invalid && p_position > m_size) throw exception_io_seek_out_of_range();

	t_filesize lowest = m_position_base - m_buffer.get_depth();

	if (p_position < lowest) {
		if (m_file->can_seek()) {
			m_buffer.reset();
			t_filesize target = p_position;
			t_size delta = m_buffer.get_max_depth();
			if (delta > backread_on_seek) delta = backread_on_seek;
			if (target > delta) target -= delta;
			else target = 0;
			m_file->seek(target,p_abort);
			m_position_base = target;
		}
		else {
			m_buffer.reset();
			m_file->reopen(p_abort);
			m_position_base = 0;
		}
	}

	m_position = p_position;
}
Пример #9
0
	bool WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort, DWORD timeout /*must not be INFINITE*/) {
		PFC_ASSERT( timeout != INFINITE );
		const DWORD entry = GetTickCount();
		const HANDLE handles[2] = {ev, abort.get_abort_event()};
		for(;;) {
			const DWORD done = GetTickCount() - entry;
			if (done >= timeout) return false;
			SetLastError(0);
			const DWORD status = MsgWaitForMultipleObjects(2, handles, FALSE, timeout - done, QS_ALLINPUT);
			switch(status) {
				case WAIT_TIMEOUT:
					return false;
				case WAIT_OBJECT_0:
					return true;
				case WAIT_OBJECT_0 + 1:
					throw exception_aborted();
				case WAIT_OBJECT_0 + 2:
					ProcessPendingMessages();
					break;
				case WAIT_FAILED:
					WIN32_OP_FAIL();
				default:
					uBugCheck();
			}
		}
	}
Пример #10
0
pfc::list_t<metadb_handle_ptr> get_sorted_playlist(const pfc::list_base_const_t<metadb_handle_ptr> &data, threaded_process_status &p_status, abort_callback &p_abort) {
	std::multimap<int, metadb_handle_ptr, std::greater<int>> temp;
	std::multimap<int, metadb_handle_ptr, std::greater<int>>::iterator it;
	pfc::list_t<metadb_handle_ptr> result;
	pfc::lores_timer timer;
	pfc::string8 message, msg;
	int size = data.get_count();

	for (int i = 0; i < size; i++) {
		message.reset();
		message << "Track " << i + 1 << " of " << size;
		p_status.set_item(message);
		p_status.set_progress(i + 1, size);

		timer.start();

		const metadb_handle_ptr track = data[i];
		int count = get_track_count(track, p_abort);

		msg.reset();
		msg << count;
		console::print(msg);

		// don't make more than 5 requests per second
		// (averaged over a 5 minute period)
		if (timer.query() < 0.2) {
			p_abort.sleep(0.2);
		}

		if (i && (i % 100 == 0)) {
			p_abort.sleep(10);
		}

		if (count > 0) {
			temp.insert(std::pair<int, metadb_handle_ptr>(count, track));
		} else {
			temp.insert(std::pair<int, metadb_handle_ptr>(0, track));
		}
	}

	for (it = temp.begin(); it != temp.end(); it++) {
		metadb_handle_ptr track = it->second;
		result.add_item(track);
	}

	return result;
}
	HANDLE createFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, abort_callback & abort) {
		abort.check();
		
		return CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);

		// CancelSynchronousIo() doesn't f*****g work. Useless.
#if 0
		pCancelSynchronousIo_t pCancelSynchronousIo = (pCancelSynchronousIo_t) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CancelSynchronousIo");
		if (pCancelSynchronousIo == NULL) {
#ifdef _DEBUG
			uDebugLog() << "Async CreateFile unavailable - using regular";
#endif
			return CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
		} else {
#ifdef _DEBUG
			uDebugLog() << "Starting async CreateFile...";
			pfc::hires_timer t; t.start();
#endif
			createFileData_t data = {lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, NULL, 0};
			HANDLE hThread = (HANDLE) _beginthreadex(NULL, 0, createFileProc, &data, 0, NULL);
			HANDLE waitHandles[2] = {hThread, abort.get_abort_event()};
			switch(WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE)) {
			case WAIT_OBJECT_0: // succeeded
				break;
			case WAIT_OBJECT_0 + 1: // abort
#ifdef _DEBUG
				uDebugLog() << "Aborting async CreateFile...";
#endif
				pCancelSynchronousIo(hThread);
				WaitForSingleObject(hThread, INFINITE);
				break;
			default:
				uBugCheck();
			}
			CloseHandle(hThread);
			SetLastError(data.dwErrorCode);
#ifdef _DEBUG
			uDebugLog() << "Async CreateFile completed in " << pfc::format_time_ex(t.query(), 6) << ", status: " << (uint32_t) data.dwErrorCode;
#endif
			if (abort.is_aborting()) {
				if (data.hResult != INVALID_HANDLE_VALUE) CloseHandle(data.hResult);
				throw exception_aborted();
			}
			return data.hResult;
		}
#endif
	}
	DWORD readOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, void * out, DWORD outBytes, abort_callback & abort) {
		abort.check();
		if (outBytes == 0) return 0;
		OVERLAPPED ol = {};
		fillOverlapped(ol, myEvent, position);
		ResetEvent(myEvent);
		DWORD bytesDone;
		SetLastError(NO_ERROR);
		if (ReadFile( handle, out, outBytes, &bytesDone, &ol)) {
			// succeeded already?
			return bytesDone;
		}

		{
			const DWORD code = GetLastError();
			switch(code) {
			case ERROR_HANDLE_EOF:
			case ERROR_BROKEN_PIPE:
				return 0;
			case ERROR_IO_PENDING:
				break; // continue
			default:
				exception_io_from_win32(code);
			};
		}

		const HANDLE handles[] = {myEvent, abort.get_abort_event()};
		SetLastError(NO_ERROR);
		DWORD state = WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE);
		if (state == WAIT_OBJECT_0) {
			SetLastError(NO_ERROR);
			if (!GetOverlappedResult(handle,&ol,&bytesDone,TRUE)) {
				const DWORD code = GetLastError();
				if (code == ERROR_HANDLE_EOF || code == ERROR_BROKEN_PIPE) bytesDone = 0;
				else {
					CancelIo(handle);
					exception_io_from_win32(code);
				}
			}
			return bytesDone;
		}
		CancelIo(handle);
		throw exception_aborted();
	}
Пример #13
0
t_size seekabilizer::read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
	p_abort.check_e();

	if (m_position > m_position_base + pfc::max_t<t_size>(m_buffer.get_max_depth(),backread_on_seek) && m_file->can_seek()) {
		m_buffer.reset();
		t_filesize target = m_position;
		if (target < backread_on_seek) target = 0;
		else target -= backread_on_seek;
		m_file->seek(target,p_abort);
		m_position_base = target;
	}

	//seek ahead
	while(m_position > m_position_base) {
		enum {tempsize = 1024};
		t_uint8 temp[tempsize];
		t_size delta = (t_size) pfc::min_t<t_filesize>(tempsize,m_position - m_position_base);
		t_size bytes_read = 0;
		bytes_read = m_file->read(temp,delta,p_abort);
		m_buffer.write(temp,bytes_read);
		m_position_base += bytes_read;

		if (bytes_read < delta) {
			return 0;
		}
	}

	t_size done = 0;
	t_uint8 * targetptr = (t_uint8*) p_buffer;

	//try to read backbuffer
	if (m_position < m_position_base) {
		if (m_position_base - m_position > (t_filesize)m_buffer.get_depth()) throw exception_io_seek_out_of_range();
		t_size backread_depth = (t_size) (m_position_base - m_position);
		t_size delta = pfc::min_t<t_size>(backread_depth,p_bytes-done);
		m_buffer.read(backread_depth,targetptr,delta);
		done += delta;
		m_position += delta;
	}

	//regular read
	if (done < p_bytes)
	{
		t_size bytes_read;
		bytes_read = m_file->read(targetptr+done,p_bytes-done,p_abort);

		m_buffer.write(targetptr+done,bytes_read);

		done += bytes_read;
		m_position += bytes_read;
		m_position_base += bytes_read;
	}

	return done;
}
Пример #14
0
t_size reader_membuffer_base::read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
	p_abort.check_e();
	t_size max = get_buffer_size();
	if (max < m_offset) uBugCheck();
	max -= m_offset;
	t_size delta = p_bytes;
	if (delta > max) delta = max;
	memcpy(p_buffer,(char*)get_buffer() + m_offset,delta);
	m_offset += delta;
	return delta;
}
Пример #15
0
mutexScope::mutexScope(HANDLE hMutex_, abort_callback & abort) : hMutex(hMutex_) {
	HANDLE h[2] = {hMutex, abort.get_abort_event()};
	switch( WaitForMultipleObjects(2, h, FALSE, INFINITE) ) {
	case WAIT_OBJECT_0:
		break; // and enter
	case WAIT_OBJECT_0+1:
		throw exception_aborted();
	default:
		uBugCheck();			
	}
}
Пример #16
0
void input_entry::g_open_for_info_write_timeout(service_ptr_t<input_info_writer> & p_instance,service_ptr_t<file> p_filehint,const char * p_path,abort_callback & p_abort,double p_timeout,bool p_from_redirect) {
	pfc::lores_timer timer;
	timer.start();
	for(;;) {
		try {
			g_open_for_info_write(p_instance,p_filehint,p_path,p_abort,p_from_redirect);
			break;
		} catch(exception_io_sharing_violation) {
			if (timer.query() > p_timeout) throw;
			p_abort.sleep(0.01);
		}
	}
}
Пример #17
0
bool directory_callback_impl::on_entry(filesystem * owner,abort_callback & p_abort,const char * url,bool is_subdirectory,const t_filestats & p_stats) {
	p_abort.check_e();
	if (is_subdirectory) {
		if (m_recur) {
			try {
				owner->list_directory(url,*this,p_abort);
			} catch(exception_io const &) {}
		}
	} else {
		m_data.add_item(pfc::rcnew_t<t_entry>(url,p_stats));
	}
	return true;
}
Пример #18
0
void stream_reader_chunk::flush(abort_callback & p_abort) {
	while(!m_eof) {
		p_abort.check_e();
		t_uint8 temp;
		m_reader->read_lendian_t(temp,p_abort);
		m_buffer_size = temp;
		if (temp != sizeof(m_buffer)) m_eof = true;
		m_buffer_state = 0;
		if (m_buffer_size>0) {
			m_reader->skip_object(m_buffer_size,p_abort);
		}
	}
}
Пример #19
0
t_filesize file::g_transfer(stream_reader * p_src,stream_writer * p_dst,t_filesize p_bytes,abort_callback & p_abort) {
	enum {BUFSIZE = 1024*1024*8};
	pfc::array_t<t_uint8> temp;
	temp.set_size((t_size)pfc::min_t<t_filesize>(BUFSIZE,p_bytes));
	void* ptr = temp.get_ptr();
	t_filesize done = 0;
	while(done<p_bytes) {
		p_abort.check_e();
		t_size delta = (t_size)pfc::min_t<t_filesize>(BUFSIZE,p_bytes-done);
		delta = p_src->read(ptr,delta,p_abort);
		if (delta<=0) break;
		p_dst->write(ptr,delta,p_abort);
		done += delta;
	}
	return done;
}
Пример #20
0
static void index_tracks_helper(const char * p_path,const service_ptr_t<file> & p_reader,const t_filestats & p_stats,playlist_loader_callback::t_entry_type p_type,playlist_loader_callback::ptr p_callback, abort_callback & p_abort,bool & p_got_input)
{
	TRACK_CALL_TEXT("index_tracks_helper");
	if (p_reader.is_empty() && filesystem::g_is_remote_safe(p_path))
	{
		TRACK_CALL_TEXT("remote");
		metadb_handle_ptr handle;
		p_callback->handle_create(handle,make_playable_location(p_path,0));
		p_got_input = true;
		p_callback->on_entry(handle,p_type,p_stats,true);
	} else {
		TRACK_CALL_TEXT("hintable");
		service_ptr_t<input_info_reader> instance;
		input_entry::g_open_for_info_read(instance,p_reader,p_path,p_abort);

		t_filestats stats = instance->get_file_stats(p_abort);

		t_uint32 subsong,subsong_count = instance->get_subsong_count();
		bool bInfoGetError = false;
		for(subsong=0;subsong<subsong_count;subsong++)
		{
			TRACK_CALL_TEXT("subsong-loop");
			p_abort.check();
			metadb_handle_ptr handle;
			t_uint32 index = instance->get_subsong(subsong);
			p_callback->handle_create(handle,make_playable_location(p_path,index));

			p_got_input = true;
			if (! bInfoGetError && p_callback->want_info(handle,p_type,stats,true) )
			{
				file_info_impl info;
				try {
					TRACK_CODE("get_info",instance->get_info(index,info,p_abort));
				} catch(std::exception const & e) {
					bInfoGetError = true;
				}
				p_callback->on_entry_info(handle,p_type,stats,info,true);
			}
			else
			{
				p_callback->on_entry(handle,p_type,stats,true);
			}
		}
	}
}
Пример #21
0
	bool WaitAbortable(HANDLE ev, abort_callback & abort, DWORD timeout) {
		const HANDLE handles[2] = {ev, abort.get_abort_event()};
		SetLastError(0);
		const DWORD status = WaitForMultipleObjects(2, handles, FALSE, timeout);
		switch(status) {
			case WAIT_TIMEOUT:
				PFC_ASSERT( timeout != INFINITE );
				return false;
			case WAIT_OBJECT_0:
				return true;
			case WAIT_OBJECT_0 + 1:
				throw exception_aborted();
			case WAIT_FAILED:
				WIN32_OP_FAIL();
			default:
				uBugCheck();
		}
	}
Пример #22
0
	void SleepAbortable_MsgLoop(abort_callback & abort, DWORD timeout /*must not be INFINITE*/) {
		PFC_ASSERT( timeout != INFINITE );
		const DWORD entry = GetTickCount();
		const HANDLE handles[1] = {abort.get_abort_event()};
		for(;;) {
			const DWORD done = GetTickCount() - entry;
			if (done >= timeout) return;
			SetLastError(0);
			const DWORD status = MsgWaitForMultipleObjects(1, handles, FALSE, timeout - done, QS_ALLINPUT);
			switch(status) {
				case WAIT_TIMEOUT:
					return;
				case WAIT_OBJECT_0:
					throw exception_aborted();
				case WAIT_OBJECT_0 + 1:
					ProcessPendingMessages();
				default:
					throw exception_win32(GetLastError());
			}
		}
	}
Пример #23
0
static bool grab_items_by_path(pfc::list_base_t<metadb_handle_ptr> & p_out,const char * p_path,abort_callback & p_abort)
{
	try {
		pfc::string8 path;
		filesystem::g_get_canonical_path(p_path,path);
		p_out.remove_all();
		service_ptr_t<input_info_reader> reader;
		input_entry::g_open_for_info_read(reader,0,path,p_abort);

		static_api_ptr_t<metadb> l_metadb;
		
		const t_uint32 count = reader->get_subsong_count();
		for(t_uint32 n=0;n<count;n++) {
			p_abort.check_e();
			metadb_handle_ptr ptr;
			l_metadb->handle_create(ptr,make_playable_location(path,reader->get_subsong(n)));
			p_out.add_item(ptr);
		}

		return p_out.get_count() > 0;
	} catch(std::exception const &) {return false;}
}
Пример #24
0
	void open_path_helper(input_decoder::ptr & p_input, file::ptr p_file, const char * path,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints) {
		p_abort.check();
		p_input.release();

		TRACK_CODE("input_entry::g_open_for_decoding",
			input_entry::g_open_for_decoding(p_input,p_file,path,p_abort,p_from_redirect)
			);

		
		if (!p_skip_hints) {
			try {
				static_api_ptr_t<metadb_io>()->hint_reader(p_input.get_ptr(),path,p_abort);
			} catch(exception_io_data) {
				//Don't fail to decode when this barfs, might be barfing when reading info from another subsong than the one we're trying to decode etc.
				p_input.release();
				if (p_file.is_valid()) p_file->reopen(p_abort);
				TRACK_CODE("input_entry::g_open_for_decoding",
					input_entry::g_open_for_decoding(p_input,p_file,path,p_abort,p_from_redirect)
					);
			}
		}
	}
t_size stream_reader_buffered::read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
	if (p_bytes <= m_bufferRemaining) {
		memcpy( p_buffer, m_bufferPtr, p_bytes );
		m_bufferRemaining -= p_bytes;
		m_bufferPtr += p_bytes;
		return p_bytes;
	}
	
	p_abort.check();
	char * output = (char*) p_buffer;
	t_size output_ptr = 0;

	while(output_ptr < p_bytes) {
		{
			t_size delta = pfc::min_t(p_bytes - output_ptr, m_bufferRemaining);
			if (delta > 0)
			{
				memcpy(output + output_ptr, m_bufferPtr, delta);
				output_ptr += delta;
				m_bufferPtr += delta;
				m_bufferRemaining -= delta;
			}
		}

		if (m_bufferRemaining == 0)
		{
			t_size bytes_read;
			bytes_read = m_base->read(m_buffer.get_ptr(), m_buffer.get_size(), p_abort);
			m_bufferPtr = m_buffer.get_ptr();
			m_bufferRemaining = bytes_read;

			if (m_bufferRemaining == 0) break;
		}
		
	}		

	return output_ptr;
}
Пример #26
0
	void WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort) {
		const HANDLE handles[2] = {ev, abort.get_abort_event()};
		for(;;) {
			SetLastError(0);
			const DWORD status = MsgWaitForMultipleObjects(2, handles, FALSE, INFINITE, QS_ALLINPUT);
			switch(status) {
				case WAIT_TIMEOUT:
					PFC_ASSERT(!"How did we get here?");
					uBugCheck();
				case WAIT_OBJECT_0:
					return;
				case WAIT_OBJECT_0 + 1:
					throw exception_aborted();
				case WAIT_OBJECT_0 + 2:
					ProcessPendingMessages();
					break;
				case WAIT_FAILED:
					WIN32_OP_FAIL();
				default:
					uBugCheck();
			}
		}
	}
Пример #27
0
static void track_indexer__g_get_tracks_wrap(const char * p_path,const service_ptr_t<file> & p_reader,const t_filestats & p_stats,playlist_loader_callback::t_entry_type p_type,playlist_loader_callback::ptr p_callback, abort_callback & p_abort) {
	bool got_input = false;
	bool fail = false;
	try {
		index_tracks_helper(p_path,p_reader,p_stats,p_type,p_callback,p_abort, got_input);
	} catch(exception_aborted) {
		throw;
	} catch(exception_io_unsupported_format) {
		fail = true;
	} catch(std::exception const & e) {
		fail = true;
		console::formatter() << "could not enumerate tracks (" << e << ") on:\n" << file_path_display(p_path);
	}
	if (fail) {
		if (!got_input && !p_abort.is_aborting()) {
			if (p_type == playlist_loader_callback::entry_user_requested)
			{
				metadb_handle_ptr handle;
				p_callback->handle_create(handle,make_playable_location(p_path,0));
				p_callback->on_entry(handle,p_type,p_stats,true);
			}
		}
	}
}
Пример #28
0
void reader_membuffer_base::seek(t_filesize position,abort_callback & p_abort) {
	p_abort.check_e();
	t_filesize max = get_buffer_size();
	if (position == filesize_invalid || position > max) throw exception_io_seek_out_of_range();
	m_offset = (t_size)position;
}
Пример #29
0
		void load_database_t::load_cache(HWND wnd, ipod_device_ptr_ref_t p_ipod, bool b_CheckIfFilesChanged, threaded_process_v2_t & p_status, abort_callback & p_abort)
		{
			pfc::string8 base;
			p_ipod->get_root_path(base);

			metadb_handle_list handlestoread(m_handles);

			pfc::string8 cachePath = base;
			cachePath << "metadata_cache.fpl";

			//We want to hint from main thread to avoid annoyances
			static_api_ptr_t<main_thread_callback_manager> p_main_thread;
			p_status.update_text("Loading metadata cache");
			service_ptr_t<t_main_thread_load_cache_v2_t> p_cache_loader = new service_impl_t<t_main_thread_load_cache_v2_t>
				(base);

			p_cache_loader->callback_run();
			//p_main_thread->add_callback(p_cache_loader);
			if (!p_cache_loader->m_signal.wait_for(-1))
				throw pfc::exception("Cache read timeout!");
			if (!p_cache_loader->m_ret)
				throw pfc::exception(pfc::string8() << "Error reading metadata cache: " << p_cache_loader->m_error);

			p_status.update_text("Checking files for changes");
			//pfc::hires_timer timer2;
			//timer2.start();
			t_size n = handlestoread.get_count(), count = n;
			for (; n; n--)
			{
				if (p_ipod->mobile || !b_CheckIfFilesChanged)
				{
					if (handlestoread[n - 1]->is_info_loaded_async())
						handlestoread.remove_by_idx(n - 1);
					m_tracks[n - 1]->m_runtime_filestats.m_timestamp = filetimestamp_invalid;
					if (m_tracks[n - 1]->original_timestamp_valid)
						m_tracks[n - 1]->m_runtime_filestats.m_timestamp = m_tracks[n - 1]->original_timestamp;
					else if (m_tracks[n - 1]->lastmodifiedtime)
						m_tracks[n - 1]->m_runtime_filestats.m_timestamp = filetime_time_from_appletime(m_tracks[n - 1]->lastmodifiedtime);
					m_tracks[n - 1]->m_runtime_filestats.m_size = m_tracks[n - 1]->size;
				}
				else
				{
					if (true)
					{
						if (n % 20 == 0)
							p_abort.check();
						t_filestats stats = handlestoread[n - 1]->get_filestats();
						const char * path = handlestoread[n - 1]->get_path();
						if (!stricmp_utf8_max(path, "file://", 7))
						{
							path += 7;
							win32::handle_ptr_t p_file =
								CreateFile(pfc::stringcvt::string_os_from_utf8(path), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
							if (p_file.is_valid())
							{
								t_filestats newstats = filestats_invalid;
								GetFileSizeEx(p_file, (PLARGE_INTEGER)&newstats.m_size);
								GetFileTime(p_file, NULL, NULL, (LPFILETIME)&newstats.m_timestamp);
								m_tracks[n - 1]->m_runtime_filestats = newstats;
								if (handlestoread[n - 1]->is_info_loaded_async())
								{
									t_uint64 hour = 60 * 60;
									hour *= 10000000;
									if (stats.m_size == newstats.m_size && (stats.m_timestamp == newstats.m_timestamp || _abs64(newstats.m_timestamp - stats.m_timestamp) == hour) && newstats.m_size != filesize_invalid && newstats.m_timestamp != filetimestamp_invalid)
										handlestoread.remove_by_idx(n - 1);
								}
							}
						}
					}
				}
				p_status.update_progress_subpart_helper(count - n + 1, count);
			}
			//console::formatter() << "info checked in: " << pfc::format_time_ex(timer2.query(),6);

			if (handlestoread.get_count())
			{
				p_status.update_text("Loading file info");
				//static_api_ptr_t<main_thread_callback_manager> p_main_thread;

				service_ptr_t<t_main_thread_scan_file_info> p_info_loader = new service_impl_t<t_main_thread_scan_file_info>
					(handlestoread, metadb_io::load_info_force, wnd);
				p_main_thread->add_callback(p_info_loader);
				if (!p_info_loader->m_signal.wait_for(-1))
					throw pfc::exception("File info reading timeout!");
				if (p_info_loader->m_ret == metadb_io::load_info_aborted)
					throw pfc::exception("File info read was aborted");
			}

			p_abort.check();

		}
Пример #30
0
/** Does /not/ throw exception_io_data, unlike normal */
pfc::string8 SpotifySession::waitForLogin(abort_callback & p_abort) {
	while (WAIT_OBJECT_0 != WaitForSingleObject(loggedInEvent, 200))
		if (p_abort.is_aborting())
			return "user aborted";
	return loginResult;
}