mainform.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. #include "mainform.h"
  2. #include "ui_mainform.h"
  3. #include <portaudio.h>
  4. #include <QMessageBox>
  5. #include <QCoreApplication>
  6. #include <QDir>
  7. #include <QSettings>
  8. #include "imediadeviceinfo.h"
  9. #ifndef MAX_STR_LEN
  10. #define MAX_STR_LEN 512
  11. #endif // !MAX_STR_LEN
  12. #ifndef MAX_PATH
  13. #define MAX_PATH 260
  14. #endif // !MAX_PATH
  15. typedef int (*lpfn_get_cameracountfun)();
  16. typedef int (*lpfn_get_videodevice_namefun)(int device_id, char* buf, int len);
  17. typedef int (*lpfn_get_videodevice_infofun)(int device_id, char* namebuf, int namelen, char* pathbuf, int pathlen);
  18. typedef int (*lpfn_get_videodeviceid)(const char* dev_name);
  19. static lpfn_get_cameracountfun get_cameracount = NULL;
  20. static lpfn_get_videodevice_namefun get_videodevice_name = NULL;
  21. static lpfn_get_videodevice_infofun get_videodevice_info = NULL;
  22. static lpfn_get_videodevice_namefun get_device_fullpathname = NULL;
  23. static lpfn_get_videodeviceid get_videodeviceid = NULL;
  24. QList<AudioDeviceInfo> availableDevices(DevMode mode);
  25. static int audio_translate_id(int in_direction, int idx)
  26. {
  27. int i, n, ii;
  28. //audio_log_set_func(NULL);
  29. n = Pa_GetDeviceCount();
  30. for (i = 0, ii = 0; i < n; ++i) {
  31. const PaDeviceInfo* info = Pa_GetDeviceInfo(i);
  32. if (in_direction) {
  33. if (info->maxInputChannels) {
  34. if (ii == idx) {
  35. //audio_log_set_func(__audio_log_func);
  36. return i;
  37. }
  38. ii++;
  39. }
  40. } else {
  41. if (info->maxOutputChannels) {
  42. if (ii == idx) {
  43. //audio_log_set_func(__audio_log_func);
  44. return i;
  45. }
  46. ii++;
  47. }
  48. }
  49. }
  50. //audio_log_set_func(__audio_log_func);
  51. return -1;
  52. }
  53. int audio_get_dev_count(int* in_cnt, int* out_cnt)
  54. {
  55. int i;
  56. int icnt = 0, ocnt = 0;
  57. int cnt = Pa_GetDeviceCount();
  58. qDebug() << "device count is " << cnt;
  59. for (i = 0; i < cnt; ++i) {
  60. const PaDeviceInfo* info = Pa_GetDeviceInfo(i);
  61. if (info->maxInputChannels)
  62. icnt++;
  63. if (info->maxOutputChannels)
  64. ocnt++;
  65. }
  66. if (in_cnt)
  67. *in_cnt = icnt;
  68. if (out_cnt)
  69. *out_cnt = ocnt;
  70. return 0;
  71. }
  72. static char* audio_get_dev_name(char* buf, bool in_direction, int idx)
  73. {
  74. int cnt = Pa_GetDeviceCount();
  75. int ii, i;
  76. for (i = 0, ii = 0; i < cnt; ++i) {
  77. const PaDeviceInfo* info = Pa_GetDeviceInfo(i);
  78. if (in_direction) {
  79. if (info->maxInputChannels) {
  80. if (idx == ii) {
  81. strcpy(buf, info->name);
  82. return buf;
  83. }
  84. ii++;
  85. }
  86. } else {
  87. if (info->maxOutputChannels) {
  88. if (idx == ii) {
  89. strcpy(buf, info->name);
  90. return buf;
  91. }
  92. ii++;
  93. }
  94. }
  95. }
  96. return NULL;
  97. }
  98. static QList<AudioDeviceInfo> show_audio_dev(DevMode flag)
  99. {
  100. int icnt, ocnt;
  101. QList< AudioDeviceInfo> result;
  102. int rc = audio_get_dev_count(&icnt, &ocnt);
  103. if (rc == 0) {
  104. int i;
  105. char tmp[128];
  106. if (flag & AudioInput) {
  107. qDebug() << "audio input devices: " << icnt;
  108. for (i = 0; i < icnt; ++i) {
  109. audio_get_dev_name(tmp, true, i);
  110. qDebug() << i << "=" << tmp;
  111. AudioDeviceInfo info;
  112. info.name = tmp;
  113. info.mod = AudioInput;
  114. result << info;
  115. }
  116. }
  117. if (flag & AudioOutput) {
  118. qDebug() << "audio output devices: " << ocnt;
  119. for (i = 0; i < ocnt; ++i) {
  120. audio_get_dev_name(tmp, false, i);
  121. qDebug() << i << "=" << tmp;
  122. AudioDeviceInfo info;
  123. info.name = tmp;
  124. info.mod = AudioOutput;
  125. result << info;
  126. }
  127. }
  128. }
  129. return result;
  130. }
  131. static QList<AudioDeviceInfo> show_video_dev()
  132. {
  133. int icount = get_cameracount();
  134. qDebug() << "video devices:" << icount;
  135. QList< AudioDeviceInfo> result;
  136. int inumber = 0;
  137. for (int i = 0; i < 2 * icount; ++i) {
  138. char strcamera[2 * MAX_PATH] = { 0 };
  139. char strpath[MAX_PATH] = { 0 };
  140. if (0 == get_device_fullpathname(i, strcamera, 2 * MAX_PATH)) {
  141. qDebug() << inumber++ << " " << strcamera;
  142. AudioDeviceInfo info;
  143. info.name = strcamera;
  144. info.mod = VideoDevice;
  145. result << info;
  146. }
  147. }
  148. return result;
  149. }
  150. QList<AudioDeviceInfo> availableDevices(DevMode mode)
  151. {
  152. QList<AudioDeviceInfo> devList;
  153. if (mode & VideoDevice) {
  154. devList.append(show_video_dev());
  155. }
  156. if (mode & AudioInput || mode & AudioOutput) {
  157. devList.append(show_audio_dev(mode));
  158. }
  159. return devList;
  160. }
  161. MainForm::MainForm(QWidget *parent) :
  162. QWidget(parent),
  163. ui(new Ui::MainForm), deviceInfoLib(nullptr), rootFilePath()
  164. {
  165. Pa_Initialize();
  166. ui->setupUi(this);
  167. ui->tabWidget->setVisible(false);
  168. connect(ui->modeBox, QOverload<int>::of(&QComboBox::activated), this, &MainForm::modeChanged);
  169. connect(ui->deviceBox, QOverload<int>::of(&QComboBox::activated), this, &MainForm::deviceChanged);
  170. ui->modeBox->setCurrentIndex(0);
  171. modeChanged(0);
  172. ui->deviceBox->setCurrentIndex(0);
  173. deviceChanged(0);
  174. }
  175. MainForm::~MainForm()
  176. {
  177. delete ui;
  178. if (deviceInfoLib != nullptr) {
  179. deviceInfoLib->unload();
  180. delete deviceInfoLib;
  181. }
  182. Pa_Terminate();
  183. }
  184. bool MainForm::loadExportFunctions()
  185. {
  186. bool result = false;
  187. if (deviceInfoLib != nullptr) {
  188. return true;
  189. }
  190. QString appDir = QCoreApplication::applicationDirPath();
  191. QString libAbsolutePath = appDir + "/libmediadeviceinfo.so";
  192. qDebug() << "Enter loadExportFunctions" << " " << libAbsolutePath << endl;
  193. deviceInfoLib = new QLibrary(libAbsolutePath);
  194. deviceInfoLib->load();
  195. do
  196. {
  197. if (!deviceInfoLib->isLoaded()) {
  198. qDebug() << "Load libmediadeviceinfo.so failed: " << deviceInfoLib->errorString() << endl;
  199. break;
  200. }
  201. get_cameracount = (lpfn_get_cameracountfun)deviceInfoLib->resolve("rvc_videocap_get_device_count");
  202. if (!get_cameracount) {
  203. qDebug() << "Load rvc_videocap_get_device_count failed: " << deviceInfoLib->errorString() << endl;
  204. break;
  205. }
  206. get_videodevice_name = (lpfn_get_videodevice_namefun)deviceInfoLib->resolve("rvc_videocap_get_device_name");
  207. if (!get_videodevice_name) {
  208. qDebug() << "Load rvc_videocap_get_device_name failed: " << deviceInfoLib->errorString() << endl;
  209. break;
  210. }
  211. get_videodevice_info = (lpfn_get_videodevice_infofun)deviceInfoLib->resolve("rvc_videocap_get_device_info");
  212. if (!get_videodevice_info) {
  213. qDebug() << "Load rvc_videocap_get_device_info failed: " << deviceInfoLib->errorString() << endl;
  214. break;
  215. }
  216. get_device_fullpathname = (lpfn_get_videodevice_namefun)deviceInfoLib->resolve("rvc_videocap_get_device_fullpathname");
  217. if (!get_device_fullpathname) {
  218. qDebug() << "Load rvc_videocap_get_device_fullpathname failed: " << deviceInfoLib->errorString() << endl;
  219. break;
  220. }
  221. get_videodeviceid = (lpfn_get_videodeviceid)deviceInfoLib->resolve("rvc_videocap_get_video_device_id");
  222. if (!get_videodeviceid) {
  223. qDebug() << "Load rvc_videocap_get_video_device_id failed: " << deviceInfoLib->errorString() << endl;
  224. break;
  225. }
  226. result = true;
  227. } while (false);
  228. if (!result) {
  229. if (deviceInfoLib != nullptr) {
  230. deviceInfoLib->unload();
  231. delete deviceInfoLib;
  232. deviceInfoLib = nullptr;
  233. }
  234. }
  235. return result;
  236. }
  237. DevMode MainForm::convertIdx2Mode(int idx)
  238. {
  239. DevMode result = DevMode::MediaALL;
  240. switch (idx) {
  241. case 0:
  242. result = DevMode::AudioInput;
  243. break;
  244. case 1:
  245. result = DevMode::AudioOutput;
  246. break;
  247. case 2:
  248. result = DevMode::VideoDevice;
  249. break;
  250. default:
  251. break;
  252. }
  253. return result;
  254. }
  255. void MainForm::modeChanged(int idx)
  256. {
  257. ui->deviceBox->clear();
  258. DevMode mode = convertIdx2Mode(idx);
  259. if (deviceInfoLib != nullptr || loadExportFunctions()) {
  260. for (auto& deviceInfo : availableDevices(mode))
  261. ui->deviceBox->addItem(deviceInfo.name, QVariant::fromValue(deviceInfo));
  262. ui->deviceBox->setCurrentIndex(0);
  263. }
  264. ui->deviceBox->setCurrentIndex(0);
  265. deviceChanged(0);
  266. }
  267. void MainForm::deviceChanged(int idx)
  268. {
  269. if (ui->deviceBox->count() == 0)
  270. return;
  271. if (idx == -1) {
  272. int newIdx = 0;
  273. const int selectIdx = ui->modeBox->currentIndex();
  274. DevMode mode = convertIdx2Mode(selectIdx);
  275. QVariant curName = getCurrentActiveDev(mode);
  276. for (int i = 0; i < ui->deviceBox->count() && curName.isValid(); ++i) {
  277. AudioDeviceInfo item = ui->deviceBox->itemData(i).value<AudioDeviceInfo>();
  278. qDebug() << "devicechange: " << item.name << " vs " << curName.toString();
  279. if (item.name == curName.toString()) {
  280. newIdx = i;
  281. break;
  282. }
  283. }
  284. ui->deviceBox->setCurrentIndex(newIdx);
  285. qDebug() << "pre deviceChanged -1 with " << newIdx;
  286. deviceChanged(newIdx);
  287. qDebug() << "return deviceChanged -1 with " << newIdx;
  288. return;
  289. }
  290. qDebug() << "pre pre deviceChanged normal with " << idx;
  291. ui->deviceBox->itemData(idx).value<AudioDeviceInfo>();
  292. // device has changed
  293. qDebug() << "pre deviceChanged normal with " << idx;
  294. m_deviceInfo = ui->deviceBox->itemData(idx).value<AudioDeviceInfo>();
  295. qDebug() << "return deviceChanged normal with " << idx;
  296. }
  297. void MainForm::on_loadBtn_clicked()
  298. {
  299. qDebug() << "Enter push button";
  300. const int selectIdx = ui->modeBox->currentIndex();
  301. modeChanged(selectIdx);
  302. }
  303. void MainForm::on_saveBtn_clicked()
  304. {
  305. const int selectIdx = ui->modeBox->currentIndex();
  306. DevMode mode = convertIdx2Mode(selectIdx);
  307. if (!setCurrentActiveDev(mode, m_deviceInfo.name)) {
  308. QMessageBox::critical(this, "错误", "写入失败!");
  309. } else {
  310. //QString content = QString("写入 %1 成功!").arg(m_deviceInfo.name);
  311. QMessageBox::information(this, "提示", "已应用!");
  312. }
  313. }
  314. QVariant MainForm::getCurrentActiveDev(DevMode mode)
  315. {
  316. QString configPath = getRootIniPath();
  317. QSettings settings(configPath, QSettings::IniFormat);
  318. settings.setIniCodec("UTF-8");
  319. QVariant result;
  320. switch (mode) {
  321. case AudioInput:
  322. settings.beginGroup("Audio");
  323. result = settings.value("handfree_in_dev");
  324. settings.endGroup();
  325. break;
  326. case AudioOutput:
  327. settings.beginGroup("Audio");
  328. result = settings.value("handfree_out_dev");
  329. settings.endGroup();
  330. break;
  331. case VideoDevice:
  332. settings.beginGroup("Video");
  333. result = settings.value("EnvCamera");
  334. settings.endGroup();
  335. break;
  336. case MediaALL:
  337. break;
  338. default:
  339. break;
  340. }
  341. qDebug() << "get " << mode << " " << result;
  342. return result;
  343. }
  344. bool MainForm::setCurrentActiveDev(DevMode mode, QVariant value)
  345. {
  346. QString configPath = getRootIniPath();
  347. QSettings settings(configPath, QSettings::IniFormat);
  348. settings.setIniCodec("UTF-8");
  349. QVariant persistentValue(value);
  350. bool result = false;
  351. switch (mode) {
  352. case AudioInput:
  353. settings.beginGroup("Audio");
  354. settings.setValue("handfree_in_dev", persistentValue);
  355. settings.endGroup();
  356. result = true;
  357. break;
  358. case AudioOutput:
  359. settings.beginGroup("Audio");
  360. settings.setValue("handfree_out_dev", persistentValue);
  361. settings.endGroup();
  362. result = true;
  363. break;
  364. case VideoDevice:
  365. settings.beginGroup("Video");
  366. settings.setValue("EnvCamera", persistentValue);
  367. settings.endGroup();
  368. result = true;
  369. break;
  370. case MediaALL:
  371. break;
  372. default:
  373. break;
  374. }
  375. if (result) {
  376. QVariant newValue = getCurrentActiveDev(mode);
  377. if (newValue != value) {
  378. qDebug() << "newValue: " << newValue << " vs " << value;
  379. result = false;
  380. }
  381. }
  382. return result;
  383. }
  384. QString MainForm::getRootIniPath()
  385. {
  386. if (rootFilePath.isEmpty()) {
  387. QString appDir = QCoreApplication::applicationDirPath();
  388. QDir dir(appDir); //bin
  389. dir.cdUp(); //1.2.3.4
  390. dir.cdUp(); //version
  391. dir.cdUp(); //Run
  392. dir.cd("hardwarecfg");
  393. QString rootIniPath = dir.absolutePath() + "/root.ini";
  394. //QFileInfoList rootInis = dir.entryInfoList(QStringList() << "root.ini", QDir::Files);
  395. qDebug() << "root path at media page: " << rootIniPath;
  396. rootFilePath = rootIniPath;
  397. }
  398. return rootFilePath;
  399. }