Visualisations slow still? (1 Viewer)

Nemulate

Portal Pro
December 29, 2005
607
9
IOW
Home Country
England England
Hi,

just wondered if ths is still a known problem as some visualisations are unusable in MP whilst fine in WMP10?

Thanks
 

bigj

Portal Pro
January 10, 2005
245
1
Nemulate said:
Hi,

just wondered if ths is still a known problem as some visualisations are unusable in MP whilst fine in WMP10?

Thanks

It's still the same - I did some investigation work a while back - the gPlayer has a flag to go fullscreen that is still set false I think - this may be root cause - I wrote a test plugin from WMP that just never received the 'fullscreen' flag. For say a D3D visualisation, this would allow the vis to Present (via HW) rather than have to GDI copy. Wish I had more time to fix this, but hope this helps.
BigJ.
 

Nemulate

Portal Pro
December 29, 2005
607
9
IOW
Home Country
England England
Ok so sounds like it's a programing bug then? The vis never realises it's in full screen so can't use hardware d3d? Will see if it's in mantis then. Thanks
 

bigj

Portal Pro
January 10, 2005
245
1
Ok, so I finally got round to checking out the CVS and building the project from the sources...

I tried applying the fullscreen flag to the player and it does solve the issue with visualisations running slow when fullscreen. I had to apply a workaround for MP losing focus (borrowed from elsewhere in the project).

There's some caveats with this as it stands:

1. To prevent it going fullscreen when running MP in a window, I check for this and fallback to the previous stretch-blit method in this case. This is consistent then with the other player modes (tv, movies etc).

2. Some vis plugins try to change screen res when going fullscreen; so if using say a TV-out be prepared for this.

Perhaps if this was ever to be applied to the tree there should be an option added to the configuration to allow users to choose.
e.g.
WMPlayer Visualisation Fullscreen : Use Stretch [ ], Use true fullscreen [X]
In which case the check for 1. above would be redundant since the user option could be used as an explicit preference.

I tested it and it works at high framerates for GForce and for my own test plugin - was 8fps now >35fps

Here's the new code; sorry to dump it here, I can't get CVS/tortoise to work consistently for some reason.

AudioPlayerWMP9.cs
See SetVideoWindow...


/*
* Copyright (C) 2005 Team MediaPortal
* https://www.team-mediaportal.com
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
using System;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Diagnostics;
using MediaPortal.TagReader;
using MediaPortal.Util;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.Win32;
using Direct3D = Microsoft.DirectX.Direct3D;



using MediaPortal.GUI.Library;
using DirectShowLib;
namespace MediaPortal.Player
{
public class AudioPlayerWMP9 : IPlayer
{
private const int SW_SHOW = 5;
private const int SW_RESTORE = 9;
public const Int32 TOGGLE_HIDEWINDOW = 0x080;
public const Int32 TOGGLE_UNHIDEWINDOW = 0x040;
public const Int32 HWND_TOPMOST = -1;
public const Int32 HWND_NOTOPMOST = -2;

[DllImport("User32")]
private static extern int SetForegroundWindow(IntPtr hwnd);

// Activates a window
[DllImportAttribute("User32.DLL")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();

public enum PlayState
{
Init,
Playing,
Paused,
Ended
}
string _currentFile = "";
PlayState _graphState = PlayState.Init;
bool _isFullScreen = false;
int _positionX = 10, _positionY = 10, _videoWidth = 100, _videoHeight = 100;
static AxWMPLib.AxWindowsMediaPlayer _wmp10Player = null;
bool _needUpdate = true;
bool _notifyPlaying = true;

public AudioPlayerWMP9()
{
}


static void CreateInstance()
{
// disable auto windows mediaplayer auto cd-play
if (_wmp10Player != null) return;
try
{
UInt32 dwValue = (UInt32)0;
RegistryKey hkcu = Registry.CurrentUser;
RegistryKey subkey = hkcu.OpenSubKey(@"Software\Microsoft\MediaPlayer\Preferences", true);

subkey.SetValue("CDAutoPlay", (Int32)dwValue);

// enable metadata lookup for CD's
dwValue = (UInt32)Convert.ToInt32(subkey.GetValue("MetadataRetrieval"));
dwValue |= 1;
subkey.SetValue("MetadataRetrieval", (Int32)dwValue);
subkey.Close();
hkcu.Close();
}
catch (Exception) { }

_wmp10Player = new AxWMPLib.AxWindowsMediaPlayer();


_wmp10Player.BeginInit();
GUIGraphicsContext.form.SuspendLayout();
_wmp10Player.Enabled = true;

System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Resource1));
_wmp10Player.Location = new System.Drawing.Point(8, 16);
_wmp10Player.Name = "axWindowsMediaPlayer1";
_wmp10Player.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axWindowsMediaPlayer1.OcxState")));
_wmp10Player.Size = new System.Drawing.Size(264, 240);
_wmp10Player.TabIndex = 0;
GUIGraphicsContext.form.Controls.Add(_wmp10Player);


try
{
_wmp10Player.EndInit();
}
catch (COMException)
{
}

_wmp10Player.uiMode = "none";
_wmp10Player.windowlessVideo = true;

_wmp10Player.enableContextMenu = false;
_wmp10Player.Ctlenabled = false;
_wmp10Player.Visible = false;
GUIGraphicsContext.form.ResumeLayout(false);


}

static public ArrayList GetCDTracks()
{
GUIListItem item;
ArrayList list = new ArrayList();
item = new GUIListItem();
item.IsFolder = true;
item.Label = "..";
item.Label2 = "";
item.Path = "";
Utils.SetDefaultIcons(item);
Utils.SetThumbnails(ref item);
list.Add(item);

CreateInstance();
if (_wmp10Player.cdromCollection.count <= 0) return list;
if (_wmp10Player.cdromCollection.count <= 0) return list;


WMPLib.IWMPCdrom cdrom = _wmp10Player.cdromCollection.Item(0);

if (cdrom == null) return list;
if (cdrom.Playlist == null) return list;


for (int iTrack = 0; iTrack < cdrom.Playlist.count; iTrack++)
{
try
{
MusicTag tag = new MusicTag();
WMPLib.IWMPMedia media = cdrom.Playlist.get_Item(iTrack);
item = new GUIListItem();
item.IsFolder = false;
item.Label = media.name;
item.Label2 = "";
item.Path = String.Format("cdda:{0}", iTrack);
item.FileInfo = null;

for (int i = 0; i < media.attributeCount; ++i)
{
string strAttr = media.getAttributeName(i);
string strValue = media.getItemInfo(strAttr);
if (String.Compare("album", strAttr, true) == 0) tag.Album = strValue;
if (String.Compare("actor", strAttr, true) == 0) tag.Artist = strValue;
if (String.Compare("artist", strAttr, true) == 0) tag.Artist = strValue;
if (String.Compare("style", strAttr, true) == 0) tag.Genre = strValue;
if (String.Compare("releasedate", strAttr, true) == 0)
{
try
{
tag.Year = Convert.ToInt32(strValue.Substring(0, 4));
}
catch (Exception)
{
}
}
}
tag.Title = media.name;
tag.Duration = (int)media.duration;
tag.Track = iTrack + 1;
//tag.Comment =
//tag.Year =
//tag.Genre =
item.MusicTag = tag;
list.Add(item);
}
catch (Exception)
{
}
}
return list;
}

public override bool Play(string strFile)
{
_graphState = PlayState.Init;
_currentFile = strFile;

_notifyPlaying = true;
GC.Collect();
CreateInstance();

if (_wmp10Player == null) return false;
if (_wmp10Player.cdromCollection == null) return false;

_wmp10Player.PlayStateChange += new AxWMPLib._WMPOCXEvents_PlayStateChangeEventHandler(OnPlayStateChange);

//_wmp10Player.enableContextMenu = false;
//_wmp10Player.Ctlenabled = false;
if (strFile.IndexOf("cdda:") >= 0)
{
string strTrack = strFile.Substring(5);
int iTrack = Convert.ToInt32(strTrack);
if (_wmp10Player.cdromCollection.count <= 0) return false;
if (_wmp10Player.cdromCollection.Item(0).Playlist == null) return false;
if (iTrack > _wmp10Player.cdromCollection.Item(0).Playlist.count) return false;
_wmp10Player.currentMedia = _wmp10Player.cdromCollection.Item(0).Playlist.get_Item(iTrack - 1);
if (_wmp10Player.currentMedia == null) return false;

Log.Write("Audioplayer:play track:{0}/{1}", iTrack, _wmp10Player.cdromCollection.Item(0).Playlist.count);
}
else if (strFile.IndexOf(".cda") >= 0)
{
string strTrack = "";
int pos = strFile.IndexOf(".cda");
if (pos >= 0)
{
pos--;
while (Char.IsDigit(strFile[pos]) && pos > 0)
{
strTrack = strFile[pos] + strTrack;
pos--;
}
}

if (_wmp10Player.cdromCollection.count <= 0) return false;
string strDrive = strFile.Substring(0, 1);
strDrive += ":";
int iCdRomDriveNr = 0;
while ((_wmp10Player.cdromCollection.Item(iCdRomDriveNr).driveSpecifier != strDrive) && (iCdRomDriveNr < _wmp10Player.cdromCollection.count))
{
iCdRomDriveNr++;
}

int iTrack = Convert.ToInt32(strTrack);
if (_wmp10Player.cdromCollection.Item(iCdRomDriveNr).Playlist == null) return false;
int tracks = _wmp10Player.cdromCollection.Item(iCdRomDriveNr).Playlist.count;
if (iTrack > tracks) return false;
_wmp10Player.currentMedia = _wmp10Player.cdromCollection.Item(iCdRomDriveNr).Playlist.get_Item(iTrack - 1);
if (_wmp10Player.currentMedia == null) return false;
/*
string strStart=strFile.Substring(0,2)+@"\";
int ipos=strFile.LastIndexOf("+");
if (ipos >0) strStart += strFile.Substring(ipos+1);
strFile=strStart;
_currentFile=strFile;
Log.Write("Audioplayer:play {0}", strFile);*/
//_wmp10Player.URL=strFile;
_currentFile = strFile;
}
else
{
Log.Write("Audioplayer:play {0}", strFile);
_wmp10Player.URL = strFile;
}
_wmp10Player.Ctlcontrols.play();
_wmp10Player.Visible = false;


GUIMessage msg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_PLAYBACK_STARTED, 0, 0, 0, 0, 0, null);
msg.Label = strFile;

GUIWindowManager.SendThreadMessage(msg);
_graphState = PlayState.Playing;
GC.Collect();
_needUpdate = true;
_isFullScreen = GUIGraphicsContext.IsFullScreenVideo;
_positionX = GUIGraphicsContext.VideoWindow.Left;
_positionY = GUIGraphicsContext.VideoWindow.Top;
_videoWidth = GUIGraphicsContext.VideoWindow.Width;
_videoHeight = GUIGraphicsContext.VideoWindow.Height;

SetVideoWindow();

return true;
}

private void OnPlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if (_wmp10Player == null) return;
switch (_wmp10Player.playState)
{
case WMPLib.WMPPlayState.wmppsStopped:
SongEnded(false);
break;
}
}

void SongEnded(bool bManualStop)
{
// this is triggered only if movie has ended
// ifso, stop the movie which will trigger MovieStopped

if (!Utils.IsAudio(_currentFile))
GUIGraphicsContext.IsFullScreenVideo = false;
Log.Write("Audioplayer:ended {0} {1}", _currentFile, bManualStop);
_currentFile = "";
if (_wmp10Player != null)
{
_wmp10Player.Visible = false;
_wmp10Player.PlayStateChange -= new AxWMPLib._WMPOCXEvents_PlayStateChangeEventHandler(OnPlayStateChange);
}
//GUIGraphicsContext.IsFullScreenVideo=false;
GUIGraphicsContext.IsPlaying = false;
if (!bManualStop)
{
_graphState = PlayState.Ended;
}
else
{
_graphState = PlayState.Init;
}
GC.Collect();
}


public override bool Ended
{
get { return _graphState == PlayState.Ended; }
}

public override double Duration
{
get
{
if (_graphState != PlayState.Init && _wmp10Player != null)
{
try
{
return _wmp10Player.currentMedia.duration;
}
catch (Exception)
{
}
}
return 0.0d;
}
}

public override double CurrentPosition
{
get
{
try
{
return _wmp10Player.Ctlcontrols.currentPosition;
}
catch (Exception)
{
}
return 0.0d;
}
}

public override void Pause()
{
if (_wmp10Player == null) return;
if (_graphState == PlayState.Paused)
{
_graphState = PlayState.Playing;
_wmp10Player.Ctlcontrols.play();
}
else if (_graphState == PlayState.Playing)
{
_wmp10Player.Ctlcontrols.pause();
if (_wmp10Player.playState == WMPLib.WMPPlayState.wmppsPaused)
_graphState = PlayState.Paused;
}
}

public override bool Paused
{
get
{
return (_graphState == PlayState.Paused);
}
}

public override bool Playing
{
get
{
return (_graphState == PlayState.Playing || _graphState == PlayState.Paused);
}
}

public override bool Stopped
{
get
{
return (_graphState == PlayState.Init);
}
}

public override string CurrentFile
{
get { return _currentFile; }
}

public override void Stop()
{
if (_wmp10Player == null) return;
if (_graphState != PlayState.Init)
{
_wmp10Player.Ctlcontrols.stop();
_wmp10Player.Visible = false;
SongEnded(true);
}
}

public override int Volume
{
get
{

if (_wmp10Player == null) return 100;
return _wmp10Player.settings.volume;
}
set
{

if (_wmp10Player == null) return;
if (_wmp10Player.settings.volume != value)
{
_wmp10Player.settings.volume = value;
}
}
}


public override bool HasVideo
{
get { return true; }
}


#region IDisposable Members

public override void Release()
{
/*
if (_wmp10Player == null) return;
_wmp10Player.Visible = false;

try
{
GUIGraphicsContext.form.Controls.Remove(_wmp10Player);
}
catch (Exception) { }
_wmp10Player.Dispose();
_wmp10Player = null;
* */
}
#endregion

public override bool FullScreen
{
get
{
return GUIGraphicsContext.IsFullScreenVideo;
}
set
{
if (value != _isFullScreen)
{
_isFullScreen = value;
_needUpdate = true;
}
}
}
public override int PositionX
{
get { return _positionX; }
set
{
if (value != _positionX)
{
_positionX = value;
_needUpdate = true;
}
}
}

public override int PositionY
{
get { return _positionY; }
set
{
if (value != _positionY)
{
_positionY = value;
_needUpdate = true;
}
}
}

public override int RenderWidth
{
get { return _videoWidth; }
set
{
if (value != _videoWidth)
{
_videoWidth = value;
_needUpdate = true;
}
}
}
public override int RenderHeight
{
get { return _videoHeight; }
set
{
if (value != _videoHeight)
{
_videoHeight = value;
_needUpdate = true;
}
}
}

public override void Process()
{
if (!Playing) return;
if (_wmp10Player == null) return;
if (GUIGraphicsContext.BlankScreen || (GUIGraphicsContext.Overlay == false && GUIGraphicsContext.IsFullScreenVideo == false))
{
if (_wmp10Player.Visible)
{
_wmp10Player.ClientSize = new Size(0, 0);
_wmp10Player.Visible = false;
//_wmp10Player.uiMode = "invisible";
}
}
else if (!_wmp10Player.Visible)
{
_needUpdate = true;
SetVideoWindow();
//_wmp10Player.uiMode = "none";
_wmp10Player.Visible = true;
}


if (CurrentPosition >= 10.0)
{
if (_notifyPlaying)
{
_notifyPlaying = false;
GUIMessage msg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_PLAYING_10SEC, 0, 0, 0, 0, 0, null);
msg.Label = CurrentFile;
GUIWindowManager.SendThreadMessage(msg);
}
}
}

public override void SetVideoWindow()
{

if (_wmp10Player == null) return;
if (GUIGraphicsContext.IsFullScreenVideo != _isFullScreen)
{
_isFullScreen = GUIGraphicsContext.IsFullScreenVideo;
_needUpdate = true;
}
if (!_needUpdate) return;
_needUpdate = false;


if (_isFullScreen)
{
Log.Write("AudioPlayer:Fullscreen");

IntPtr mpHwnd = GetActiveWindow();

_positionX = GUIGraphicsContext.OverScanLeft;
_positionY = GUIGraphicsContext.OverScanTop;
_videoWidth = GUIGraphicsContext.OverScanWidth;
_videoHeight = GUIGraphicsContext.OverScanHeight;

_wmp10Player.Location = new Point(0, 0);
_wmp10Player.ClientSize = new System.Drawing.Size(GUIGraphicsContext.Width, GUIGraphicsContext.Height);
_wmp10Player.Size = new System.Drawing.Size(GUIGraphicsContext.Width, GUIGraphicsContext.Height);

_videoRectangle = new Rectangle(0, 0, _wmp10Player.ClientSize.Width, _wmp10Player.ClientSize.Height);
_sourceRectangle = _videoRectangle;

// If MediaPortal app is fullscreen then go true fullscreen
Rectangle scr = Screen.PrimaryScreen.WorkingArea;
bool bMPIsFullscreen =
(GUIGraphicsContext.Width == scr.Width) &&
(GUIGraphicsContext.Height == scr.Height);

Log.Write("Screen is {0}x{1}, GUIGraphicsContext is {2}x{3} => {4}",
scr.Width, scr.Height, GUIGraphicsContext.Width, GUIGraphicsContext.Height,
bMPIsFullscreen?"Effectively fullscreen":"Treat as windowed");

if (bMPIsFullscreen)
{
Log.Write("AudioPlayer:confused:witching wmp10Player fullscreen");
_wmp10Player.fullScreen = true;
_wmp10Player.stretchToFit = false;
}
// else go stretchy
else
{
Log.Write("AudioPlayer:confused:witching wmp10Player non-fullscreen, stretchToFit");
_wmp10Player.stretchToFit = true;
}

// Restore original focus
ShowWindow(mpHwnd, SW_RESTORE);
SetForegroundWindow(mpHwnd);

Log.Write("AudioPlayer:done");

return;
}
else
{

_wmp10Player.ClientSize = new System.Drawing.Size(_videoWidth, _videoHeight);
_wmp10Player.Location = new Point(_positionX, _positionY);

_videoRectangle = new Rectangle(_positionX, _positionY, _wmp10Player.ClientSize.Width, _wmp10Player.ClientSize.Height);
_sourceRectangle = _videoRectangle;
//Log.Write("AudioPlayer:set window:({0},{1})-({2},{3})",_positionX,_positionY,_positionX+_wmp10Player.ClientSize.Width,_positionY+_wmp10Player.ClientSize.Height);

Log.Write("AudioPlayer:Not fullscreen");
_wmp10Player.fullScreen = false;
_wmp10Player.stretchToFit = true;
}
//_wmp10Player.uiMode = "none";
//_wmp10Player.windowlessVideo = true;
//_wmp10Player.enableContextMenu = false;
//_wmp10Player.Ctlenabled = false;
GUIGraphicsContext.form.Controls[0].Enabled = false;
}
/*
public override int AudioStreams
{
get { return _wmp10Player.Ctlcontrols.audioLanguageCount;}
}
public override int CurrentAudioStream
{
get { return _wmp10Player.Ctlcontrols.currentAudioLanguage;}
set { _wmp10Player.Ctlcontrols.currentAudioLanguage=value;}
}
public override string AudioLanguage(int iStream)
{
return _wmp10Player.controls.getLanguageName(iStream);
}
*/
public override void SeekRelative(double dTime)
{
if (_wmp10Player == null) return;
if (_graphState != PlayState.Init)
{

double dCurTime = CurrentPosition;
dTime = dCurTime + dTime;
if (dTime < 0.0d) dTime = 0.0d;
if (dTime < Duration)
{
_wmp10Player.Ctlcontrols.currentPosition = dTime;
}
}
}

public override void SeekAbsolute(double dTime)
{
if (_wmp10Player == null) return;
if (_graphState != PlayState.Init)
{
if (dTime < 0.0d) dTime = 0.0d;
if (dTime < Duration)
{
_wmp10Player.Ctlcontrols.currentPosition = dTime;
}
}
}

public override void SeekRelativePercentage(int iPercentage)
{
if (_wmp10Player == null) return;
if (_graphState != PlayState.Init)
{
double dCurrentPos = CurrentPosition;
double dDuration = Duration;

double fCurPercent = (dCurrentPos / Duration) * 100.0d;
double fOnePercent = Duration / 100.0d;
fCurPercent = fCurPercent + (double)iPercentage;
fCurPercent *= fOnePercent;
if (fCurPercent < 0.0d) fCurPercent = 0.0d;
if (fCurPercent < Duration)
{
_wmp10Player.Ctlcontrols.currentPosition = fCurPercent;
}
}
}


public override void SeekAsolutePercentage(int iPercentage)
{
if (_wmp10Player == null) return;
if (_graphState != PlayState.Init)
{
if (iPercentage < 0) iPercentage = 0;
if (iPercentage >= 100) iPercentage = 100;
double fPercent = Duration / 100.0f;
fPercent *= (double)iPercentage;
_wmp10Player.Ctlcontrols.currentPosition = fPercent;
}
}
public override int Speed
{
get
{
if (_graphState == PlayState.Init) return 1;
if (_wmp10Player == null) return 1;
return (int)_wmp10Player.settings.rate;
}
set
{
if (_wmp10Player == null) return;
if (_graphState != PlayState.Init)
{
try
{
_wmp10Player.settings.rate = (double)value;
}
catch (Exception)
{
}
}
}
}

}
}
 

bigj

Portal Pro
January 10, 2005
245
1
thechad said:
You should submit the patch to sourceforge so that it an be merged in from their. May be missed in here as threads title does not mention a patch.

Ok - I worked out how the patching/sf submissions work; I think.
"1411517 WMP Audio Visualisations : Enable true fullscreen""
 

Users who are viewing this thread

Similar threads

MP1 MP2 DVB-T playback DE
Those signal numbers look fine. (y) Unfortunately, I don't have any other suggestions as to the possible cause of your problem. :( -- from CyberSimian in the UK
Those signal numbers look fine. (y) Unfortunately, I don't have any other suggestions as to the possible cause of your problem. :(...
I've just rebuilt my htpc and added DVB-S and DVB-T cards TBS6281 and TBS6982. The system is all working well except for playback...
Replies
3
Views
632
You can find ton of guide here: https://www.avsforum.com/threads/madvr-player-support-thread.2215490/?post_id=39123050#post-39123050
You can find ton of guide here: https://www.avsforum.com/threads/madvr-player-support-thread.2215490/?post_id=39123050#post-39123050
Hi, I have a problem if I set madVR as Video Render. When I try to play my .mkv files I have an 'Unable to play. Video COdec...
Replies
3
Views
949
Yes, all compatible with x64 ;)
Yes, all compatible with x64 ;)
Hi folks, for all those who would like to enjoy Mediaportal on the Titanskin, I have now adapted the well-known MP games package...
Replies
7
Views
734
The layout of remotes does vary from one model/brand to another. I too find that some layouts are better than others. Generally, I prefer the buttons that I use most-frequently to be positioned near the center of the remote, which is not the case with that particular Dell remote. :( Battery life is often a problem. A remote that I...
The layout of remotes does vary from one model/brand to another. I too find that some layouts are better than others. Generally, I...
In Dec 2020: I purchased 2 remotes for my new HTPC install, eg: HP USB MCE IR RC6 Wireless Receiver and TSGH-IR02 Windows Media...
Replies
16
Views
3K
Strange ...
Strange ...
Updated MP client from 1.29 to 1.32. Kept Titan skin same as previously; very standard no Extended etc (afaik). The TV menu item...
Replies
5
Views
2K
Top Bottom