예제 #1
0
void SpotifyService::EnsureServerCreated(const QString& username,
                                         const QString& password) {
  if (server_ && blob_process_) {
    return;
  }

  delete server_;
  server_ = new SpotifyServer(this);

  connect(
      server_,
      SIGNAL(LoginCompleted(bool, QString, pb::spotify::LoginResponse_Error)),
      SLOT(LoginCompleted(bool, QString, pb::spotify::LoginResponse_Error)));
  connect(server_, SIGNAL(PlaylistsUpdated(pb::spotify::Playlists)),
          SLOT(PlaylistsUpdated(pb::spotify::Playlists)));
  connect(server_, SIGNAL(InboxLoaded(pb::spotify::LoadPlaylistResponse)),
          SLOT(InboxLoaded(pb::spotify::LoadPlaylistResponse)));
  connect(server_, SIGNAL(StarredLoaded(pb::spotify::LoadPlaylistResponse)),
          SLOT(StarredLoaded(pb::spotify::LoadPlaylistResponse)));
  connect(server_,
          SIGNAL(UserPlaylistLoaded(pb::spotify::LoadPlaylistResponse)),
          SLOT(UserPlaylistLoaded(pb::spotify::LoadPlaylistResponse)));
  connect(server_, SIGNAL(PlaybackError(QString)),
          SIGNAL(StreamError(QString)));
  connect(server_, SIGNAL(SearchResults(pb::spotify::SearchResponse)),
          SLOT(SearchResults(pb::spotify::SearchResponse)));
  connect(server_, SIGNAL(ImageLoaded(QString, QImage)),
          SIGNAL(ImageLoaded(QString, QImage)));
  connect(server_,
          SIGNAL(SyncPlaylistProgress(pb::spotify::SyncPlaylistProgress)),
          SLOT(SyncPlaylistProgress(pb::spotify::SyncPlaylistProgress)));
  connect(server_,
          SIGNAL(ToplistBrowseResults(pb::spotify::BrowseToplistResponse)),
          SLOT(ToplistLoaded(pb::spotify::BrowseToplistResponse)));

  server_->Init();

  login_task_id_ = app_->task_manager()->StartTask(tr("Connecting to Spotify"));

  QString login_username = username;
  QString login_password = password;

  if (username.isEmpty()) {
    QSettings s;
    s.beginGroup(kSettingsGroup);

    login_username = s.value("username").toString();
    login_password = QString();
  }

  server_->Login(login_username, login_password, bitrate_,
                 volume_normalisation_);

  StartBlobProcess();
}
SpotifyResolver::SpotifyResolver(SpotifyServer* spotify, QObject* parent)
    : Resolver(parent),
      spotify_(spotify),
      next_id_(0) {
  connect(spotify_, SIGNAL(SearchResults(spotify_pb::SearchResponse)),
          SLOT(SearchFinished(spotify_pb::SearchResponse)));
}
예제 #3
0
void SpotifyServer::MessageArrived(const pb::spotify::Message& message) {
  if (message.has_login_response()) {
    const pb::spotify::LoginResponse& response = message.login_response();
    logged_in_ = response.success();

    if (response.success()) {
      // Send any messages that were queued before the client logged in
      for (const pb::spotify::Message& message : queued_messages_) {
        SendOrQueueMessage(message);
      }
      queued_messages_.clear();
    }

    emit LoginCompleted(response.success(),
                        QStringFromStdString(response.error()),
                        response.error_code());
  } else if (message.has_playlists_updated()) {
    emit PlaylistsUpdated(message.playlists_updated());
  } else if (message.has_load_playlist_response()) {
    const pb::spotify::LoadPlaylistResponse& response =
        message.load_playlist_response();

    switch (response.request().type()) {
      case pb::spotify::Inbox:
        emit InboxLoaded(response);
        break;

      case pb::spotify::Starred:
        emit StarredLoaded(response);
        break;

      case pb::spotify::UserPlaylist:
        emit UserPlaylistLoaded(response);
        break;
    }
  } else if (message.has_playback_error()) {
    emit PlaybackError(QStringFromStdString(message.playback_error().error()));
  } else if (message.has_search_response()) {
    emit SearchResults(message.search_response());
  } else if (message.has_image_response()) {
    const pb::spotify::ImageResponse& response = message.image_response();
    const QString id = QStringFromStdString(response.id());

    if (response.has_data()) {
      emit ImageLoaded(
          id, QImage::fromData(
                  QByteArray(response.data().data(), response.data().size())));
    } else {
      emit ImageLoaded(id, QImage());
    }
  } else if (message.has_sync_playlist_progress()) {
    emit SyncPlaylistProgress(message.sync_playlist_progress());
  } else if (message.has_browse_album_response()) {
    emit AlbumBrowseResults(message.browse_album_response());
  } else if (message.has_browse_toplist_response()) {
    emit ToplistBrowseResults(message.browse_toplist_response());
  }
}
void SpotifyService::EnsureServerCreated(const QString& username,
                                         const QString& password) {
  if (server_ && blob_process_) {
    return;
  }

  delete server_;
  server_ = new SpotifyServer(this);

  connect(server_, SIGNAL(LoginCompleted(bool,QString,spotify_pb::LoginResponse_Error)),
                   SLOT(LoginCompleted(bool,QString,spotify_pb::LoginResponse_Error)));
  connect(server_, SIGNAL(PlaylistsUpdated(spotify_pb::Playlists)),
          SLOT(PlaylistsUpdated(spotify_pb::Playlists)));
  connect(server_, SIGNAL(InboxLoaded(spotify_pb::LoadPlaylistResponse)),
          SLOT(InboxLoaded(spotify_pb::LoadPlaylistResponse)));
  connect(server_, SIGNAL(StarredLoaded(spotify_pb::LoadPlaylistResponse)),
          SLOT(StarredLoaded(spotify_pb::LoadPlaylistResponse)));
  connect(server_, SIGNAL(UserPlaylistLoaded(spotify_pb::LoadPlaylistResponse)),
          SLOT(UserPlaylistLoaded(spotify_pb::LoadPlaylistResponse)));
  connect(server_, SIGNAL(PlaybackError(QString)),
          SIGNAL(StreamError(QString)));
  connect(server_, SIGNAL(SearchResults(spotify_pb::SearchResponse)),
          SLOT(SearchResults(spotify_pb::SearchResponse)));
  connect(server_, SIGNAL(ImageLoaded(QString,QImage)),
          SLOT(ImageLoaded(QString,QImage)));
  connect(server_, SIGNAL(SyncPlaylistProgress(spotify_pb::SyncPlaylistProgress)),
          SLOT(SyncPlaylistProgress(spotify_pb::SyncPlaylistProgress)));

  server_->Init();

  login_task_id_ = model()->task_manager()->StartTask(tr("Connecting to Spotify"));

  if (username.isEmpty()) {
    QSettings s;
    s.beginGroup(kSettingsGroup);

    server_->Login(s.value("username").toString(), s.value("password").toString());
  } else {
    server_->Login(username, password);
  }

  StartBlobProcess();
}
예제 #5
0
SpotifyServer* SpotifySearchProvider::server() {
  if (server_)
    return server_;

  if (!service_)
    service_ = InternetModel::Service<SpotifyService>();

  if (service_->login_state() != SpotifyService::LoginState_LoggedIn)
    return NULL;

  server_ = service_->server();
  connect(server_, SIGNAL(SearchResults(pb::spotify::SearchResponse)),
          SLOT(SearchFinishedSlot(pb::spotify::SearchResponse)));
  connect(server_, SIGNAL(ImageLoaded(QString,QImage)),
          SLOT(ArtLoadedSlot(QString,QImage)));
  connect(server_, SIGNAL(AlbumBrowseResults(pb::spotify::BrowseAlbumResponse)),
          SLOT(AlbumBrowseResponse(pb::spotify::BrowseAlbumResponse)));
  connect(server_, SIGNAL(destroyed()), SLOT(ServerDestroyed()));

  return server_;
}
QScriptValue SearchResultsScriptClass::newInstance()
{
	return newInstance(SearchResults());
}
예제 #7
0
void CJabberProto::OnIqResultAdvancedSearch( HXML iqNode )
{
	const TCHAR* type;
	int    id;

	U_TCHAR_MAP mColumnsNames(10);
	LIST<void>  SearchResults(2);

	if ((( id = JabberGetPacketID( iqNode )) == -1 ) || (( type = xmlGetAttrValue( iqNode, _T("type"))) == NULL )) {
		JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 );
		return;
	}

	if ( !lstrcmp( type, _T("result"))) {
		HXML queryNode = xmlGetNthChild( iqNode, _T("query"), 1 );
		HXML xNode = xmlGetChildByTag( queryNode, "x", "xmlns", _T(JABBER_FEAT_DATA_FORMS));
		if (xNode) {
			//1. Form search results info
			HXML reportNode = xmlGetNthChild( xNode, _T("reported"), 1 );
			if (reportNode) {
				int i = 1;
				while ( HXML fieldNode = xmlGetNthChild( reportNode, _T("field"), i++ )) {
					TCHAR* var = ( TCHAR* )xmlGetAttrValue( fieldNode, _T( "var" ));
					if ( var ) {
						TCHAR* Label = ( TCHAR* )xmlGetAttrValue( fieldNode, _T( "label" ));
						mColumnsNames.insert(var, (Label!=NULL) ? Label : var);
			}	}	}

			int i=1;
			HXML itemNode;
			while ( itemNode = xmlGetNthChild( xNode, _T("item"), i++ )) {
				U_TCHAR_MAP *pUserColumn = new U_TCHAR_MAP(10);
				int j = 1;
				while ( HXML fieldNode = xmlGetNthChild( itemNode, _T("field"), j++ )) {
					if ( TCHAR* var = (TCHAR*)xmlGetAttrValue( fieldNode, _T("var"))) {
						if ( TCHAR* Text = (TCHAR*)xmlGetText( xmlGetChild( fieldNode, _T("value")))) {
							if ( !mColumnsNames[var] )
								mColumnsNames.insert(var,var);
							pUserColumn->insert(var,Text);
				}	}	}

				SearchResults.insert((void*)pUserColumn);
			}
		}
		else {
			//2. Field list search results info
			int i=1;
			while ( HXML itemNode = xmlGetNthChild( queryNode, _T("item"), i++ )) {
				U_TCHAR_MAP *pUserColumn=new U_TCHAR_MAP(10);
				
				TCHAR* jid = (TCHAR*)xmlGetAttrValue( itemNode, _T("jid"));
				TCHAR* keyReturned;
				mColumnsNames.insertCopyKey( _T("jid"),_T("jid"),&keyReturned, CopyKey, DestroyKey );
				mColumnsNames.insert( _T("jid"), keyReturned );
				pUserColumn->insertCopyKey( _T("jid"), jid, NULL, CopyKey, DestroyKey );

				for ( int j=0; ; j++ ) {
					HXML child = xmlGetChild( itemNode, j );
					if ( !child )
						break;

					const TCHAR* szColumnName = xmlGetName( child );
					if ( szColumnName ) {
						if ( xmlGetText( child ) && xmlGetText( child )[0] != _T('\0')) {
							mColumnsNames.insertCopyKey(( TCHAR* )szColumnName,_T(""),&keyReturned, CopyKey, DestroyKey);
							mColumnsNames.insert(( TCHAR* )szColumnName,keyReturned);
							pUserColumn->insertCopyKey(( TCHAR* )szColumnName, ( TCHAR* )xmlGetText( child ),NULL, CopyKey, DestroyKey);
				}	}	}

				SearchResults.insert((void*)pUserColumn);
		}	}
	}
	else if (!lstrcmp( type, _T("error"))) {
		const TCHAR* code=NULL;
		const TCHAR* description=NULL;
		TCHAR buff[255];
		HXML errorNode =  xmlGetChild( iqNode , "error" );
		if (errorNode) {
			code = xmlGetAttrValue( errorNode, _T("code"));
			description = xmlGetText( errorNode );
		}

		_sntprintf(buff,SIZEOF(buff),TranslateT("Error %s %s\r\nTry to specify more detailed"),code ? code : _T(""),description?description:_T(""));
		JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 );
		if (searchHandleDlg )
			SetDlgItemText(searchHandleDlg,IDC_INSTRUCTIONS,buff);
		else
			MessageBox(NULL, buff, TranslateT("Search error"), MB_OK|MB_ICONSTOP);
		return;
	}

	SearchReturnResults((HANDLE)id, (void*)&SearchResults, (U_TCHAR_MAP *)&mColumnsNames);

	for (int i=0; i < SearchResults.getCount(); i++ )
		delete ((U_TCHAR_MAP *)SearchResults[i]);

	//send success to finish searching
	JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 );
}
예제 #8
0
	// recursive function which does all search logic
	void DFBB(StarcraftState & s, int depth)
	{		
		// increase the node expansion count
		nodesExpanded++;
		
		// if we have constraints and they are not met
		if (params.useConstraints && !s.meetsConstraints(params.ssc))
		{
			// this state is not legal
			return;
		}
	
		// the time at which the last thing in the queue will finish
		int finishTime = s.getLastFinishTime();
		
		/*int lookupVal = TT.lookup(s.hashAllUnits(1), s.hashAllUnits(2));
		if (lookupVal != -1 && lookupVal < finishTime)
		{
		    ttcuts++;
		    //return;
		}

		TT.save(s.hashAllUnits(1), s.hashAllUnits(2), finishTime);*/

		// if we already have completed the units for the goal, don't worry about last finish time
		if (s.meetsGoalCompleted(params.goal))
		{
			finishTime = s.getCurrentFrame();
		}

		// if we have met the goal, we're good
		if (s.meetsGoal(params.goal)) 
		{
			// if it's better than the current best solution, set the new best
			if (finishTime < upperBound)//  || ((finishTime == upperBound) && (s.getWorkerCount() > winnerWorkerCount))) 
			{
				// set the winning info
				upperBound = finishTime;
				winner = s;
				winnerFound = true;
				winnerWorkerCount = s.getWorkerCount();

				results = SearchResults(true, upperBound, nodesExpanded, searchTimer.getElapsedTimeInMilliSec(), s.getBuildOrder());
				results.upperBound = s.calculateUpperBoundHeuristic(params.goal);
				results.lowerBound = s.eval(params.goal);
				results.avgBranch = numChildren / (double)numGenerations;
				results.minerals = s.getFinishTimeMinerals();
				results.gas = s.getFinishTimeGas();
				
				results.saveState = SearchSaveState(getBuildOrder(s), upperBound);
				
				//graphVizOutput(s, true);
				results.printResults(true);
				
				s.printData();

				return;
			}
		}
		
		// if we are using search timeout and we are over the limit
		// (nodesExpanded % 1000 == 0) only checks the time every 1000 expansions, since it is slow
		if (params.searchTimeLimit && (nodesExpanded % 200 == 0) && (searchTimer.getElapsedTimeInMilliSec() > params.searchTimeLimit))
		{
			results.saveState = SearchSaveState(getBuildOrder(s), upperBound);
			//results.saveState.print();
		
			// throw an exception to unroll the recursion
			throw 1;
		}
		
		// get the legal action set
		ActionSet legalActions = s.getLegalActions(params.goal); 

		// only use relevant actions
		legalActions = legalActions & relevantActions;
		
		// if we enabled the supply bounding flag
		if (params.useSupplyBounding)
		{
			// if we are more than 2 supply providers in the lead 
			if ((s.getMaxSupply() - s.getCurrentSupply()) >= params.supplyBoundingThreshold*DATA[DATA.getSupplyProvider()].supplyProvided())
			{
				// make supply providers illegal
				legalActions.subtract(DATA.getSupplyProvider());
			}
		}
		
		// if we enabled the always make workers flag, and workers are legal
		if (params.useAlwaysMakeWorkers && !params.goal[DATA.getWorker()] && legalActions[DATA.getWorker()])
		{
			ActionSet tempLegal(legalActions);
			ActionSet legalBeforeWorker;
			
			// compute when the next worker will be trainable
			int workerReady = s.resourcesReady(DATA.getWorker());
			
			// for each other legal action
			while (!tempLegal.isEmpty())
			{
				Action nextAction = tempLegal.popAction();
				
				// if the action will be ready before the next worker
				if (s.resourcesReady(nextAction) <= workerReady)
				{
					// it's legal
					legalBeforeWorker.add(nextAction);
				}
			}
			
			// update the legal actions
			legalActions = legalBeforeWorker;
		}
		
		// if we enabled the use worker cutoff flag and we're above the cutoff
		if (params.useWorkerCutoff && s.getCurrentFrame() > (params.workerCutoff * upperBound))
		{
			// workers are no longer legal
			legalActions.subtract(DATA.getWorker());

			// if we have enough supply for the remaining goal
			if (s.hasEnoughSupplyForGoal(params.goal))
			{
				// make supply providers illegal
				legalActions.subtract(DATA.getSupplyProvider());
			}
		}	

		// if we have children, update the counter
		if (!legalActions.isEmpty())
		{
			numGenerations += 1;
			numChildren += legalActions.numActions();
		}
		
		// load the save state if we are using it
		if (params.useSaveState && !finishedLoadingSaveState)
		{
			// if we are under the saved depth, load accordingly
			if (depth < params.saveState.getDepth())
			{
				// pop actions until the NEXT action is the one we want to start on
				while (!legalActions.isEmpty() && legalActions.nextAction() != params.saveState[depth])
				{
					legalActions.popAction();
				}
			}
			// if we are over the depth, we are finished loading
			else
			{
				finishedLoadingSaveState = true;
			}
		}
		
		// children of this state in the search
		std::vector<StarcraftState> childStates;

		// while there are still legal actions to perform
		while (!legalActions.isEmpty()) 
		{				
			// get the next action
			Action nextAction = legalActions.popAction();
			
			// when this action would finish
			int actionFinishTime = s.resourcesReady(nextAction) + DATA[nextAction].buildTime();
			
			// heuristic value of the goal state
			int heuristicTime = s.getCurrentFrame() + s.eval(params.goal, params.useLandmarkLowerBoundHeuristic);
			
			// the h value for this node
			int h = (actionFinishTime > heuristicTime) ? actionFinishTime : heuristicTime;
			
			// primary cut-off, very quick heuristic
			if (h <= upperBound)
			{
				bool stillLegal = true;
				StarcraftState child(s);
				
				// set the repetitions if we are using repetitions, otherwise set to 1
				int repeat = params.useRepetitions ? params.getRepetitions(nextAction) : 1;
				
				// if we are using increasing repetitions
				if (params.useIncreasingRepetitions)
				{
					// if we don't have the threshold amount of units, use a repetition value of 1
					repeat = child.getNumUnits(nextAction) >= params.getRepetitionThreshold(nextAction) ? repeat : 1;
				}
				
				// make sure we don't repeat to more than we need for this unit type
				if (params.goal.get(nextAction))
				{
					repeat = (std::min)(repeat, params.goal.get(nextAction) - child.getNumUnits(nextAction));
				}
				else if (params.goal.getMax(nextAction))
				{
					repeat = (std::min)(repeat, params.goal.getMax(nextAction) - child.getNumUnits(nextAction));
				}

				// limit repetitions to how many we can make based on current used supply
				if (DATA[nextAction].supplyRequired() > 0)
				{
					int haveSupplyFor = (s.getMaxSupply() + s.getSupplyInProgress() - s.getCurrentSupply()) / DATA[nextAction].supplyRequired();

					repeat = (std::min)(repeat, haveSupplyFor);
				}
				
				// if we're not finished loading the state, repeat value is 1
				if (params.useSaveState && !finishedLoadingSaveState)
				{
					repeat = 1;
				}

				// for each repetition of this action
				for (int r = 0; r < repeat; ++r)
				{
					// if the action is still legal
					if (child.isLegal(nextAction, params.goal))
					{						
						int readyTime = child.resourcesReady(nextAction); 
						child.doAction(nextAction, readyTime);
					}
					// if it's not legal, break the chain
					else
					{
						stillLegal = false;
						break;
					}
				}
				
				// if all actions in a row are legal, recurse on the child
				if (stillLegal)
				{
					child.setParent(&s);
					child.setActionPerformedK((UnitCountType)repeat);
					//DFBB(child, depth+1);
					childStates.push_back(child);
				}
			}
		}	
		
		//std::sort(childStates.begin(), childStates.end(), StarcraftStateCompare<StarcraftStateType>(params));
		//std::random_shuffle(childStates.begin(), childStates.end());
		for (size_t i(0); i<childStates.size(); ++i)
		{
		    DFBB(childStates[i], depth+1);
		}
	}
static void JabberIqResultAdvancedSearch( XmlNode *iqNode, void *userdata )
{
	TCHAR* type;
	int    id;

	U_TCHAR_MAP mColumnsNames(10);
	LIST<void>  SearchResults(2);

	if ((( id = JabberGetPacketID( iqNode )) == -1 ) || (( type = JabberXmlGetAttrValue( iqNode, "type" )) == NULL )) {
		JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 );
		return;
	}

	if ( !lstrcmp( type, _T("result"))) {
		XmlNode* queryNode=JabberXmlGetNthChild(iqNode,"query",1);
		XmlNode* xNode = JabberXmlGetChildWithGivenAttrValue( queryNode, "x", "xmlns", _T("jabber:x:data"));
		if (xNode) {
			//1. Form search results info
			XmlNode* reportNode=JabberXmlGetNthChild(xNode,"reported",1);
			if (reportNode) {
				int i = 1;
				while ( XmlNode* fieldNode = JabberXmlGetNthChild( reportNode, "field", i++ )) {
					TCHAR* var = JabberXmlGetAttrValue( fieldNode, "var" );
					if ( var ) {
						TCHAR * Label=JabberXmlGetAttrValue(fieldNode,"label");
						mColumnsNames.insert(var, (Label!=NULL) ? Label : var);
			}	}	}

			int i=1;
			XmlNode* itemNode;
			while ( itemNode = JabberXmlGetNthChild( xNode, "item", i++ )) {
				U_TCHAR_MAP *pUserColumn = new U_TCHAR_MAP(10);
				int j = 1;
				while ( XmlNode* fieldNode = JabberXmlGetNthChild( itemNode, "field", j++ )) {
					if (TCHAR * var=JabberXmlGetAttrValue(fieldNode,"var" )) {
						if (TCHAR * Text=(JabberXmlGetChild(fieldNode,"value")->text)) {
							if (!mColumnsNames[var])
								mColumnsNames.insert(var,var);
							pUserColumn->insert(var,Text);
				}	}	}

				SearchResults.insert((void*)pUserColumn);
			}
		}
		else {
			//2. Field list search results info
			int i=1;
			while ( XmlNode* itemNode = JabberXmlGetNthChild( queryNode, "item", i++ )) {
				U_TCHAR_MAP *pUserColumn=new U_TCHAR_MAP(10);
				
				TCHAR* jid = JabberXmlGetAttrValue( itemNode, "jid" );
				TCHAR* keyReturned;
				mColumnsNames.insertCopyKey( _T("jid"),_T("jid"),&keyReturned, CopyKey, DestroyKey );
				mColumnsNames.insert( _T("jid"), keyReturned );
				pUserColumn->insertCopyKey( _T("jid"), jid, NULL, CopyKey, DestroyKey );

				for ( int j=0; j < itemNode->numChild; j++ ) {
					XmlNode* child = itemNode->child[j];
					if ( child->name ) {
						TCHAR * szColumnName=a2t(child->name);
						if ( child->text && child->text[0] != _T('\0')) {
							TCHAR *keyReturned;
							mColumnsNames.insertCopyKey(szColumnName,_T(""),&keyReturned, CopyKey, DestroyKey);
							mColumnsNames.insert(szColumnName,keyReturned);
							pUserColumn->insertCopyKey(szColumnName,child->text,NULL, CopyKey, DestroyKey);
							mir_free(szColumnName);
				}	}	}

				SearchResults.insert((void*)pUserColumn);
		}	}
	}
	else if (!lstrcmp( type, _T("error"))) {
		TCHAR * code=NULL;
		TCHAR * description=NULL;
		TCHAR buff[255];
		XmlNode* errorNode = JabberXmlGetChild( iqNode, "error" );
		if (errorNode) {
			code = JabberXmlGetAttrValue(errorNode,"code");
			description = errorNode->text;
		}

		_sntprintf(buff,SIZEOF(buff),TranslateT("Error %s %s\r\nTry to specify more detailed"),code ? code : _T(""),description?description:_T(""));
		JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 );
		if (searchHandleDlg )
			SetDlgItemText(searchHandleDlg,IDC_INSTRUCTIONS,buff);
		else
			MessageBox(NULL, buff, TranslateT("Search error"), MB_OK|MB_ICONSTOP);
		return;
	}

	JabberSearchReturnResults((HANDLE)id, (void*)&SearchResults, (U_TCHAR_MAP *)&mColumnsNames);

	for (int i=0; i < SearchResults.getCount(); i++ )
		delete ((U_TCHAR_MAP *)SearchResults[i]);

	//send success to finish searching
	JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 );
}