Ticket #10848: 0001-OSD-Add-a-graphical-display-of-audio-level-to-cut-li.patch
File 0001-OSD-Add-a-graphical-display-of-audio-level-to-cut-li.patch, 21.2 KB (added by , 12 years ago) |
---|
-
new file mythtv/libs/libmyth/audiooutputgraph.cpp
From 2134417d3314af4f14d3d85429d4affb64009225 Mon Sep 17 00:00:00 2001 From: Lawrence Rust <lvr@softsystem.co.uk> Date: Tue, 19 Jun 2012 13:22:56 +0200 Subject: [PATCH] OSD: Add a graphical display of audio level to cut list editor When using the cut list editor to remove ads etc it's difficult to place the cut precisely when the program is faded in or out. In these cases it's common to cut the dialogue or retain voice-overs. It's also impossible to create a cut list for DVB radio recordings. This patch adds a visual graph of the audio level +/-0.5 frame around the current paused frame. Signed-off-by: Lawrence Rust <lvr@softsystem.co.uk> --- mythtv/libs/libmyth/audiooutputgraph.cpp | 276 ++++++++++++++++++++++++++++++ mythtv/libs/libmyth/audiooutputgraph.h | 45 +++++ mythtv/libs/libmyth/libmyth.pro | 3 +- mythtv/libs/libmythtv/audioplayer.h | 6 + mythtv/libs/libmythtv/deletemap.cpp | 5 + mythtv/libs/libmythtv/deletemap.h | 1 + mythtv/libs/libmythtv/mythplayer.cpp | 22 +++- mythtv/libs/libmythtv/mythplayer.h | 5 + mythtv/libs/libmythtv/osd.cpp | 15 ++ mythtv/libs/libmythtv/osd.h | 1 + mythtv/themes/MythCenter-wide/osd.xml | 7 +- mythtv/themes/Terra/osd.xml | 4 + mythtv/themes/default-wide/osd.xml | 5 +- mythtv/themes/default/osd.xml | 7 +- 14 files changed, 394 insertions(+), 8 deletions(-) create mode 100644 mythtv/libs/libmyth/audiooutputgraph.cpp create mode 100644 mythtv/libs/libmyth/audiooutputgraph.h diff --git a/mythtv/libs/libmyth/audiooutputgraph.cpp b/mythtv/libs/libmyth/audiooutputgraph.cpp new file mode 100644 index 0000000..ec736b4
- + 1 #include "audiooutputgraph.h" 2 3 #include <math.h> 4 5 #include <QtGlobal> 6 #include <QImage> 7 #include <QByteArray> 8 #include <QPair> 9 10 #include "mythlogging.h" 11 #include "mythpainter.h" 12 #include "mythimage.h" 13 14 #define LOC QString("AOG::%1").arg(__func__) 15 16 const int kBufferMilliSecs = 500; 17 18 /* 19 * Audio data buffer 20 */ 21 class AudioOutputGraph::Buffer : protected QByteArray 22 { 23 public: 24 Buffer() : 25 m_maxSamples(0), 26 m_sample_rate(44100), 27 m_tcFirst(0), m_tcNext(0), 28 m_bits(0), 29 m_channels(0), 30 m_sizeMax(0) 31 { } 32 virtual ~Buffer() { } 33 34 // Properties 35 void SetMaxSamples(unsigned samples) { m_maxSamples = samples; } 36 void SetSampleRate(unsigned sample_rate) { m_sample_rate = sample_rate; } 37 38 inline int BitsPerChannel() const { return m_bits; } 39 inline int Channels() const { return m_channels; } 40 41 inline int64_t Next() const { return m_tcNext; } 42 inline int64_t First() const { return m_tcFirst; } 43 44 typedef QPair<int64_t, int64_t> range_t; 45 range_t Avail(int64_t timecode) const 46 { 47 if (timecode == 0 || timecode == -1) 48 timecode = m_tcNext; 49 50 int64_t tc1 = timecode - Samples2MS(m_maxSamples / 2); 51 if (tc1 < m_tcFirst) 52 tc1 = m_tcFirst; 53 54 int64_t tc2 = tc1 + Samples2MS(m_maxSamples); 55 if (tc2 > m_tcNext) 56 { 57 tc2 = m_tcNext; 58 if (tc2 < tc1 + Samples2MS(m_maxSamples)) 59 { 60 tc1 = tc2 - Samples2MS(m_maxSamples); 61 if (tc1 < m_tcFirst) 62 tc1 = m_tcFirst; 63 } 64 } 65 return range_t(tc1, tc2); 66 } 67 68 int Samples(const range_t &avail) const 69 { 70 return MS2Samples(avail.second - avail.first); 71 } 72 73 // Operations 74 void Empty() 75 { 76 m_tcFirst = m_tcNext = 0; 77 m_bits = m_channels = 0; 78 resize(0); 79 } 80 81 void Append(const uchar *b, unsigned long len, unsigned long timecode, int channels, int bits) 82 { 83 if (m_bits != bits || m_channels != channels) 84 { 85 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("(%1, %2 channels, %3 bits)") 86 .arg(timecode).arg(channels).arg(bits)); 87 88 Resize(channels, bits); 89 m_tcNext = m_tcFirst = timecode; 90 } 91 92 unsigned samples = Bytes2Samples(len); 93 int64_t tcNext = timecode + Samples2MS(samples); 94 95 if (qAbs(timecode - m_tcNext) <= 1) 96 { 97 append( reinterpret_cast< const char* >(b), len); 98 m_tcNext = tcNext; 99 } 100 else if (timecode >= m_tcFirst && tcNext <= m_tcNext) 101 { 102 // Duplicate 103 return; 104 } 105 else 106 { 107 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString(" discontinuity %1 -> %2") 108 .arg(m_tcNext).arg(timecode)); 109 110 Resize(channels, bits); 111 append( reinterpret_cast< const char* >(b), len); 112 m_tcFirst = timecode; 113 m_tcNext = tcNext; 114 } 115 116 int overflow = size() - m_sizeMax; 117 if (overflow > 0) 118 { 119 remove(0, overflow); 120 m_tcFirst = m_tcNext - Samples2MS(Bytes2Samples(m_sizeMax)); 121 } 122 } 123 124 const int16_t* Data16(const range_t &avail) const 125 { 126 unsigned start = MS2Samples(avail.first - m_tcFirst); 127 return reinterpret_cast< const int16_t* >(constData() + start * BytesPerSample()); 128 } 129 130 protected: 131 inline unsigned BytesPerSample() const 132 { 133 return m_channels * ((m_bits + 7) / 8); 134 } 135 136 inline unsigned Bytes2Samples(unsigned bytes) const 137 { 138 return (m_channels && m_bits) ? bytes / BytesPerSample() : 0; 139 } 140 141 inline unsigned long Samples2MS(unsigned samples) const 142 { 143 return (samples * 1000UL + m_sample_rate - 1) / m_sample_rate; // round up 144 } 145 146 inline unsigned MS2Samples(int64_t ms) const 147 { 148 return ms > 0 ? (ms * m_sample_rate) / 1000 : 0; // NB round down 149 } 150 151 private: 152 void Resize(int channels, int bits) 153 { 154 m_bits = bits; 155 m_channels = channels; 156 m_sizeMax = ((m_sample_rate * kBufferMilliSecs) / 1000) * BytesPerSample(); 157 resize(0); 158 } 159 160 private: 161 unsigned m_maxSamples; 162 unsigned m_sample_rate; 163 unsigned long m_tcFirst, m_tcNext; 164 int m_bits; 165 int m_channels; 166 int m_sizeMax; 167 }; 168 169 170 /* 171 * Audio graphic 172 */ 173 AudioOutputGraph::AudioOutputGraph() : 174 m_painter(0), 175 m_dBsilence(-72), m_dBquiet(-60), m_dBLoud(-12), m_dbMax(-6), 176 m_buffer(new AudioOutputGraph::Buffer()) 177 { } 178 179 AudioOutputGraph::~AudioOutputGraph() 180 { 181 delete m_buffer; 182 } 183 184 void AudioOutputGraph::SetPainter(MythPainter* painter) 185 { 186 m_painter = painter; 187 } 188 189 void AudioOutputGraph::SetSampleRate(unsigned sample_rate) 190 { 191 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("(%1)") 192 .arg(sample_rate)); 193 194 m_buffer->SetSampleRate(sample_rate); 195 } 196 197 void AudioOutputGraph::SetSampleCount(unsigned sample_count) 198 { 199 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("(%1)") 200 .arg(sample_count)); 201 202 m_buffer->SetMaxSamples(sample_count); 203 } 204 205 void AudioOutputGraph::prepare() 206 { 207 } 208 209 void AudioOutputGraph::add(uchar *buf, unsigned long len, unsigned long timecode, int channels, int bits) 210 { 211 m_buffer->Append(buf, len, timecode, channels, bits); 212 } 213 214 void AudioOutputGraph::Reset() 215 { 216 LOG(VB_PLAYBACK, LOG_INFO, LOC); 217 218 m_buffer->Empty(); 219 } 220 221 MythImage *AudioOutputGraph::GetImage(int64_t timecode) const 222 { 223 Buffer::range_t avail = m_buffer->Avail(timecode); 224 225 LOG(VB_PLAYBACK, LOG_INFO, LOC + 226 QString("(%1) using [%2..%3] avail [%4..%5]") 227 .arg(timecode).arg(avail.first).arg(avail.second) 228 .arg(m_buffer->First()).arg(m_buffer->Next()) ); 229 230 const int width = m_buffer->Samples(avail); 231 if (width <= 0) 232 return 0; 233 234 const unsigned range = 1U << m_buffer->BitsPerChannel(); 235 const double threshold = 20 * log10(1.0 / range); // 16bit=-96.3296dB => ~6dB/bit 236 const int height = (int)-ceil(threshold); // 96 237 238 QImage image(width, height, QImage::Format_ARGB32); 239 image.fill(0); 240 241 const int channels = m_buffer->Channels(); 242 243 // Assume signed 16 bit/sample 244 const int16_t *p = m_buffer->Data16(avail); 245 246 for (int x = 0; x < width; ++x) 247 { 248 int left = p[0]; 249 int right = channels > 1 ? p[1] : left; 250 p += channels; 251 252 unsigned avg = qAbs(left) + qAbs(right); 253 double db = 20 * log10( (double)(avg ? avg : 1) / range); 254 255 int idb = (int)ceil(db); 256 QRgb rgb = idb <= m_dBsilence ? qRgb(255, 255, 255) 257 : idb <= m_dBquiet ? qRgb( 0, 255, 255) 258 : idb <= m_dBLoud ? qRgb( 0, 255, 0) 259 : idb <= m_dbMax ? qRgb(255, 255, 0) 260 : qRgb(255, 0, 0); 261 262 int v = height - (int)(height * (db / threshold)); 263 if (v >= height) 264 v = height - 1; 265 else if (v < 0) 266 v = 0; 267 268 for (int y = 0; y <= v; ++y) 269 image.setPixel(x, height - 1 - y, rgb); 270 } 271 272 MythImage *mi = new MythImage(m_painter); 273 mi->Assign(image); 274 return mi; 275 } 276 -
new file mythtv/libs/libmyth/audiooutputgraph.h
diff --git a/mythtv/libs/libmyth/audiooutputgraph.h b/mythtv/libs/libmyth/audiooutputgraph.h new file mode 100644 index 0000000..eff48db
- + 1 #ifndef AUDIOOUTPUTGRAPH_H 2 #define AUDIOOUTPUTGRAPH_H 3 #include <stdint.h> 4 5 #include "mythexp.h" 6 #include "visual.h" 7 8 class MythImage; 9 class MythPainter; 10 11 class MPUBLIC AudioOutputGraph : public MythTV::Visual 12 { 13 public: 14 AudioOutputGraph(); 15 virtual ~AudioOutputGraph(); 16 17 // Properties 18 void SetPainter(MythPainter*); 19 void SetSampleRate(unsigned sample_rate); 20 void SetSampleCount(unsigned sample_count); 21 22 void SetSilenceLevel(int db = -72) { m_dBsilence = db; } 23 void SetQuietLevel(int db = -60) { m_dBquiet = db; } 24 void SetLoudLevel(int db = -12) { m_dBLoud = db; } 25 void SetMaxLevel(int db = -6) { m_dbMax = db; } 26 27 // Operations 28 MythImage *GetImage(int64_t timecode) const; 29 void Reset(); 30 31 // MythTV::Visual implementation 32 public: 33 virtual void add(uchar *b, unsigned long b_len, unsigned long timecode, int chnls, int bits); 34 virtual void prepare(); 35 36 // Implementation 37 private: 38 MythPainter *m_painter; 39 int m_dBsilence, m_dBquiet, m_dBLoud, m_dbMax; 40 class Buffer; 41 Buffer * const m_buffer; 42 }; 43 44 #endif // AUDIOOUTPUTGRAPH_H 45 -
mythtv/libs/libmyth/libmyth.pro
diff --git a/mythtv/libs/libmyth/libmyth.pro b/mythtv/libs/libmyth/libmyth.pro index b457360..010e7cb 100644
a b HEADERS += audio/audiooutpututil.h audio/audiooutputdownmix.h 18 18 HEADERS += audio/audiooutputdigitalencoder.h audio/spdifencoder.h 19 19 HEADERS += audio/audiosettings.h audio/audiooutputsettings.h audio/pink.h 20 20 HEADERS += audio/volumebase.h audio/eldutils.h 21 HEADERS += audiooutputgraph.h 21 22 HEADERS += backendselect.h dbsettings.h dialogbox.h 22 23 HEADERS += langsettings.h 23 24 HEADERS += mythconfigdialogs.h mythconfiggroups.h … … SOURCES += audio/audiooutputnull.cpp 46 47 SOURCES += audio/audiooutpututil.cpp audio/audiooutputdownmix.cpp 47 48 SOURCES += audio/audiosettings.cpp audio/audiooutputsettings.cpp audio/pink.c 48 49 SOURCES += audio/volumebase.cpp audio/eldutils.cpp 49 50 SOURCES += audiooutputgraph.cpp 50 51 SOURCES += backendselect.cpp dbsettings.cpp dialogbox.cpp 51 52 SOURCES += langsettings.cpp 52 53 SOURCES += mythconfigdialogs.cpp mythconfiggroups.cpp -
mythtv/libs/libmythtv/audioplayer.h
diff --git a/mythtv/libs/libmythtv/audioplayer.h b/mythtv/libs/libmythtv/audioplayer.h index a9f2f48..e11821f 100644
a b 3 3 4 4 #include <stdint.h> 5 5 6 #include <QString> 7 #include <QMutex> 8 9 #include "volumebase.h" /* for MuteState */ 10 #include "audiooutputsettings.h" /* for AudioFormat */ 11 6 12 class MythPlayer; 7 13 class AudioOutput; 8 14 -
mythtv/libs/libmythtv/deletemap.cpp
diff --git a/mythtv/libs/libmythtv/deletemap.cpp b/mythtv/libs/libmythtv/deletemap.cpp index 7bb0b66..1ddf6b1 100644
a b void DeleteMap::UpdateOSD(uint64_t frame, uint64_t total, double frame_rate, 200 200 m_cachedTotalForOSD = total; 201 201 } 202 202 203 void DeleteMap::UpdateOSD(int64_t timecode, OSD *osd) 204 { 205 osd->SetGraph("osd_program_editor", "audiograph", timecode); 206 } 207 203 208 /// Set the edit mode and optionally hide the edit mode OSD. 204 209 void DeleteMap::SetEditing(bool edit, OSD *osd) 205 210 { -
mythtv/libs/libmythtv/deletemap.h
diff --git a/mythtv/libs/libmythtv/deletemap.h b/mythtv/libs/libmythtv/deletemap.h index 731fac8..5980b57 100644
a b class MTV_PUBLIC DeleteMap 39 39 void SetSeekAmount(int amount) { m_seekamount = amount; } 40 40 41 41 void UpdateOSD(uint64_t frame, uint64_t total, double frame_rate, OSD *osd); 42 void UpdateOSD(int64_t timecode, OSD *osd); 42 43 43 44 bool IsEditing(void) const { return m_editing; } 44 45 void SetEditing(bool edit, OSD *osd = NULL); -
mythtv/libs/libmythtv/mythplayer.cpp
diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp index 9487346..4ec0836 100644
a b MythPlayer::MythPlayer(PlayerFlags flags) 172 172 totalFrames(0), totalLength(0), 173 173 totalDuration(0), 174 174 rewindtime(0), 175 m_latestVideoTimecode(-1), 175 176 // Input Video Attributes 176 177 video_disp_dim(0,0), video_dim(0,0), 177 178 video_frame_rate(29.97f), video_aspect(4.0f / 3.0f), … … void MythPlayer::ReleaseNextVideoFrame(VideoFrame *buffer, 1123 1124 if (wrap) 1124 1125 WrapTimecode(timecode, TC_VIDEO); 1125 1126 buffer->timecode = timecode; 1127 m_latestVideoTimecode = timecode; 1126 1128 1127 1129 if (videoOutput) 1128 1130 videoOutput->ReleaseFrame(buffer); … … void MythPlayer::RefreshPauseFrame(void) 2025 2027 { 2026 2028 videoOutput->UpdatePauseFrame(disp_timecode); 2027 2029 needNewPauseFrame = false; 2030 2031 if (deleteMap.IsEditing()) 2032 { 2033 osdLock.lock(); 2034 if (osd) 2035 deleteMap.UpdateOSD(GetLatestVideoTimecode(), osd); 2036 osdLock.unlock(); 2037 } 2028 2038 } 2029 2039 else 2030 2040 { … … void MythPlayer::DecoderLoop(bool pause) 3160 3170 continue; 3161 3171 } 3162 3172 3163 DecodeType dt = (audio.HasAudioOut() && normal_speed) ?3173 DecodeType dt = deleteMap.IsEditing() || (audio.HasAudioOut() && normal_speed) ? 3164 3174 kDecodeAV : kDecodeVideo; 3165 3175 3166 3176 DecoderGetFrame(dt); … … bool MythPlayer::DecoderGetFrameFFREW(void) 3190 3200 { 3191 3201 DecoderGetFrameREW(); 3192 3202 } 3193 return decoder->GetFrame( kDecodeVideo);3203 return decoder->GetFrame(deleteMap.IsEditing() ? kDecodeAV : kDecodeVideo); 3194 3204 } 3195 3205 3196 3206 bool MythPlayer::DecoderGetFrameREW(void) … … bool MythPlayer::EnableEdit(void) 3819 3829 if (!osd) 3820 3830 return false; 3821 3831 3832 m_audiograph.SetPainter(videoOutput->GetOSDPainter()); 3833 int sample_rate = GetAudio()->GetSampleRate(); 3834 m_audiograph.SetSampleRate(sample_rate); 3835 m_audiograph.SetSampleCount((unsigned)(sample_rate / video_frame_rate)); 3836 GetAudio()->addVisual(&m_audiograph); 3837 3822 3838 speedBeforeEdit = play_speed; 3823 3839 pausedBeforeEdit = Pause(); 3824 3840 deleteMap.SetEditing(true); … … void MythPlayer::DisableEdit(int howToSave) 3870 3886 if (player_ctx->playingInfo) 3871 3887 player_ctx->playingInfo->SaveEditing(false); 3872 3888 player_ctx->UnlockPlayingInfo(__FILE__, __LINE__); 3889 GetAudio()->removeVisual(&m_audiograph); 3890 m_audiograph.Reset(); 3873 3891 if (!pausedBeforeEdit) 3874 3892 Play(speedBeforeEdit); 3875 3893 else -
mythtv/libs/libmythtv/mythplayer.h
diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h index 67fd3dc..e46d3c9 100644
a b 28 28 #include "deletemap.h" 29 29 #include "commbreakmap.h" 30 30 #include "audioplayer.h" 31 #include "audiooutputgraph.h" 31 32 32 33 #include "mythtvexp.h" 33 34 … … class MTV_PUBLIC MythPlayer 176 177 int GetFFRewSkip(void) const { return ffrew_skip; } 177 178 float GetPlaySpeed(void) const { return play_speed; } 178 179 AudioPlayer* GetAudio(void) { return &audio; } 180 const AudioOutputGraph& GetAudioGraph() const { return m_audiograph; } 179 181 float GetAudioStretchFactor(void) { return audio.GetStretchFactor(); } 180 182 float GetNextPlaySpeed(void) const { return next_play_speed; } 181 183 int GetLength(void) const { return totalLength; } … … class MTV_PUBLIC MythPlayer 183 185 uint64_t GetFramesPlayed(void) const { return framesPlayed; } 184 186 virtual int64_t GetSecondsPlayed(void); 185 187 virtual int64_t GetTotalSeconds(void) const; 188 int64_t GetLatestVideoTimecode() const { return m_latestVideoTimecode; } 186 189 virtual uint64_t GetBookmark(void); 187 190 QString GetError(void) const; 188 191 bool IsErrorRecoverable(void) const … … class MTV_PUBLIC MythPlayer 656 659 long long totalLength; 657 660 int64_t totalDuration; 658 661 long long rewindtime; 662 int64_t m_latestVideoTimecode; 659 663 660 664 // -- end state stuff -- 661 665 … … class MTV_PUBLIC MythPlayer 724 728 725 729 // Audio stuff 726 730 AudioPlayer audio; 731 AudioOutputGraph m_audiograph; 727 732 728 733 // Picture-in-Picture 729 734 PIPMap pip_players; -
mythtv/libs/libmythtv/osd.cpp
diff --git a/mythtv/libs/libmythtv/osd.cpp b/mythtv/libs/libmythtv/osd.cpp index 6b2f09f..732b94d 100644
a b void OSD::SetRegions(const QString &window, frm_dir_map_t &map, 601 601 bar->Display(); 602 602 } 603 603 604 void OSD::SetGraph(const QString &window, const QString &graph, int64_t timecode) 605 { 606 MythScreenType *win = GetWindow(window); 607 if (!win) 608 return; 609 610 MythUIImage *image = dynamic_cast<MythUIImage* >(win->GetChild(graph)); 611 if (!image) 612 return; 613 614 MythImage* mi = m_parent->GetAudioGraph().GetImage(timecode); 615 if (mi) 616 image->SetImage(mi); 617 } 618 604 619 bool OSD::DrawDirect(MythPainter* painter, QSize size, bool repaint) 605 620 { 606 621 if (!painter) -
mythtv/libs/libmythtv/osd.h
diff --git a/mythtv/libs/libmythtv/osd.h b/mythtv/libs/libmythtv/osd.h index 2136fa2..1ec46e3 100644
a b class OSD 161 161 OSDTimeout timeout); 162 162 void SetRegions(const QString &window, frm_dir_map_t &map, 163 163 long long total); 164 void SetGraph(const QString &window, const QString &graph, int64_t timecode); 164 165 bool IsWindowVisible(const QString &window); 165 166 166 167 bool DialogVisible(QString window = QString()); -
mythtv/themes/MythCenter-wide/osd.xml
diff --git a/mythtv/themes/MythCenter-wide/osd.xml b/mythtv/themes/MythCenter-wide/osd.xml index f35f567..ab7b669 100644
a b 414 414 </shape> 415 415 <textarea name="title"> 416 416 <font>medium</font> 417 <area>10,10, 870,40</area>417 <area>10,10,130,40</area> 418 418 <align>left,vcenter</align> 419 419 </textarea> 420 <imagetype name="audiograph"> 421 <area>140,4,500,44</area> 422 </imagetype> 420 423 <textarea name="seekamount" from="title"> 421 <area> 10,10,870,40</area>424 <area>640,10,240,40</area> 422 425 <align>right,vcenter</align> 423 426 </textarea> 424 427 <textarea name="timedisplay" from="title"> -
mythtv/themes/Terra/osd.xml
diff --git a/mythtv/themes/Terra/osd.xml b/mythtv/themes/Terra/osd.xml index f11d40c..bb45fa0 100644
a b 386 386 <value>Video Editor</value> 387 387 </textarea> 388 388 389 <imagetype name="audiograph"> 390 <area>250,30,290,34</area> 391 </imagetype> 392 389 393 <textarea name="timedisplay"> 390 394 <area>540,38,200,30</area> 391 395 <font>basesmall</font> -
mythtv/themes/default-wide/osd.xml
diff --git a/mythtv/themes/default-wide/osd.xml b/mythtv/themes/default-wide/osd.xml index ccebd8a..830399c 100644
a b 511 511 <cornerradius>12</cornerradius> 512 512 </shape> 513 513 <textarea name="title"> 514 <area>10,10, 600,30</area>514 <area>10,10,130,30</area> 515 515 <align>left,top</align> 516 516 <font>small</font> 517 517 </textarea> 518 <imagetype name="audiograph"> 519 <area>140,4,630,34</area> 520 </imagetype> 518 521 <textarea name="seekamount" from="title"> 519 522 <area>770,10,300,30</area> 520 523 <align>right,top</align> -
mythtv/themes/default/osd.xml
diff --git a/mythtv/themes/default/osd.xml b/mythtv/themes/default/osd.xml index 31e6ac6..166a765 100644
a b 511 511 <cornerradius>12</cornerradius> 512 512 </shape> 513 513 <textarea name="title"> 514 <area>6,8, 375,25</area>514 <area>6,8,120,25</area> 515 515 <align>left,top</align> 516 516 <font>small</font> 517 517 </textarea> 518 <imagetype name="audiograph"> 519 <area>126,2,412,23</area> 520 </imagetype> 518 521 <textarea name="seekamount" from="title"> 519 <area> 481,8,187,25</area>522 <area>538,8,130,25</area> 520 523 <align>right,top</align> 521 524 </textarea> 522 525 <textarea name="timedisplay" from="title">