view sv/main/EasaierSessionManager.cpp @ 276:a9af42a93073

New property box for time stretching some labels updated
author benoitrigolleau
date Wed, 15 Oct 2008 16:18:18 +0000
parents 119d89cb65cb
children 8bdfbd9ad418
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */

/*	Sound Access	
		EASAIER client application.	
		Silogic 2007. Laure Bajard. 
	
	This program 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.  See the file    
	COPYING included with this distribution for more information.
*/

#include "EasaierSessionManager.h"

#include <QUrl>
#include <QMessageBox>
#include <QTextStream>
#include <iostream>
#include <QStatusBar>
#include <vector>

#include <QApplication>
#include <Qt>
#include <QUrl>

#include "layer/Layer.h"
#include "base/TempDirectory.h"
#include "data/fileio/AudioSourceInfoReader.h"
#include "data/fileio/ModelReader.h"
#include "data/fileio/QueryConfigReader.h"
#include "data/fileio/SparqlResultsReader.h"
#include "data/fileio/SparqlRelatedMediaReader.h"
#include "data/fileio/VideoFileReaderFactory.h"
#include "data/model/WaveFileModel.h"
#include "main/MainWindow.h"
#include "widgets/QueryResultsWidget.h"
#include "widgets/RelatedMediaWidget.h"
#include "base/PropertyContainer.h"
#include "data/fileio/AudioFileReaderFactory.h"
#include "widgets/SpeechRecognitionUI.h"

#include "widgets/SpeechFileHandler.h"
#include <QMessageBox>

#include "data/fileio/FileParserThread.h"

EasaierSessionManager::EasaierSessionManager(HttpClient* httpClient) : QObject(),
	m_fileName(""),
	m_httpClient(httpClient),
	m_document(0),
	m_audioSourceInfoModel(0),
	m_queryModel(0),
	m_currentPane(0)
{
	connect(m_httpClient, SIGNAL(requestFinished(int, bool)), this, SLOT(fileLoaded(int, bool)));
}

EasaierSessionManager::~EasaierSessionManager()
{
	closeSession();
	m_httpClient = 0;
}

bool EasaierSessionManager::newSession()
{
	closeSession();

	m_queryModel = new QueryModel();
	QString filename = "/data/query/queryfield.xml";
	QString query = m_httpClient->getServletName() + "?theme=getFile&fileName=data/query/queryfield.xml";
	loadFile(query, filename, LoadedFile::QUERY_CONFIG);

	return true;
}

bool EasaierSessionManager::openSession(Document *document)
{
	newSession();

	m_fileName = document->getAudioSourceInfoFileName();
	m_document = document;

	//QString params = "&identification=" + m_fileName;
	QString params = "&signal=" + m_fileName;

	//QString query = m_httpClient->getServletName() + "?theme=infoFile"+params;
	QString query = m_httpClient->getServletName() + "?theme=musicBySignal"+params;
	QString filename = "/easaier/servlet/musicBySignal";
	loadFile(query, filename, LoadedFile::AUDIO_SOURCE_INFO);

	//get related media
	query = m_httpClient->getServletName() + "?theme=relatedMedia" + params;
	filename = "/easaier/servlet/relatedMedia";
	loadFile(query, filename, LoadedFile::RELATED_MEDIA_LIST);

	return true;
}

bool EasaierSessionManager::openAudioInfoFile(Document *document)
{
	closeFile();

	m_fileName = document->getAudioSourceInfoFileName();
	m_document = document;

	//QString params = "&identification=" + m_fileName;
	QString params = "&signal=" + m_fileName;

	//get infofile
	//QString query = m_httpClient->getServletName() + "?theme=infoFile" + params;
	QString query = m_httpClient->getServletName() + "?theme=musicBySignal" + params;
	
	//QString filename = "/easaier/servlet/infoFile";
	QString filename = "/easaier/servlet/musicBySignal";
	
	loadFile(query, filename, LoadedFile::AUDIO_SOURCE_INFO);
	
	//get related media

	query = m_httpClient->getServletName() + "?theme=relatedMedia" + params;
	filename = "/easaier/servlet/relatedMedia";
	loadFile(query, filename, LoadedFile::RELATED_MEDIA_LIST);

	return true;
}

void EasaierSessionManager::closeFile()
{
	m_audioSourceInfoModel = 0;

	while (!m_loadFile.empty())
	{
		m_loadFile.begin()->second->close();
		delete m_loadFile.begin()->second;
	    m_loadFile.erase(m_loadFile.begin());
	}

	m_modelLoaded.clear();
}

void EasaierSessionManager::closeSession()
{
	closeFile();

	m_fileName = "";
	m_document = 0;
	
	if (m_queryModel)
	{
		delete m_queryModel;
		m_queryModel = 0;
	}
}

void EasaierSessionManager::loadFile(const QString& queryAux, const QString& filename, LoadedFile::FileType type, const QString& postPath)
{
	QFile * postFile = 0;

	if ((queryAux == 0) || (filename == 0))
		return;

	if (m_httpClient->getHost() == "")
		return;

	QUrl url(queryAux);
	QString query = QString(url.toEncoded());

	QString directory = filename.left(filename.lastIndexOf("/"));
	QString file = filename.right(filename.length() - filename.lastIndexOf("/"));

	if (directory.left(1) == "/")
	{
		directory.remove(0, 1);
	}else if (directory.left(6) == "file:/")
	{
		directory.remove(0, 6);
	}

	//create the subdirectory in local
	QString localPath = TempDirectory::getInstance()->getSubDirectoryPath(directory);
	localPath.append(file);

	LoadedFile* newFile = new LoadedFile(localPath);
	newFile->setFileType(type);
	newFile->setUri(filename);

	if (postPath != "")
	{
		postFile = new QFile(postPath);
	}
	int index;
	index =  m_httpClient->get(query,newFile );

	std::cerr << "Ask for file : GET " << query.toStdString() << " - index : " << index << std::endl;

	m_loadFile[index] = newFile;

	if (type == LoadedFile::QUERY_RESULTS)
		MainWindow::instance()->statusBar()->showMessage(tr("Querying database..."));
	else if (type == LoadedFile::QUERY_CONFIG)
		MainWindow::instance()->statusBar()->showMessage(tr("Asking for query config..."));
	else
		MainWindow::instance()->statusBar()->showMessage(tr("Loading File : %1").arg(filename));
}

void EasaierSessionManager::loadFile(const QByteArray& payload , const QString& filename, LoadedFile::FileType type, const QString& postPath)
{
	QFile * postFile = 0;

	if (m_httpClient->getHost() == "")
		return;


	QString directory = filename.left(filename.lastIndexOf("/"));
	QString file = filename.right(filename.length() - filename.lastIndexOf("/"));

	if (directory.left(1) == "/")
	{
		directory.remove(0, 1);
	}

	//create the subdirectory in local
	QString localPath = TempDirectory::getInstance()->getSubDirectoryPath(directory);
	localPath.append(file);

	LoadedFile* newFile = new LoadedFile(localPath);
	newFile->setFileType(type);
	newFile->setUri(filename);

	int index;

	// build the header
	QHttpRequestHeader header("POST", m_httpClient->getServletName());
	header.setValue("Host", m_httpClient->getHost());
	header.setValue("Port", QString::number(m_httpClient->getHostPort()));
    header.setContentType("multipart/form-data; boundary=7d44e178b0434");
    header.setValue("Cache-Control", "no-cache");    
	header.setValue("Accept","*/*"); 
    header.setContentLength(payload.length());
	//

	index =  m_httpClient->request(header, payload, newFile);

	std::cerr << "Ask for file : POST " << " - index : " << index << std::endl;

	m_loadFile[index] = newFile;

	if (type == LoadedFile::QUERY_RESULTS)
		MainWindow::instance()->statusBar()->showMessage(tr("Querying database..."));
	else if (type == LoadedFile::QUERY_CONFIG)
		MainWindow::instance()->statusBar()->showMessage(tr("Asking for query config..."));
	else
		MainWindow::instance()->statusBar()->showMessage(tr("Loading File : %1").arg(filename));
}

void EasaierSessionManager::fileLoaded(int index, bool error)
{
	QString errorString = m_httpClient->errorString();
	std::map<int , LoadedFile*>::iterator iter = m_loadFile.find(index);
	if (iter == m_loadFile.end())
	{
		std::cerr << "fileLoaded() : file " << index << " not found. " << std::endl;
		return;
	}
	if (error)
	{
		QApplication::restoreOverrideCursor();
		QMessageBox::critical(MainWindow::instance(), tr("Download Failed"), m_httpClient->errorString());
		return; 
	}
	bool read = false;
	
	//retreive loaded file
	LoadedFile* loadedFile = iter->second;
	loadedFile->close();
	
	//save type and filename for reading
	LoadedFile::FileType type = loadedFile->getFileType();
	QString filename = loadedFile->fileName();
	QString uri = loadedFile->getUri();
	
	//delete de file and erase from the loaded file queue
	delete loadedFile;
	m_loadFile.erase(iter);
	loadedFile = 0;

	std::cerr << "fileLoaded() : file loaded, start to read file " << index << std::endl;

	if ((type == LoadedFile::QUERY_RESULTS) || (type == LoadedFile::QUERY_CONFIG))
	{
		MainWindow::instance()->statusBar()->clearMessage();
	}
	else
	{
		QString name = filename.right(filename.length() - filename.lastIndexOf("/"));
		MainWindow::instance()->statusBar()->showMessage(tr("File Loaded : %1").arg(name), 3000);
	}

	//read and load (in m_document) the file according to its type 
	switch (type) {

		case LoadedFile::AUDIO_SOURCE_INFO :
		{
		    m_audioSourceInfoModel = new AudioSourceInfoModel();
			AudioSourceInfoReader audioSourceInfoReader(m_audioSourceInfoModel);
			read = audioSourceInfoReader.parse(filename);
			if (read && !m_audioSourceInfoModel->isEmpty() )
			{
				m_document->setAudioSourceInfoModel(m_audioSourceInfoModel);
				loadRelatedModel();
			}
		    break;
		}
		case LoadedFile::MODEL :
		{
			QString modelName = "";
			if (uri.left(5) == "/data")
			{
				modelName = m_audioSourceInfoModel->getKey("file:/" + uri);
			}
			else
			{
				modelName = uri.right(uri.length() - uri.lastIndexOf('/') -1);
				modelName.remove(".txt");
			}

			read = addModelToLayers(modelName, filename);

		    break;
		}
		case LoadedFile::METADATA :
		{
			ModelReader modelReader(m_document,0, m_currentPane);
			read = modelReader.parse(filename);

		    break;
		}
		case LoadedFile::QUERY_CONFIG :
		{
			QueryConfigReader reader(m_queryModel);
			bool ok = reader.parse(filename);

			if (ok)
				emit queryModelLoaded(m_queryModel);

			read = ok;
		    break;
		}
		case LoadedFile::QUERY_RESULTS :
		{
			/*QueryResultsWidget* resultsWidget = MainWindow::instance()->getQueryResultsWidget();
			resultsWidget->reset();

			if (resultsWidget)
			{
				SparqlResultsReader rd;
				connect(rd.getHandler(), SIGNAL(newResultDetected ()), MainWindow::instance(),SLOT(createNewResultItem()),Qt::QueuedConnection);
				connect(rd.getHandler(), SIGNAL(newInfoResultDetected(QString,QString)), MainWindow::instance(),SLOT(addInfoIntoResultItem(QString,QString)),Qt::QueuedConnection);
				connect(rd.getHandler(), SIGNAL(endOfResultDetected ()), MainWindow::instance(),SLOT(saveCurrentResultItem()),Qt::QueuedConnection); //Qt::DirectConnection
				connect(rd.getHandler(), SIGNAL(endOfDocumentDetected ()), MainWindow::instance(),SLOT(displayResultList()),Qt::QueuedConnection);
				
				read = rd.parse(filename);
			}*/
			FileParserThread *myThread = new FileParserThread(filename);
			myThread->start();
			read = true;
		    break;
		}
		case LoadedFile::RELATED_MEDIA_LIST :
		{
			m_relMediaList.clear();
			SparqlRelatedMediaReader reader(&m_relMediaList);
			read = reader.parse(filename);
			importRelatedMedia(&m_relMediaList);
			break;
		}
		case LoadedFile::RELATED_MEDIA :
		{
			read = true;
			RelatedMediaWidget* relMediaWidget = MainWindow::instance()->getRelatedMediaWidget();
			relMediaWidget->addRelatedMedia(filename, m_relMediaList);
			break;
		}
		case LoadedFile::VOCAL_QUERY :
		{
			QFile file;
			QXmlInputSource *inputSource;
			QXmlSimpleReader reader; 
			SpeechFileHandler handler; 
			file.setFileName(filename); 
			inputSource= new QXmlInputSource(&file); 
			reader.setContentHandler(&handler); 
			read=reader.parse(inputSource); 
			MainWindow::instance()->getSpeechRecognitionUI()->setResult(handler.getResult());
		}
		default: break;
	}

	//if the file could not be read by any reader
	if (!read)
	{
		QFile file(filename);
		if (file.open(QFile::ReadOnly)) {
			QApplication::restoreOverrideCursor();
			QMessageBox::critical(MainWindow::instance(), tr("Download Error"), file.readAll());
		}
	}
	else {
		std::cerr << "fileLoaded() : " << index << " all successful. " << std::endl;
	}
	QApplication::restoreOverrideCursor();
}

void EasaierSessionManager::loadRelatedModel()
{
	std::set<Layer *> layers = m_document->getLayers();
	std::set<Layer *>::iterator iter;

	std::set<QString> loadedModel;

	for (iter=layers.begin(); iter != layers.end(); iter++)
	{
		Layer * layer = *iter;

		QString modelName	= layer->getModelName();
		if (layer->getLayerPresentationName() == "Waveform")
		{
			modelName = "available_as";
			int modelId = 1;
			layer->setModelName(modelName);
			layer->setModelId(modelId);
			
			QStringList* uriList = m_audioSourceInfoModel->getInfo(modelName);
			if (!uriList)
				return;
			QString uri = uriList->at(0);
			uri.remove("file:/");
			uri.replace(".wma", ".mp3");
			
			QString query = m_httpClient->getServletName() + "?theme=getFile&fileName="+uri;

			std::set<QString>::iterator iterModel = m_modelLoaded.find(uri);

			if (iterModel == m_modelLoaded.end())
			{
				m_modelLoaded.insert(uri);	
				loadFile(query, uri, LoadedFile::MODEL);
			}
		} else if (modelName != "")
		{
			std::set<QString>::iterator iterModel = m_modelLoaded.find(modelName);

			if (iterModel == m_modelLoaded.end())
			{
				QString query = m_httpClient->getServletName() + "?theme=getTimeLine&signal="+m_document->getAudioSourceInfoFileName()+"&event_label="+modelName;
				QString file = "metadata/" + modelName + ".txt";

				m_modelLoaded.insert(modelName);	
				loadFile(query, file, LoadedFile::MODEL);
			}
		}
	}
}

bool EasaierSessionManager::addModelToLayers(const QString& name, const QString& filename)
{
	std::set<Layer *> layers = m_document->getLayers();
	std::set<Layer *>::iterator iter;

	std::map<QString, Model *> addedModel;

	bool ok = false;

	for (iter=layers.begin(); iter != layers.end(); iter++)
	{
		Layer * layer = *iter;

		QString modelName	= layer->getModelName();
		QString modelId		= QString::number(layer->getModelId());

		if (modelName == name)
		{
			std::map<QString, Model *>::iterator iterModel;
			iterModel = addedModel.find(modelName);

			if (iterModel == addedModel.end())
			{
				QString extension = filename.right(filename.length()-filename.lastIndexOf(".")-1);
				extension = extension.toLower();
				if (AudioFileReaderFactory::isKnownExtensions(extension))
				{
					WaveFileModel *model = new WaveFileModel(filename);
					m_document->setMainModel(model);
					addedModel[modelName] = (Model* ) model;
					ok = true;
					emit audioFileLoaded();
				}
#ifdef HAVE_VIDEO
				else if (VideoFileReaderFactory::isKnownExtensions(extension)) 
				{
					ok = !(MainWindow::instance()->openVideoFile(filename, MainWindow::ReplaceMainModel));
					emit audioFileLoaded();
				}
#endif
				else
				{
					ModelReader modelReader(m_document, layer);
					ok = modelReader.parse(filename);
				}
			}
			else
			{
				Model* model = iterModel->second;
				m_document->addImportedModel(model);
				m_document->setModel(layer, model);
			}
		}
	}

	return ok;
}

void EasaierSessionManager::importMetadata(const QString& filename, Pane* pane)
{
	QString query = m_httpClient->getServletName() + "?theme=getTimeLine&signal="+m_document->getAudioSourceInfoFileName()+"&event_label="+filename;

	QString file = "metadata/" + filename + ".txt";

	loadFile( query, file, LoadedFile::METADATA);

	m_currentPane = pane;
}

void EasaierSessionManager::importRelatedMedia(std::map<QString, QString> *relMediaList)
{
	QString filename;
	QString query;

	std::map<QString, QString>::iterator iter;
	for (iter = relMediaList->begin(); iter != relMediaList->end(); iter++)
	{
		filename = iter->first;
		filename.remove("file:/");

		query = m_httpClient->getServletName() + "?theme=getFile&fileName=" + filename;

		loadFile( query, filename, LoadedFile::RELATED_MEDIA);
	}
}

void EasaierSessionManager::queryDatabase(const QString& themeName)
{
	
	QueryThemeModel *themeModel = (m_queryModel->getThemes()).find(themeName)->second;
	QString postFilePath = "";

	//for the post
	QString boundary="7d44e178b0434";
	QString endline="\r\n";
	QString start_delim="--"+boundary+endline;
	QString cont_disp_str="Content-Disposition: form-data;";

	QByteArray *payload = new QByteArray();
	QDataStream data_stream(payload, QFile::WriteOnly | QFile::Unbuffered);
	/////////

	QString param = start_delim + cont_disp_str + "name=" + "\"theme\"" + endline+endline+themeName+endline;
	data_stream.writeRawData(param.toStdString().c_str(),param.toStdString().length());

	if(themeModel!=0){

		PropertyContainer::PropertyList propertyList = themeModel->getProperties();
		for(int i=0; i< ((int) propertyList.size());i++){
			if (themeModel->getPropertyType(propertyList[i]) == PropertyContainer::FileProperty)
			{
				// We are here dealing with a filePath
				postFilePath = themeModel->getPropertyValue(propertyList[i]);
				if(postFilePath!=""){
					QString only_filename = postFilePath.section( '/', -1 );
					QString param = start_delim + cont_disp_str + "name=" + "\""+propertyList[i]+"\""+"; filename="+"\""+only_filename+"\""+endline+"Content-Type: application/octet-stream"+endline+endline;
					data_stream.writeRawData(param.toStdString().c_str(),param.toStdString().length());
					
					QFile file(postFilePath);
					if (file.open( QFile::ReadOnly )) {
						while (!file.atEnd()) {
							QByteArray line = file.readLine();
							data_stream.writeRawData(line.data(),line.length());
						}
						file.close();
					}
				}
			}
			else{
				// Normal parameter
				QString param = start_delim + cont_disp_str + "name=" + "\"" + propertyList[i]+ "\"" + endline+endline+themeModel->getPropertyValue(propertyList[i])+endline;
				data_stream.writeRawData(param.toStdString().c_str(),param.toStdString().length());
			}
		}
		//bug for the last field - add an unused field
		QString param = start_delim + cont_disp_str + "name=" + "\"toto\"" + endline+endline+""+endline;
		data_stream.writeRawData(param.toStdString().c_str(),param.toStdString().length());

		QString stop_delim=endline+"--"+boundary+"--"+endline;
		data_stream.writeRawData(stop_delim.toStdString().c_str(),stop_delim.toStdString().length());
	}
	QString filename = "/easaier/servlet/"+themeName;
	
	QApplication::setOverrideCursor( Qt::WaitCursor );
	loadFile(*payload, filename, LoadedFile::QUERY_RESULTS, postFilePath);
}


void EasaierSessionManager::speechRecognition(const QString& themeName)
{
	
	QString postFilePath = "";

	//for the post
	QString boundary="7d44e178b0434";
	QString endline="\r\n";
	QString start_delim="--"+boundary+endline;
	QString cont_disp_str="Content-Disposition: form-data;";

	QByteArray *payload = new QByteArray();
	QDataStream data_stream(payload, QFile::WriteOnly | QFile::Unbuffered);
	/////////


	QString param = start_delim + cont_disp_str + "name=" + "\"theme\"" + endline+endline+themeName+endline;
	data_stream.writeRawData(param.toStdString().c_str(),param.toStdString().length());

	param = start_delim + cont_disp_str + "name=" + "\"" + "language"+ "\"" + endline+endline+MainWindow::instance()->getSpeechRecognitionUI()->getLanguage().toStdString().c_str()+endline;
	data_stream.writeRawData(param.toStdString().c_str(),param.toStdString().length());

	// We are here dealing with a filePath
	postFilePath = "c:/test.wav";
	if(postFilePath!=""){
		QString only_filename = postFilePath.section( '/', -1 );
		QString param = start_delim + cont_disp_str + "name=" + "\"file\""+"; filename="+"\""+only_filename+"\""+endline+"Content-Type: application/octet-stream"+endline+endline;
		data_stream.writeRawData(param.toStdString().c_str(),param.toStdString().length());
					
		QFile file(postFilePath);
		if (file.open( QFile::ReadOnly )) {
			while (!file.atEnd()) {
				QByteArray line = file.readLine();
				data_stream.writeRawData(line.data(),line.length());
			}
			file.close();
		}
	}
		
	data_stream.writeRawData(param.toStdString().c_str(),param.toStdString().length());

	QString stop_delim=endline+"--"+boundary+"--"+endline;
	data_stream.writeRawData(stop_delim.toStdString().c_str(),stop_delim.toStdString().length());

	QString filename = "/easaier/servlet/"+themeName;
	
	QApplication::setOverrideCursor( Qt::WaitCursor );
	loadFile(*payload, filename, LoadedFile::VOCAL_QUERY, postFilePath);
}