PageRenderTime 24ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/rosegarden-12.04/src/gui/dialogs/AudioSplitDialog.cpp

#
C++ | 355 lines | 246 code | 55 blank | 54 comment | 20 complexity | b663069d667155bb63988f4441389a2d MD5 | raw file
Possible License(s): GPL-2.0
  1. /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
  2. /*
  3. Rosegarden
  4. A MIDI and audio sequencer and musical notation editor.
  5. Copyright 2000-2012 the Rosegarden development team.
  6. Other copyrights also apply to some parts of this work. Please
  7. see the AUTHORS file and individual file headers for details.
  8. This program is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU General Public License as
  10. published by the Free Software Foundation; either version 2 of the
  11. License, or (at your option) any later version. See the file
  12. COPYING included with this distribution for more information.
  13. */
  14. #include "AudioSplitDialog.h"
  15. #include "misc/Debug.h"
  16. #include "misc/Strings.h"
  17. #include "base/Exception.h"
  18. #include "base/RealTime.h"
  19. #include "base/Segment.h"
  20. #include "document/RosegardenDocument.h"
  21. #include "gui/application/RosegardenApplication.h"
  22. #include "sound/AudioFileManager.h"
  23. #include <QDialog>
  24. #include <QDialogButtonBox>
  25. #include <QDesktopServices>
  26. #include <QGroupBox>
  27. #include <QLabel>
  28. #include <QPalette>
  29. #include <QScrollArea>
  30. #include <QSpinBox>
  31. #include <QString>
  32. #include <QWidget>
  33. #include <QVBoxLayout>
  34. #include <QHBoxLayout>
  35. #include <QApplication>
  36. #include <QGraphicsScene>
  37. #include <QGraphicsView>
  38. #include <QGraphicsRectItem>
  39. #include <QList>
  40. #include <QGraphicsSimpleTextItem>
  41. namespace Rosegarden
  42. {
  43. AudioSplitDialog::AudioSplitDialog(QWidget *parent,
  44. Segment *segment,
  45. RosegardenDocument *doc):
  46. QDialog(parent),
  47. m_doc(doc),
  48. m_segment(segment),
  49. m_sceneWidth(500),
  50. m_sceneHeight(200),
  51. m_previewWidth(400),
  52. m_previewHeight(100)
  53. {
  54. if (!segment || segment->getType() != Segment::Audio)
  55. reject();
  56. setModal(true);
  57. // pre-pend "Rosegarden" to title in a way that preserves existing
  58. // translations unchanged:
  59. QString title = QString("%1 - %2").arg(tr("Rosegarden")).arg(tr("Autosplit Audio Segment"));
  60. setWindowTitle(title);
  61. QVBoxLayout *layout = new QVBoxLayout;
  62. setLayout(layout);
  63. //!!! Use "Autosplit" or "AutoSplit" but not both. I'm ignoring this to
  64. // avoid string changes, but for 10.04 this should change to "Auto-split"
  65. // throughout, I think.
  66. QLabel *label = new QLabel(tr("AutoSplit Segment \"") + strtoqstr(m_segment->getLabel()) + QString("\""));
  67. layout->addWidget(label);
  68. QGroupBox *box = new QGroupBox;
  69. QVBoxLayout *boxLayout = new QVBoxLayout;
  70. box->setLayout(boxLayout);
  71. layout->addWidget(box);
  72. m_scene = new QGraphicsScene;
  73. m_view = new QGraphicsView(m_scene);
  74. boxLayout->addWidget(m_view);
  75. QWidget *hbox = new QWidget;
  76. QHBoxLayout *hboxLayout = new QHBoxLayout;
  77. hbox->setLayout(hboxLayout);
  78. boxLayout->addWidget(hbox);
  79. label = new QLabel(tr("Threshold"));
  80. hboxLayout->addWidget(label);
  81. m_thresholdSpin = new QSpinBox;
  82. hboxLayout->addWidget(m_thresholdSpin);
  83. m_thresholdSpin->setSuffix(" %");
  84. connect(m_thresholdSpin, SIGNAL(valueChanged(int)),
  85. SLOT(slotThresholdChanged(int)));
  86. // ensure this is cleared
  87. m_previewBoxes.clear();
  88. // Set thresholds
  89. //
  90. int threshold = 1;
  91. m_thresholdSpin->setValue(threshold);
  92. drawPreview();
  93. drawSplits(1);
  94. QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help);
  95. layout->addWidget(buttonBox);
  96. connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
  97. connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
  98. connect(buttonBox, SIGNAL(helpRequested()), this, SLOT(slotHelpRequested()));
  99. }
  100. void
  101. AudioSplitDialog::slotHelpRequested()
  102. {
  103. // TRANSLATORS: if the manual is translated into your language, you can
  104. // change the two-letter language code in this URL to point to your language
  105. // version, eg. "http://rosegardenmusic.com/wiki/doc:audioSplitDialog-es" for the
  106. // Spanish version. If your language doesn't yet have a translation, feel
  107. // free to create one.
  108. QString helpURL = tr("http://rosegardenmusic.com/wiki/doc:audioSplitDialog-en");
  109. QDesktopServices::openUrl(QUrl(helpURL));
  110. }
  111. void
  112. AudioSplitDialog::noPreviewMsg()
  113. {
  114. QGraphicsSimpleTextItem *text =
  115. new QGraphicsSimpleTextItem(tr("<no preview generated for this audio file>"));
  116. text->setBrush(Qt::black);
  117. m_scene->addItem(text);
  118. text->setPos(30, 30);
  119. }
  120. void
  121. AudioSplitDialog::drawPreview()
  122. {
  123. // Delete everything in the scene
  124. //
  125. QList<QGraphicsItem *> list = m_scene->items();
  126. for (QList<QGraphicsItem *>::Iterator it = list.begin();
  127. it != list.end(); it++) {
  128. delete *it;
  129. }
  130. // empty the preview boxes
  131. m_previewBoxes.erase(m_previewBoxes.begin(), m_previewBoxes.end());
  132. // Draw a bounding box
  133. //
  134. int border = 5;
  135. m_scene->addRect(0, 0,
  136. m_sceneWidth - border * 2,
  137. m_sceneHeight - border * 2,
  138. QPen(Qt::black, border),
  139. Qt::white);
  140. // Get preview in vector form
  141. //
  142. AudioFileManager &aFM = m_doc->getAudioFileManager();
  143. AudioFile *aF = aFM.getAudioFile(m_segment->getAudioFileId());
  144. if (aF == NULL) {
  145. noPreviewMsg();
  146. return;
  147. }
  148. int channels = aF->getChannels();
  149. std::vector<float> values;
  150. try {
  151. values = aFM.getPreview(m_segment->getAudioFileId(),
  152. m_segment->getAudioStartTime(),
  153. m_segment->getAudioEndTime(),
  154. m_previewWidth,
  155. false);
  156. } catch (Exception e) {
  157. noPreviewMsg();
  158. return ;
  159. }
  160. qreal startX = (m_sceneWidth - m_previewWidth) / 2;
  161. qreal halfHeight = m_sceneHeight / 2;
  162. float h1, h2;
  163. std::vector<float>::iterator it = values.begin();
  164. // Draw preview
  165. //
  166. for (int i = 0; i < m_previewWidth; i++) {
  167. if (channels == 1) {
  168. h1 = *(it++);
  169. h2 = h1;
  170. } else {
  171. h1 = *(it++);
  172. h2 = *(it++);
  173. }
  174. qreal startY = halfHeight + h1 * float(m_previewHeight / 2);
  175. qreal endY = halfHeight - h2 * float(m_previewHeight / 2);
  176. if (startY < 0) {
  177. RG_DEBUG << "AudioSplitDialog::AudioSplitDialog - "
  178. << "startY - out of negative range"
  179. << endl;
  180. startY = 0;
  181. }
  182. if (endY < 0) {
  183. RG_DEBUG << "AudioSplitDialog::AudioSplitDialog - "
  184. << "endY - out of negative range"
  185. << endl;
  186. endY = 0;
  187. }
  188. m_scene->addLine(startX + qreal(i),
  189. startY,
  190. startX + qreal(i),
  191. endY,
  192. QPen(Qt::black));
  193. }
  194. // Draw zero dc line
  195. //
  196. m_scene->addRect(startX,
  197. halfHeight - 1,
  198. qreal(m_previewWidth),
  199. 2,
  200. QPen(Qt::black),
  201. QBrush(Qt::gray));
  202. // Start time
  203. //
  204. char msecs[100];
  205. sprintf(msecs, "%03d", m_segment->getAudioStartTime().msec());
  206. QString startText = QString("%1.%2s")
  207. .arg(m_segment->getAudioStartTime().sec)
  208. .arg(msecs);
  209. QGraphicsSimpleTextItem *text = new QGraphicsSimpleTextItem(startText);
  210. text->setBrush(Qt::black);
  211. m_scene->addItem(text);
  212. text->setPos(startX - 20,
  213. qreal(m_sceneHeight) / 2 - qreal(m_previewHeight) / 2 - 35);
  214. m_scene->addRect(startX - 1,
  215. qreal(m_sceneHeight) / 2 - qreal(m_previewHeight) / 2 - 14,
  216. 1,
  217. qreal(m_previewHeight) + 28,
  218. QPen(Qt::black),
  219. QBrush(Qt::gray));
  220. // End time
  221. //
  222. sprintf(msecs, "%03d", m_segment->getAudioEndTime().msec());
  223. QString endText = QString("%1.%2s")
  224. .arg(m_segment->getAudioEndTime().sec)
  225. .arg(msecs);
  226. text = new QGraphicsSimpleTextItem(endText);
  227. text->setBrush(Qt::black);
  228. m_scene->addItem(text);
  229. text->setPos(startX + qreal(m_previewWidth) - 20,
  230. qreal(m_sceneHeight) / 2 - qreal(m_previewHeight) / 2 - 35);
  231. m_scene->addRect(startX + qreal(m_previewWidth) - 1,
  232. qreal(m_sceneHeight) / 2 - qreal(m_previewHeight) / 2 - 14,
  233. 1,
  234. qreal(m_previewHeight) + 28,
  235. QPen(Qt::black),
  236. QBrush(Qt::gray));
  237. }
  238. void
  239. AudioSplitDialog::drawSplits(int threshold)
  240. {
  241. // Now get the current split points and paint them
  242. //
  243. RealTime startTime = m_segment->getAudioStartTime();
  244. RealTime endTime = m_segment->getAudioEndTime();
  245. AudioFileManager &aFM = m_doc->getAudioFileManager();
  246. std::vector<SplitPointPair> splitPoints =
  247. aFM.getSplitPoints(m_segment->getAudioFileId(),
  248. startTime,
  249. endTime,
  250. threshold);
  251. std::vector<SplitPointPair>::iterator it;
  252. std::vector<QGraphicsRectItem*> tempRects;
  253. RealTime length = endTime - startTime;
  254. double ticksPerUsec = double(m_previewWidth) /
  255. double((length.sec * 1000000.0) + length.usec());
  256. qreal startX = (m_sceneWidth - m_previewWidth) / 2;
  257. qreal halfHeight = m_sceneHeight / 2;
  258. qreal x1, x2;
  259. qreal overlapHeight = 10;
  260. for (it = splitPoints.begin(); it != splitPoints.end(); it++) {
  261. RealTime splitStart = it->first - startTime;
  262. RealTime splitEnd = it->second - startTime;
  263. x1 = ticksPerUsec * double(double(splitStart.sec) * 1000000.0 + (double)splitStart.usec());
  264. x2 = ticksPerUsec * double(double(splitEnd.sec) * 1000000.0 + double(splitEnd.usec()));
  265. QGraphicsRectItem *rect = m_scene->addRect(startX + x1,
  266. halfHeight - qreal(m_previewHeight) / 2 - overlapHeight / 2,
  267. x2 - x1,
  268. qreal(m_previewHeight) + overlapHeight,
  269. QPen(Qt::red),
  270. QBrush(Qt::blue));
  271. tempRects.push_back(rect);
  272. }
  273. std::vector<QGraphicsRectItem*>::iterator pIt;
  274. // We've written the new Rects, now delete the old ones
  275. //
  276. if (m_previewBoxes.size()) {
  277. // clear any previous preview boxes
  278. //
  279. for (pIt = m_previewBoxes.begin(); pIt != m_previewBoxes.end(); pIt++) {
  280. //(*pIt)->setVisible(false);
  281. delete (*pIt);
  282. }
  283. m_previewBoxes.erase(m_previewBoxes.begin(), m_previewBoxes.end());
  284. // m_scene->update();
  285. }
  286. // m_scene->update();
  287. // Now store the new ones
  288. //
  289. for (pIt = tempRects.begin(); pIt != tempRects.end(); pIt++)
  290. m_previewBoxes.push_back(*pIt);
  291. }
  292. void
  293. AudioSplitDialog::slotThresholdChanged(int threshold)
  294. {
  295. drawSplits(threshold);
  296. }
  297. }
  298. #include "AudioSplitDialog.moc"