/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
 *            drumkitloader.cc
 *
 *  Thu Jan 17 20:54:14 CET 2013
 *  Copyright 2013 Bent Bisballe Nyeng
 *  deva@aasimon.org
 ****************************************************************************/

/*
 *  This file is part of DrumGizmo.
 *
 *  DrumGizmo is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  DrumGizmo is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with DrumGizmo; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */
#include "drumkitloader.h"

#include <hugin.hpp>

#include "drumkitparser.h"
#include "drumgizmo.h"

DrumKitLoader::DrumKitLoader()
	: semaphore("drumkitloader")
	, framesize(0)
{
	run();
	run_semaphore.wait(); // Wait for the thread to actually start.
}

DrumKitLoader::~DrumKitLoader()
{
	DEBUG(loader, "~DrumKitLoader() pre\n");

	if(running)
	{
		framesize_semaphore.post();
		stop();
	}

	DEBUG(loader, "~DrumKitLoader() post\n");
}

void DrumKitLoader::stop()
{
	{
		MutexAutolock l(mutex);
		load_queue.clear();
	}

	running = false;
	semaphore.post();
	wait_stop();
}

void DrumKitLoader::skip()
{
	MutexAutolock l(mutex);
	load_queue.clear();
}

void DrumKitLoader::setFrameSize(size_t framesize)
{
	DEBUG(loader, "%s pre\n", __PRETTY_FUNCTION__);

	{
		MutexAutolock l(mutex);
		this->framesize = framesize;
		framesize_semaphore.post(); // Signal that the framesize has been set.
	}

	DEBUG(loader, "%s post\n", __PRETTY_FUNCTION__);
}

bool DrumKitLoader::isDone()
{
	MutexAutolock l(mutex);
	return load_queue.size() == 0;
}

void DrumKitLoader::loadKit(DrumKit *kit)
{
	MutexAutolock l(mutex);

	DEBUG(loader, "Create AudioFile queue from DrumKit\n");

	total_num_audiofiles = 0;// For UI Progress Messages

	{ // Count total number of files that need loading:
		Instruments::iterator i = kit->instruments.begin();
		while(i != kit->instruments.end())
		{
			Instrument *instr = *i;
			total_num_audiofiles += instr->audiofiles.size();
			++i;
		}
	}

	fraction = total_num_audiofiles / 200;
	if(fraction == 0)
	{
		fraction = 1;
	}

	{ // Now actually queue them for loading:
		Instruments::iterator i = kit->instruments.begin();
		while(i != kit->instruments.end())
		{
			Instrument *instr = *i;

			std::vector<AudioFile*>::iterator af = instr->audiofiles.begin();
			while(af != instr->audiofiles.end())
			{
				AudioFile *audiofile = *af;
				load_queue.push_back(audiofile);
				af++;
			}

			++i;
		}
	}

	loaded = 0; // For UI Progress Messages

	DEBUG(loader, "Queued %d (size: %d) AudioFiles for loading.\n",
	      (int)total_num_audiofiles, (int)load_queue.size());

	semaphore.post(); // Start loader loop.
}

void DrumKitLoader::thread_main()
{
	running = true;

	run_semaphore.post(); // Signal that the thread has been started.

	framesize_semaphore.wait(); // Wait until the framesize has been set.

	while(running)
	{
		size_t size;
		{
			MutexAutolock l(mutex);
			size = load_queue.size();
		}

		// Only sleep if queue is empty.
		if(size == 0)
		{
			semaphore.wait();
		}

		std::string filename;
		{
			MutexAutolock l(mutex);
			if(load_queue.size() == 0)
			{
				continue;
			}
			AudioFile *audiofile = load_queue.front();
			load_queue.pop_front();
			filename = audiofile->filename;
			size_t preload_size = framesize * CHUNK_MULTIPLIER + framesize;
			if(preload_size < 1024)
			{
	      preload_size = 1024;
			}
			(void)preload_size;
			audiofile->load(ALL_SAMPLES); // Note: Change this to enable diskstreaming
		}

		loaded++;

		if(loaded % fraction == 0 || loaded == total_num_audiofiles)
		{
			LoadStatusMessage *ls = new LoadStatusMessage();
			ls->number_of_files = total_num_audiofiles;
			ls->numer_of_files_loaded = loaded;
			ls->current_file = filename;
			msghandler.sendMessage(MSGRCV_UI, ls);
		}
	}

	DEBUG(loader, "Loader thread finished.");
}