Add dialog to display streams' audio details (#5547)
* Add Stream Details window * Fix capitalization in StreamDiscoverer::Discover() * StreamDiscoverer::Discover(): get URL by const reference * Refactor StreamDiscoverer::Discover * Rename StreamDiscoverer callbacks * StreamDiscoverer::OnDiscovered: fix nullptr comparison * StreamDiscoverer: rename DiscoverFinished signal * StreamDiscoverer::DataReady: receive const reference * StreamDiscoverer: Remove unsigned types * StreamDetailsDialog: rename Close slot * StreamDetailsDialog: rename ui pointer to ui_ * MainWindow::ShowStreamDetails: receive a const reference * StreamDetailsDialog: use unique_ptr, remove unsigned types
This commit is contained in:
parent
589d641955
commit
d3898d2f47
|
@ -68,6 +68,7 @@ pkg_check_modules(GSTREAMER_APP REQUIRED gstreamer-app-1.0)
|
|||
pkg_check_modules(GSTREAMER_AUDIO REQUIRED gstreamer-audio-1.0)
|
||||
pkg_check_modules(GSTREAMER_BASE REQUIRED gstreamer-base-1.0)
|
||||
pkg_check_modules(GSTREAMER_TAG REQUIRED gstreamer-tag-1.0)
|
||||
pkg_check_modules(GSTREAMER_PBUTILS REQUIRED gstreamer-pbutils-1.0)
|
||||
pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92)
|
||||
pkg_check_modules(LIBMTP libmtp>=1.0)
|
||||
pkg_check_modules(LIBMYGPO_QT libmygpo-qt>=1.0.9)
|
||||
|
@ -155,6 +156,7 @@ include_directories(${GSTREAMER_APP_INCLUDE_DIRS})
|
|||
include_directories(${GSTREAMER_AUDIO_INCLUDE_DIRS})
|
||||
include_directories(${GSTREAMER_BASE_INCLUDE_DIRS})
|
||||
include_directories(${GSTREAMER_TAG_INCLUDE_DIRS})
|
||||
include_directories(${GSTREAMER_PBUTILS_INCLUDE_DIRS})
|
||||
include_directories(${GLIB_INCLUDE_DIRS})
|
||||
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
|
||||
include_directories(${LIBXML_INCLUDE_DIRS})
|
||||
|
|
|
@ -311,6 +311,7 @@ set(SOURCES
|
|||
songinfo/songkickconcertwidget.cpp
|
||||
songinfo/songplaystats.cpp
|
||||
songinfo/spotifyimages.cpp
|
||||
songinfo/streamdiscoverer.cpp
|
||||
songinfo/taglyricsinfoprovider.cpp
|
||||
songinfo/ultimatelyricslyric.cpp
|
||||
songinfo/ultimatelyricsprovider.cpp
|
||||
|
@ -358,6 +359,7 @@ set(SOURCES
|
|||
ui/settingsdialog.cpp
|
||||
ui/settingspage.cpp
|
||||
ui/standarditemiconloader.cpp
|
||||
ui/streamdetailsdialog.cpp
|
||||
ui/systemtrayicon.cpp
|
||||
ui/trackselectiondialog.cpp
|
||||
ui/windows7thumbbar.cpp
|
||||
|
@ -603,6 +605,7 @@ set(HEADERS
|
|||
songinfo/songkickconcertwidget.h
|
||||
songinfo/songplaystats.h
|
||||
songinfo/spotifyimages.h
|
||||
songinfo/streamdiscoverer.h
|
||||
songinfo/taglyricsinfoprovider.h
|
||||
songinfo/ultimatelyricslyric.h
|
||||
songinfo/ultimatelyricsprovider.h
|
||||
|
@ -641,6 +644,7 @@ set(HEADERS
|
|||
ui/settingsdialog.h
|
||||
ui/settingspage.h
|
||||
ui/standarditemiconloader.h
|
||||
ui/streamdetailsdialog.h
|
||||
ui/systemtrayicon.h
|
||||
ui/trackselectiondialog.h
|
||||
ui/windows7thumbbar.h
|
||||
|
@ -764,6 +768,7 @@ set(UI
|
|||
ui/organiseerrordialog.ui
|
||||
ui/playbacksettingspage.ui
|
||||
ui/settingsdialog.ui
|
||||
ui/streamdetailsdialog.ui
|
||||
ui/trackselectiondialog.ui
|
||||
|
||||
widgets/equalizerslider.ui
|
||||
|
@ -1265,6 +1270,7 @@ target_link_libraries(clementine_lib
|
|||
${GSTREAMER_LIBRARIES}
|
||||
${GSTREAMER_APP_LIBRARIES}
|
||||
${GSTREAMER_TAG_LIBRARIES}
|
||||
${GSTREAMER_PBUTILS_LIBRARIES}
|
||||
${QTSINGLEAPPLICATION_LIBRARIES}
|
||||
${QTSINGLECOREAPPLICATION_LIBRARIES}
|
||||
${QTIOCOMPRESSOR_LIBRARIES}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <QtConcurrentRun>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/pbutils/pbutils.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "devicefinder.h"
|
||||
|
@ -146,6 +147,8 @@ bool GstEngine::Init() {
|
|||
void GstEngine::InitialiseGstreamer() {
|
||||
gst_init(nullptr, nullptr);
|
||||
|
||||
gst_pb_utils_init();
|
||||
|
||||
#ifdef HAVE_MOODBAR
|
||||
gstfastspectrum_register_static();
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
#include "streamdiscoverer.h"
|
||||
|
||||
#include <gst/pbutils/pbutils.h>
|
||||
#include "core/logging.h"
|
||||
#include "core/signalchecker.h"
|
||||
#include "core/waitforsignal.h"
|
||||
|
||||
#include <QEventLoop>
|
||||
|
||||
const int StreamDiscoverer::kDiscoveryTimeoutS = 10;
|
||||
|
||||
StreamDiscoverer::StreamDiscoverer() : QObject(nullptr) {
|
||||
// Setting up a discoverer:
|
||||
discoverer_ = gst_discoverer_new(kDiscoveryTimeoutS * GST_SECOND, NULL);
|
||||
if (discoverer_ == NULL) {
|
||||
qLog(Error) << "Error creating discoverer" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Connecting its signals:
|
||||
CHECKED_GCONNECT(discoverer_, "discovered", &OnDiscovered, this);
|
||||
CHECKED_GCONNECT(discoverer_, "finished", &OnFinished, this);
|
||||
|
||||
// Starting the discoverer process:
|
||||
gst_discoverer_start(discoverer_);
|
||||
}
|
||||
|
||||
StreamDiscoverer::~StreamDiscoverer() {
|
||||
gst_discoverer_stop(discoverer_);
|
||||
g_object_unref(discoverer_);
|
||||
}
|
||||
|
||||
void StreamDiscoverer::Discover(const QString& url) {
|
||||
// Adding the request to discover the url given as a parameter:
|
||||
qLog(Debug) << "Discover" << url;
|
||||
if (!gst_discoverer_discover_uri_async(discoverer_,
|
||||
url.toStdString().c_str())) {
|
||||
qLog(Error) << "Failed to start discovering" << url << endl;
|
||||
return;
|
||||
}
|
||||
WaitForSignal(this, SIGNAL(DiscoverFinished()));
|
||||
}
|
||||
|
||||
void StreamDiscoverer::OnDiscovered(GstDiscoverer* discoverer,
|
||||
GstDiscovererInfo* info, GError* err,
|
||||
gpointer self) {
|
||||
StreamDiscoverer* instance = reinterpret_cast<StreamDiscoverer*>(self);
|
||||
|
||||
QString discovered_url(gst_discoverer_info_get_uri(info));
|
||||
|
||||
GstDiscovererResult result = gst_discoverer_info_get_result(info);
|
||||
if (result != GST_DISCOVERER_OK) {
|
||||
QString error_message = GSTdiscovererErrorMessage(result);
|
||||
qLog(Error) << "Discovery failed:" << error_message << endl;
|
||||
emit instance->Error(
|
||||
tr("Error discovering %1: %2").arg(discovered_url).arg(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get audio streams (we will only care about the first one, which should be
|
||||
// the only one).
|
||||
GList* audio_streams = gst_discoverer_info_get_audio_streams(info);
|
||||
|
||||
if (audio_streams != nullptr) {
|
||||
qLog(Debug) << "Discovery successful" << endl;
|
||||
// We found a valid audio stream, extracting and saving its info:
|
||||
GstDiscovererStreamInfo* stream_audio_info =
|
||||
(GstDiscovererStreamInfo*)g_list_first(audio_streams)->data;
|
||||
|
||||
StreamDetails stream_details;
|
||||
stream_details.url = discovered_url;
|
||||
stream_details.bitrate = gst_discoverer_audio_info_get_bitrate(
|
||||
GST_DISCOVERER_AUDIO_INFO(stream_audio_info));
|
||||
stream_details.channels = gst_discoverer_audio_info_get_channels(
|
||||
GST_DISCOVERER_AUDIO_INFO(stream_audio_info));
|
||||
stream_details.depth = gst_discoverer_audio_info_get_depth(
|
||||
GST_DISCOVERER_AUDIO_INFO(stream_audio_info));
|
||||
stream_details.sample_rate = gst_discoverer_audio_info_get_sample_rate(
|
||||
GST_DISCOVERER_AUDIO_INFO(stream_audio_info));
|
||||
|
||||
// Human-readable codec name:
|
||||
GstCaps* stream_caps =
|
||||
gst_discoverer_stream_info_get_caps(stream_audio_info);
|
||||
gchar* decoder_description =
|
||||
gst_pb_utils_get_codec_description(stream_caps);
|
||||
stream_details.format = (decoder_description == NULL)
|
||||
? QString(tr("Unknown"))
|
||||
: QString(decoder_description);
|
||||
|
||||
gst_caps_unref(stream_caps);
|
||||
g_free(decoder_description);
|
||||
|
||||
emit instance->DataReady(stream_details);
|
||||
|
||||
} else {
|
||||
emit instance->Error(
|
||||
tr("Could not detect an audio stream in %1").arg(discovered_url));
|
||||
}
|
||||
|
||||
gst_discoverer_stream_info_list_free(audio_streams);
|
||||
}
|
||||
|
||||
void StreamDiscoverer::OnFinished(GstDiscoverer* discoverer, gpointer self) {
|
||||
// The discoverer doesn't have any more urls in its queue. Let the loop know
|
||||
// it can exit.
|
||||
StreamDiscoverer* instance = reinterpret_cast<StreamDiscoverer*>(self);
|
||||
emit instance->DiscoverFinished();
|
||||
}
|
||||
|
||||
QString StreamDiscoverer::GSTdiscovererErrorMessage(
|
||||
GstDiscovererResult result) {
|
||||
switch (result) {
|
||||
case (GST_DISCOVERER_URI_INVALID):
|
||||
return tr("Invalid URL");
|
||||
case (GST_DISCOVERER_TIMEOUT):
|
||||
return tr("Connection timed out");
|
||||
case (GST_DISCOVERER_BUSY):
|
||||
return tr("The discoverer is busy");
|
||||
case (GST_DISCOVERER_MISSING_PLUGINS):
|
||||
return tr("Missing plugins");
|
||||
case (GST_DISCOVERER_ERROR):
|
||||
default:
|
||||
return tr("Could not get details");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef STREAMDISCOVERER_H
|
||||
#define STREAMDISCOVERER_H
|
||||
|
||||
#include <gst/pbutils/pbutils.h>
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
struct StreamDetails {
|
||||
QString url;
|
||||
QString format;
|
||||
int bitrate;
|
||||
int depth;
|
||||
int channels;
|
||||
int sample_rate;
|
||||
};
|
||||
Q_DECLARE_METATYPE(StreamDetails)
|
||||
|
||||
class StreamDiscoverer : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StreamDiscoverer();
|
||||
~StreamDiscoverer();
|
||||
|
||||
void Discover(const QString& url);
|
||||
|
||||
signals:
|
||||
void DiscoverFinished();
|
||||
void DataReady(const StreamDetails& data);
|
||||
void Error(const QString& message);
|
||||
|
||||
private:
|
||||
GstDiscoverer* discoverer_;
|
||||
|
||||
static const int kDiscoveryTimeoutS;
|
||||
|
||||
// GstDiscoverer callbacks:
|
||||
static void OnDiscovered(GstDiscoverer* discoverer, GstDiscovererInfo* info,
|
||||
GError* err, gpointer instance);
|
||||
static void OnFinished(GstDiscoverer* discoverer, gpointer instance);
|
||||
|
||||
// Helper to return descriptive error messages:
|
||||
static QString GSTdiscovererErrorMessage(GstDiscovererResult result);
|
||||
};
|
||||
|
||||
#endif // STREAMDISCOVERER_H
|
|
@ -101,6 +101,7 @@
|
|||
#include "smartplaylists/generatormimedata.h"
|
||||
#include "songinfo/artistinfoview.h"
|
||||
#include "songinfo/songinfoview.h"
|
||||
#include "songinfo/streamdiscoverer.h"
|
||||
#include "transcoder/transcodedialog.h"
|
||||
#include "ui/about.h"
|
||||
#include "ui/addstreamdialog.h"
|
||||
|
@ -113,6 +114,7 @@
|
|||
#include "ui/organiseerrordialog.h"
|
||||
#include "ui/qtsystemtrayicon.h"
|
||||
#include "ui/settingsdialog.h"
|
||||
#include "ui/streamdetailsdialog.h"
|
||||
#include "ui/systemtrayicon.h"
|
||||
#include "ui/trackselectiondialog.h"
|
||||
#include "ui/windows7thumbbar.h"
|
||||
|
@ -173,6 +175,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
|||
tray_icon_(tray_icon),
|
||||
osd_(osd),
|
||||
edit_tag_dialog_(std::bind(&MainWindow::CreateEditTagDialog, this)),
|
||||
stream_discoverer_(std::bind(&MainWindow::CreateStreamDiscoverer, this)),
|
||||
global_shortcuts_(new GlobalShortcuts(this)),
|
||||
global_search_view_(new GlobalSearchView(app_, this)),
|
||||
library_view_(new LibraryViewContainer(this)),
|
||||
|
@ -477,6 +480,8 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
|||
SLOT(ShowQueueManager()));
|
||||
connect(ui_->action_add_files_to_transcoder, SIGNAL(triggered()),
|
||||
SLOT(AddFilesToTranscoder()));
|
||||
connect(ui_->action_view_stream_details, SIGNAL(triggered()),
|
||||
SLOT(DiscoverStreamDetails()));
|
||||
|
||||
background_streams_->AddAction("Rain", ui_->action_rain);
|
||||
background_streams_->AddAction("Hypnotoad", ui_->action_hypnotoad);
|
||||
|
@ -684,6 +689,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
|||
playlist_menu_->addAction(ui_->action_remove_from_playlist);
|
||||
playlist_undoredo_ = playlist_menu_->addSeparator();
|
||||
playlist_menu_->addAction(ui_->action_edit_track);
|
||||
playlist_menu_->addAction(ui_->action_view_stream_details);
|
||||
playlist_menu_->addAction(ui_->action_edit_value);
|
||||
playlist_menu_->addAction(ui_->action_renumber_tracks);
|
||||
playlist_menu_->addAction(ui_->action_selection_set_value);
|
||||
|
@ -1712,6 +1718,10 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos,
|
|||
// no 'show in browser' action if only streams are selected
|
||||
playlist_open_in_browser_->setVisible(streams != all);
|
||||
|
||||
// If exactly one stream is selected, enable the 'show details' action.
|
||||
ui_->action_view_stream_details->setEnabled(all == 1 && streams == 1);
|
||||
ui_->action_view_stream_details->setVisible(all == 1 && streams == 1);
|
||||
|
||||
bool track_column = (index.column() == Playlist::Column_Track);
|
||||
ui_->action_renumber_tracks->setVisible(editable >= 2 && track_column);
|
||||
ui_->action_selection_set_value->setVisible(editable >= 2 && !track_column);
|
||||
|
@ -1882,6 +1892,27 @@ void MainWindow::EditTagDialogAccepted() {
|
|||
app_->playlist_manager()->current()->Save();
|
||||
}
|
||||
|
||||
void MainWindow::DiscoverStreamDetails() {
|
||||
int row = playlist_menu_index_.row();
|
||||
Song song = app_->playlist_manager()->current()->item_at(row)->Metadata();
|
||||
|
||||
QString url = song.url().toString();
|
||||
stream_discoverer_->Discover(url);
|
||||
}
|
||||
|
||||
void MainWindow::ShowStreamDetails(const StreamDetails& details) {
|
||||
StreamDetailsDialog stream_details_dialog(this);
|
||||
|
||||
stream_details_dialog.setUrl(details.url);
|
||||
stream_details_dialog.setFormat(details.format);
|
||||
stream_details_dialog.setBitrate(details.bitrate);
|
||||
stream_details_dialog.setChannels(details.channels);
|
||||
stream_details_dialog.setDepth(details.depth);
|
||||
stream_details_dialog.setSampleRate(details.sample_rate);
|
||||
|
||||
stream_details_dialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::RenumberTracks() {
|
||||
QModelIndexList indexes =
|
||||
ui_->playlist->view()->selectionModel()->selection().indexes();
|
||||
|
@ -2490,6 +2521,14 @@ EditTagDialog* MainWindow::CreateEditTagDialog() {
|
|||
return edit_tag_dialog;
|
||||
}
|
||||
|
||||
StreamDiscoverer* MainWindow::CreateStreamDiscoverer() {
|
||||
StreamDiscoverer* discoverer = new StreamDiscoverer();
|
||||
connect(discoverer, SIGNAL(DataReady(StreamDetails)),
|
||||
SLOT(ShowStreamDetails(StreamDetails)));
|
||||
connect(discoverer, SIGNAL(Error(QString)), SLOT(ShowErrorDialog(QString)));
|
||||
return discoverer;
|
||||
}
|
||||
|
||||
void MainWindow::ShowAboutDialog() { about_dialog_->show(); }
|
||||
|
||||
void MainWindow::ShowTranscodeDialog() { transcode_dialog_->show(); }
|
||||
|
|
|
@ -31,8 +31,10 @@
|
|||
#include "engines/engine_fwd.h"
|
||||
#include "library/librarymodel.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
#include "songinfo/streamdiscoverer.h"
|
||||
#include "ui/organisedialog.h"
|
||||
#include "ui/settingsdialog.h"
|
||||
#include "ui/streamdetailsdialog.h"
|
||||
|
||||
class About;
|
||||
class AddStreamDialog;
|
||||
|
@ -72,6 +74,7 @@ class RipCDDialog;
|
|||
class Song;
|
||||
class SongInfoBase;
|
||||
class SongInfoView;
|
||||
class StreamDetailsDialog;
|
||||
class SystemTrayIcon;
|
||||
class TagFetcher;
|
||||
class TaskManager;
|
||||
|
@ -165,6 +168,8 @@ signals:
|
|||
void PlaylistEditFinished(const QModelIndex& index);
|
||||
void EditTracks();
|
||||
void EditTagDialogAccepted();
|
||||
void DiscoverStreamDetails();
|
||||
void ShowStreamDetails(const StreamDetails& details);
|
||||
void RenumberTracks();
|
||||
void SelectionSetValue();
|
||||
void EditValue();
|
||||
|
@ -252,6 +257,7 @@ signals:
|
|||
void ShowVisualisations();
|
||||
SettingsDialog* CreateSettingsDialog();
|
||||
EditTagDialog* CreateEditTagDialog();
|
||||
StreamDiscoverer* CreateStreamDiscoverer();
|
||||
void OpenSettingsDialog();
|
||||
void OpenSettingsDialogAtPage(SettingsDialog::Page page);
|
||||
void ShowSongInfoConfig();
|
||||
|
@ -299,6 +305,7 @@ signals:
|
|||
OSD* osd_;
|
||||
Lazy<EditTagDialog> edit_tag_dialog_;
|
||||
Lazy<About> about_dialog_;
|
||||
Lazy<StreamDiscoverer> stream_discoverer_;
|
||||
|
||||
GlobalShortcuts* global_shortcuts_;
|
||||
|
||||
|
|
|
@ -928,6 +928,11 @@
|
|||
<string>Remove unavailable tracks from playlist</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_view_stream_details">
|
||||
<property name="text">
|
||||
<string>View Stream Details</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_toggle_show_sidebar">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#include "streamdetailsdialog.h"
|
||||
#include "ui_streamdetailsdialog.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
StreamDetailsDialog::StreamDetailsDialog(QWidget* parent)
|
||||
: QDialog(parent), ui_(new Ui::StreamDetailsDialog) {
|
||||
ui_->setupUi(this);
|
||||
}
|
||||
|
||||
StreamDetailsDialog::~StreamDetailsDialog() {}
|
||||
|
||||
void StreamDetailsDialog::setUrl(const QString& url) {
|
||||
ui_->url->setText(url);
|
||||
ui_->url->setCursorPosition(0);
|
||||
}
|
||||
void StreamDetailsDialog::setFormat(const QString& format) {
|
||||
ui_->format->setText(format);
|
||||
}
|
||||
void StreamDetailsDialog::setBitrate(int bitrate) {
|
||||
ui_->bitrate->setText(QString("%1 kbps").arg(bitrate / 1000));
|
||||
|
||||
// Some bitrates aren't properly reported by GStreamer.
|
||||
// In that case do not display bitrate information.
|
||||
ui_->bitrate->setVisible(bitrate != 0);
|
||||
ui_->bitrate_label->setVisible(bitrate != 0);
|
||||
}
|
||||
void StreamDetailsDialog::setChannels(int channels) {
|
||||
ui_->channels->setText(QString::number(channels));
|
||||
}
|
||||
void StreamDetailsDialog::setDepth(int depth) {
|
||||
// Right now GStreamer seems to be reporting incorrect numbers for MP3 and AAC
|
||||
// streams, so we leave that value hidden in the UI.
|
||||
// ui_->depth->setText(QString("%1 bits").arg(depth));
|
||||
ui_->depth->setVisible(false);
|
||||
ui_->depth_label->setVisible(false);
|
||||
}
|
||||
void StreamDetailsDialog::setSampleRate(int sample_rate) {
|
||||
ui_->sample_rate->setText(QString("%1 Hz").arg(sample_rate));
|
||||
}
|
||||
|
||||
void StreamDetailsDialog::Close() { this->close(); }
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef STREAMDETAILSDIALOG_H
|
||||
#define STREAMDETAILSDIALOG_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class StreamDetailsDialog;
|
||||
}
|
||||
|
||||
class StreamDetailsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit StreamDetailsDialog(QWidget* parent = 0);
|
||||
~StreamDetailsDialog();
|
||||
|
||||
void setUrl(const QString& url);
|
||||
void setFormat(const QString& codec); // This is localized, so only for human
|
||||
// consumption.
|
||||
void setBitrate(int);
|
||||
void setDepth(int);
|
||||
void setChannels(int);
|
||||
void setSampleRate(int);
|
||||
|
||||
private slots:
|
||||
void Close();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::StreamDetailsDialog> ui_;
|
||||
};
|
||||
|
||||
#endif // STREAMDETAILSDIALOG_H
|
|
@ -0,0 +1,148 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>StreamDetailsDialog</class>
|
||||
<widget class="QDialog" name="StreamDetailsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>210</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>210</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Stream Details</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="url_label">
|
||||
<property name="text">
|
||||
<string>URL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="url">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="format_label">
|
||||
<property name="text">
|
||||
<string>Format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="format">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="channels_label">
|
||||
<property name="text">
|
||||
<string>Channels</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="channels">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="bitrate_label">
|
||||
<property name="text">
|
||||
<string>Bit rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="bitrate">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="sample_rate_label">
|
||||
<property name="text">
|
||||
<string>Sample rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="sample_rate">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="depth_label">
|
||||
<property name="text">
|
||||
<string>Depth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="depth">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>StreamDetailsDialog</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>299</x>
|
||||
<y>186</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>249</x>
|
||||
<y>104</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
Reference in New Issue