bool Audio::Init(const std::string& res_audio_path)
{
	std::wstring dir = QPath::GetAppPath();
#ifdef _DEBUG
	dir.append(kSdkAudioDll_d);
#else
	dir.append(kSdkAudioDll);
#endif
	instance_audio_ = ::LoadLibraryW(dir.c_str());
	if (instance_audio_ == NULL)
	{
		QLOG_ERR(L"sdk audio dll load fail {0} {1}") << dir << GetLastError();
		return false;
	}

	assert(instance_audio_);
	if (instance_audio_)
	{
		nim_audio_init_module f_init = Function<nim_audio_init_module>("nim_audio_init_module");
		bool ret = f_init(res_audio_path.c_str());
		if (!ret)
		{
			QLOG_ERR(L"init audio fail: {0}") << res_audio_path;
		}
		return ret;
	}
	return false;
}
void HeadModifyForm::OnUploadHeadIconCallback(nim::NIMResCode res_code, const std::string& url)
{
	if(res_code == nim::kNIMResSuccess)
	{
		QLOG_APP(L"Head icon upload success and call callback!");

		if (complete_callback_)
			complete_callback_(uid_, url);

		if (specific_cached_file_.empty())
		{
			//删除缓存头像
			StdClosure closure = nbase::Bind(&HeadModifyForm::DeleteFileCallback, new_temp_head_image_path_);
			nbase::ThreadManager::PostTask(kThreadGlobalMisc, closure);
		}

		OnNotifyHeadModifyCallback();
	}
	else
	{
		// 头像上传失败
		QLOG_ERR(L"Upload head icon failed");
		StdClosure closure = nbase::Bind(&HeadModifyForm::OnNotifyHeadModifyFailed, this);
		nbase::ThreadManager::PostTask(kThreadUI, ToWeakCallback(closure));
	}
}
// 保存头像
void HeadModifyForm::OnButtonSaveImage()
{
	if(is_loading_image_)
		return;

	//if (!shared::FilePathIsExist(attach_path, true))
	//	return shared::CreateDirRecursively(attach_path);

	static const std::wstring mime_type = L"image/png";
	std::wstring temp_file_path;
	if (!specific_cached_file_.empty())
	{
		temp_file_path = specific_cached_file_;
	}
	else
	{
		temp_file_path = PhotoService::GetInstance()->GetPhotoDir(kUser);
		std::wstring temp_file_name;
		nbase::Time::TimeStruct now = nbase::Time::Now().ToTimeStruct(true);
		nbase::StringPrintf(temp_file_name, L"temp_head_icon_%d%d%d%d%d%d",
			now.year(), now.month(), now.day_of_month(), now.hour(), now.minute(), now.second());
		temp_file_path.append(temp_file_name);
	}

	// 覆盖本地的旧头像
	if(head_view_ctrl_->SaveSelectBitmap(head_select_ctrl_->GetPos(), temp_file_path, mime_type))
	{
		g_last_save_head_image_ = image_path_;
		RECT head_select_rect = head_select_ctrl_->GetPos();
		RECT head_panel_rect = head_panel_->GetPos();
		RECT select_padding = { head_select_rect.left - head_panel_rect.left,
			head_select_rect.top - head_panel_rect.top, 0, 0};
		g_last_select_padding_ = select_padding;
		g_last_select_width_ = head_select_rect.right - head_select_rect.left;
		new_temp_head_image_path_ = temp_file_path;

		// 在Core线程触发头像修改监听
		StdClosure notify_head_modify_closure = 
			nbase::Bind(&HeadModifyForm::NotifyHeadModify, this, temp_file_path, uid_);
		nbase::ThreadManager::PostTask(kThreadUI, ToWeakCallback(notify_head_modify_closure));
	}
	else
	{
		// 提示用户,保存失败
		QLOG_ERR(L"Save new head icon failed!");
		OnNotifyHeadModifyFailed();
	}
}
bool CefControlBase::CallJSFunction(const std::wstring& js_function_name, const std::wstring& params, nim_cef::CallJsFunctionCallback callback, int frame_id)
{
	if (browser_handler_.get() && browser_handler_->GetBrowser().get() && js_bridge_.get())
	{
		CefRefPtr<CefFrame> frame = browser_handler_->GetBrowser()->GetFrame(frame_id);

		if (!js_bridge_->CallJSFunction(nbase::UTF16ToUTF8(js_function_name).c_str(),
			nbase::UTF16ToUTF8(params).c_str(), frame, callback))
		{
			QLOG_ERR(L"Failed to call JavaScript function {0}") << js_function_name;
			return false;
		}

		return true;
	}

	return false;
}
void TeamEventForm::AddEvent(const nim::SysMessage &sys_msg, bool first)
{
	if(id_item_pair_.find(sys_msg.id_) == id_item_pair_.end())
	{
		TeamEventItem* item = new TeamEventItem;
		GlobalManager::FillBoxWithCache(item, L"main/event_item.xml");
		item->InitCtrl();
		bool ret = item->InitInfo(sys_msg);
		if (ret)
		{
			if (first)
				event_list_->AddAt(item, 0);
			else
				event_list_->Add(item);

			id_item_pair_[sys_msg.id_] = item;
		}
	}
	else
	{
		QLOG_ERR(L"repeat sysmsg, id={0}") << sys_msg.id_;
	}
}
void ChatroomFrontpage::InvokeGetRoomList()
{
	FindControl(L"loading_tip")->SetVisible(true);

	auto http_cb = ToWeakCallback([this](bool ret, int response_code, const std::string& reply)
	{
		StdClosure error_cb = ToWeakCallback([this]()
		{
			FindControl(L"loading_tip")->SetVisible(false);
			FindControl(L"load_error_tip")->SetVisible(true);
		});

		if (!ret || response_code != nim::kNIMResSuccess)
		{
			QLOG_ERR(L"Invoke get room list error. Error code: {0}.") << response_code;
			Post2UI(error_cb);

			return;
		}

		Json::Value json_reply;
		Json::Reader reader;
		if (reader.parse(reply, json_reply) && json_reply.isObject())
		{
			int res = json_reply["res"].asInt();
			if (res != 200)
			{
				QLOG_ERR(L"Invoke get room list error. Json rescode: {0}.") << res;
				Post2UI(error_cb);

				return;
			}

			int count = json_reply["msg"]["total"].asInt();
			Json::Value json_list = json_reply["msg"]["list"];
			if (!json_list.isArray())
			{
				QLOG_ERR(L"Invoke get room list error. Reason: Not an array.");
				Post2UI(error_cb);

				return;
			}

			StdClosure closure = ToWeakCallback([this, json_list, count]() 
			{
				FindControl(L"loading_tip")->SetVisible(false);

				for (int i = 0; i < count; i++)
				{
					ChatRoomInfo info;
					info.id_ = json_list[i]["roomid"].asInt64();
					info.name_ = json_list[i]["name"].asString();
					info.creator_id_ = json_list[i]["creator"].asString();
					nbase::StringToInt(json_list[i]["onlineusercount"].asString(), &info.online_count_);
					info.valid_flag_ = json_list[i]["status"].asInt();
					info.ext_ = json_list[i]["ext"].asString();
					info.announcement_ = json_list[i]["announcement"].asString();
					info.broadcast_url_ = json_list[i]["broadcasturl"].asString();
					id_info_map_[info.id_] = info;

					CreateRoomItem(info);
				}
			});
			Post2UI(closure);
		}
		else
		{
			QLOG_ERR(L"invoke get room list json parse error {0}.") << reply;
			Post2UI(error_cb);
		}
	});

	std::string api_addr = "https://app.netease.im/api/chatroom/homeList";
	std::string new_api_addr = GetConfigValue("kNIMChatRoomAddress");
	if (!new_api_addr.empty())
		api_addr = new_api_addr;

	std::string app_key = "45c6af3c98409b18a84451215d0bdd6e";
	std::string new_app_key = GetConfigValue(g_AppKey);
	if (!new_app_key.empty())
		app_key = new_app_key;
	nim_http::HttpRequest request(api_addr, "", 0, http_cb);
	request.AddHeader("Content-Type", "application/json; charset=utf-8");
	request.AddHeader("appKey", app_key);
	nim_http::PostRequest(request);
}