AtmoLight 2.1.0.0 for MediaPortal2 [2015-01-21]

Discussion in 'Plugin Development' started by Rick164, April 22, 2014.

  1. Rick164
    • Super User

    Rick164 Super User

    Joined:
    January 7, 2006
    Messages:
    1,335
    Likes Received:
    918
    Ratings:
    +1,359 / 0
    Home Country:
    Netherlands Netherlands
    Show System Specs
    Overview

    AtmoLight is a process plugin that interfaces with different ambilight solutions and brings Ambilight to MediaPortal.
    The main function is to send the needed data directly to your ambilight solution to reduce the CPU load drastically, making Ambilight and smooth playback possible.
    This is the MediaPortal2 Version of AtmoLight. You can find the version for MediaPortal here.

    Installation

    Extract the rar to C:\Program Files (x86)\Team MediaPortal\MP2-Client\Plugins


    If you have been using a test version older than Beta 1, please manually delete the AtmoLight.Settings.xml before using Beta 1 or newer. The xml is located in C:\ProgramData\Team MediaPortal\MP2-Client\Config\{USER_NAME}\.

    Beta 2 is only compatible to MP2 10th AE Update 1 or newer and all AtmoLight 2.0 version before that are only compatible to MP2 10th AE or older.

    2.0.0.0 Final is only compatible to MP2 Weekly 2014-11-15 or newer.


    Useful Links

    Changelog

    Code (Text):
    1.  
    2. Version 2.1.0.0
    3. - Fixed bug where data would be send to target handler even if handler is disconnected from target
    4. - Improved average color calculation for Hue handler
    5. - Improved VUMeter and VUMeter Rainbow effects
    6. - Fixed bug where GIFReader was case sensitive for the file extensions
    7. - Fixed a bug where connecting to AtmoWin would fail
    8. - Fixed bug where some effects would not be set properly on MediaPortal2 start up
    9. - Added possibility to use hostnames/multicast dns with Hyperion
    10. - Added AmbiBox handler
    11.  
    12. Version 2.0.0.0
    13. - Added interface to support other targets (not just AtmoWin)
    14. - Added Hyperion as target software
    15. - Added Hue as target (AtmoHue needed)
    16. - Added Boblight as target software
    17. - Added possibility to use more then one target software (e.g. AtmoWin and Hyperion at the same time)
    18. - Added "MediaPortal exit" effect (effect that gets set when MediaPortal gets closed)
    19. - Added possibility to change every setting on the fly (no MediaPortal2 restart for specific settings required anymore)
    20. - Added VU Meter and VU Meter Rainbow effects
    21. - Added blackbar detection and removal
    22. - Fixed bug where AtmoLight would do nothing when a player ends
    23. - Added support for Picture-in-Picture mode
    24. - Various small bug fixes
    25.  
    26. Version 2.0.0.0 Beta 2
    27. - Fixed bug where MediaPortal could crash to Desktop
    28. - Fixed issue where AtmoLight would always disable LEDs after reconnect
    29. - Fixed bug with deactivate between time
    30. - Added GIF Reader effect (adds support for custom effects made by users)
    31.  
    32. Version 2.0.0.0 Beta 1
    33. - Added delay feature
    34. - Added AtmoLight configuration within MP2
    35. - Added notification if connection to AtmoWin is lost
    36. - Added possibility to reconnect to AtmoWin using the remote buttons
    37.  
    38. Version 2.0.0.0 Alpha 5
    39. - Fixed bug where AtmoWin would not be stopped on MP2 exit
    40. - Added color button support
    41.     * Default: Red=ContextMenu (not implemented yet), Green=Toggle LEDs, Yellow=Change AtmoWin Profile
    42. - Changed some types in the settings. Please delete current settings file before using this version!
    43.  
    44. Version 2.0.0.0 Alpha 4
    45. - Changed UICapture to use player surface on videoplayback (faster and no blackbar problems)
    46. - Added settings
    47. - Added automatic mode
    48.     * Video effect, Music effect and Menu effect
    49.     * Timeframe where leds should be off (exclude time)
    50.     * Manual Mode (currently no way to change effects manually)
    51. - Added Low CPU feature
    52.  
    53. Version 2.0.0.0 Alpha 3
    54. - Fixed memory leak
    55. - Added possibility to use MediaPortal liveview mode for the whole UI
    56.  
    57. Version 2.0.0.0 Alpha 2
    58. - Added MediaPortal liveview mode
    59.  
    60. Version 2.0.0.0 Alpha 1
    61. - Initial Release

    Active developers

    @Rick164

    Thanks

    We would like to thank everybody who has worked on and contributed to AtmoLight in the past.
    @gemx, @angie05, @legnod, @azzuro, @BassFan, @HomeY, @Sebastiii, @Lightning303

    If i forgot someone please let me know.




    Original Post:
    Show Spoiler
    Hey,
    im currently trying to make a AtmoLight plugin for MP2. At the moment its just a skeleton and im trying to get all the tools ready i need.
    I already figgured out how i can set up an event handler for PlayerStarted aswell as PlayerStopped.

    Code (C):
    1.       void SubscribeToMessages()
    2.       {
    3.         messageQueue = new AsynchronousMessageQueue(this, new string[] { PlayerManagerMessaging.CHANNEL });
    4.         messageQueue.MessageReceived += OnMessageReceived;
    5.         messageQueue.Start();
    6.       }
    7.  
    8.       void OnMessageReceived(AsynchronousMessageQueue queue, SystemMessage message)
    9.       {
    10.         if (message.ChannelName == PlayerManagerMessaging.CHANNEL)
    11.         {
    12.           PlayerManagerMessaging.MessageType messageType = (PlayerManagerMessaging.MessageType)message.MessageType;
    13.           if (messageType == PlayerManagerMessaging.MessageType.PlayerStarted)
    14.           {
    15.             Log.Info("AtmoLight: Playback started.");
    16.           }
    17.           else if (messageType == PlayerManagerMessaging.MessageType.PlayerStopped)
    18.           {
    19.             Log.Info("AtmoLight: Playback stopped.");
    20.           }
    21.         }
    22.       }
    Please let me know if there is a better way to do that.

    What i dont know at the moment is how i can figure out what kind of media is playing. In MP1 i could use something like g_Player.IsVideo, or i would get the mediatype as parameter in the PlaybackStarted eventhandler.

    Also, what i dont know yet is how to get the video frames (surfaces) to work with them and send them to AtmoWin. This would be the counter part to mp1's framegrabber. @morpheus_xx said here that this is possible, but i just dont know how :(.

    I would highly appreciate any help. And please be patient with me, i consider myself a beginner :).
     
    Last edited: May 18, 2016
    • Like Like x 4
    • Thank You! Thank You! x 3
  2. Google AdSense Guest Advertisement



    to hide all adverts.
  3. BigGranu
    • Team MediaPortal

    BigGranu Development Group

    Joined:
    February 7, 2013
    Messages:
    238
    Likes Received:
    113
    Gender:
    Male
    Ratings:
    +178 / 0
    Home Country:
    Germany Germany
    e.g
    Code (C):
    1.  
    2. var isVideo = ServiceRegistration.Get<IPlayerContextManager>().IsVideoContextActive
    3. var isAudio = ServiceRegistration.Get<IPlayerContextManager>().IsAudioContextActive
    4.  
    About the Videoframes :oops:. I know nothing about it.
     
    • Thank You! Thank You! x 1
  4. morpheus_xx
    • Team MediaPortal

    morpheus_xx Lead Dev MP2

    Joined:
    March 24, 2007
    Messages:
    11,090
    Likes Received:
    4,766
    Ratings:
    +6,826 / 11
    Home Country:
    Germany Germany
    Show System Specs
    You can access active players via IPlayerManager service. Try to cast the IPlayer to ISlimDXPlayer, it has a Surface property. Not sure what you need for processing, but it would be a start.
    I'm on smartphone now and can't link to sources...
     
  5. Lightning303
    • Premium Supporter

    Lightning303 MP Donator

    Joined:
    September 12, 2009
    Messages:
    798
    Likes Received:
    384
    Gender:
    Male
    Ratings:
    +578 / 0
    Home Country:
    Germany Germany
    Show System Specs
    To be honest, you lost me there already :(. But no hurry, maybe when you are on you pc and have a spare 5 minutes you could look at this. I will try to explain what we are using right now for MP1. However, i did not build this, i just inharited it, especially the framegrabber part.

    In MP1 we use an event handler, like this:
    Code (C):
    1.     FrameGrabber.GetInstance().OnNewFrame += new FrameGrabber.NewFrameHandler(AtmolightPlugin_OnNewFrame);
    2.  
    3.     private void AtmolightPlugin_OnNewFrame(short width, short height, short arWidth, short arHeight, uint pSurface)
    4.     {
    5.       if (playbackEffect != ContentEffect.MediaPortalLiveMode || atmoOff || atmoCtrl == null || width == 0 || height == 0 || reInitializeLock)
    6.       {
    7.         return;
    8.       }
    9.  
    10.       if (rgbSurface == null)
    11.       {
    12.         rgbSurface = GUIGraphicsContext.DX9Device.CreateRenderTarget(captureWidth, captureHeight, Format.A8R8G8B8,
    13.           MultiSampleType.None, 0, true);
    14.       }
    15.       unsafe
    16.       {
    17.         try
    18.         {
    19.           if (AtmolightSettings.sbs3dOn)
    20.           {
    21.             VideoSurfaceToRGBSurfaceExt(new IntPtr(pSurface), width / 2, height, (IntPtr)rgbSurface.UnmanagedComPointer,
    22.               captureWidth, captureHeight);
    23.           }
    24.           else
    25.           {
    26.             VideoSurfaceToRGBSurfaceExt(new IntPtr(pSurface), width, height, (IntPtr)rgbSurface.UnmanagedComPointer,
    27.               captureWidth, captureHeight);
    28.           }
    29.  
    30.           Microsoft.DirectX.GraphicsStream stream = SurfaceLoader.SaveToStream(ImageFileFormat.Bmp, rgbSurface);
    31.  
    32.           BinaryReader reader = new BinaryReader(stream);
    33.           stream.Position = 0; // ensure that what start at the beginning of the stream.
    34.           reader.ReadBytes(14); // skip bitmap file info header
    35.           byte[] bmiInfoHeader = reader.ReadBytes(4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4);
    36.  
    37.           int rgbL = (int)(stream.Length - stream.Position);
    38.           int rgb = (int)(rgbL / (captureWidth * captureHeight));
    39.  
    40.           byte[] pixelData = reader.ReadBytes((int)(stream.Length - stream.Position));
    41.  
    42.           byte[] h1pixelData = new byte[captureWidth * rgb];
    43.           byte[] h2pixelData = new byte[captureWidth * rgb];
    44.           //now flip horizontally, we do it always to prevent microstudder
    45.           int i;
    46.           for (i = 0; i < ((captureHeight / 2) - 1); i++)
    47.           {
    48.             Array.Copy(pixelData, i * captureWidth * rgb, h1pixelData, 0, captureWidth * rgb);
    49.             Array.Copy(pixelData, (captureHeight - i - 1) * captureWidth * rgb, h2pixelData, 0, captureWidth * rgb);
    50.             Array.Copy(h1pixelData, 0, pixelData, (captureHeight - i - 1) * captureWidth * rgb, captureWidth * rgb);
    51.             Array.Copy(h2pixelData, 0, pixelData, i * captureWidth * rgb, captureWidth * rgb);
    52.           }
    53.           //send scaled and fliped frame to atmowin
    54.           if (!AtmolightSettings.lowCPU ||
    55.               (((Win32API.GetTickCount() - lastFrame) > AtmolightSettings.lowCPUTime) && AtmolightSettings.lowCPU))
    56.           {
    57.             if (AtmolightSettings.lowCPU)
    58.             {
    59.               lastFrame = Win32API.GetTickCount();
    60.             }
    61.               atmoLiveViewCtrl.setPixelData(bmiInfoHeader, pixelData);
    62.           }
    63.           stream.Close();
    64.           stream.Dispose();
    65.         }
    66.         catch (Exception ex)
    67.         {
    68.           Log.Error("AtmoLight: Error in AtmolightPlugin_OnNewFrame.");
    69.           Log.Error("AtmoLight: Exception: {0}", ex.Message);
    70.  
    71.           rgbSurface.Dispose();
    72.           rgbSurface = null;
    73.         }
    74.       }
    75.     }
    That hooks into https://github.com/MediaPortal/MediaPortal-1/blob/master/mediaportal/Core/Player/FrameGrabber.cs

    I would need something similar in MP2.

    Thanks for your help :)
     
  6. Lightning303
    • Premium Supporter

    Lightning303 MP Donator

    Joined:
    September 12, 2009
    Messages:
    798
    Likes Received:
    384
    Gender:
    Male
    Ratings:
    +578 / 0
    Home Country:
    Germany Germany
    Show System Specs
  7. morpheus_xx
    • Team MediaPortal

    morpheus_xx Lead Dev MP2

    Joined:
    March 24, 2007
    Messages:
    11,090
    Likes Received:
    4,766
    Ratings:
    +6,826 / 11
    Home Country:
    Germany Germany
    Show System Specs
    If I read your code correctly, you render the surface into a bitmap. So I expect the atmolight logic is using this as input? Or would it be able to use the Surface directly?
     
  8. Lightning303
    • Premium Supporter

    Lightning303 MP Donator

    Joined:
    September 12, 2009
    Messages:
    798
    Likes Received:
    384
    Gender:
    Male
    Ratings:
    +578 / 0
    Home Country:
    Germany Germany
    Show System Specs
    Yes, this is the input for AtmoLight, on every frame the event is called, the Surface converted into a bitmap, shrunken in size and then sent to AtmoWin. Afaik Atmowin only excepts bitmap.
     
  9. Lightning303
    • Premium Supporter

    Lightning303 MP Donator

    Joined:
    September 12, 2009
    Messages:
    798
    Likes Received:
    384
    Gender:
    Male
    Ratings:
    +578 / 0
    Home Country:
    Germany Germany
    Show System Specs
    OK, after a lot of trial and error i came up with this.

    Code (C):
    1.     private SharpDX.Direct3D9.Surface rgbSurface;
    2.     private void MyThread()
    3.     {
    4.       while (ServiceRegistration.Get<IPlayerContextManager>().IsVideoContextActive)
    5.       {
    6.         try
    7.         {
    8.           rgbSurface = ServiceRegistration.Get<ISharpDXVideoPlayer>().Surface;
    9.           Rectangle rect = new Rectangle(0, 0, rgbSurface.Description.Width, rgbSurface.Description.Height);
    10.  
    11.           DataStream stream = SharpDX.Direct3D9.Surface.ToStream(rgbSurface, SharpDX.Direct3D9.ImageFileFormat.Bmp, rect);
    12.  
    13.           BinaryReader reader = new BinaryReader(stream);
    14.           stream.Position = 0; // ensure that what start at the beginning of the stream.
    15.           reader.ReadBytes(14); // skip bitmap file info header
    16.           byte[] bmiInfoHeader = reader.ReadBytes(4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4);
    17.  
    18.           int rgbL = (int)(stream.Length - stream.Position);
    19.           int rgb = (int)(rgbL / (AtmoLightObject.captureWidth * AtmoLightObject.captureHeight));
    20.  
    21.           byte[] pixelData = reader.ReadBytes((int)(stream.Length - stream.Position));
    22.  
    23.           byte[] h1pixelData = new byte[AtmoLightObject.captureWidth * rgb];
    24.           byte[] h2pixelData = new byte[AtmoLightObject.captureWidth * rgb];
    25.           //now flip horizontally, we do it always to prevent microstudder
    26.           int i;
    27.           for (i = 0; i < ((AtmoLightObject.captureHeight / 2) - 1); i++)
    28.           {
    29.             Array.Copy(pixelData, i * AtmoLightObject.captureWidth * rgb, h1pixelData, 0, AtmoLightObject.captureWidth * rgb);
    30.             Array.Copy(pixelData, (AtmoLightObject.captureHeight - i - 1) * AtmoLightObject.captureWidth * rgb, h2pixelData, 0, AtmoLightObject.captureWidth * rgb);
    31.             Array.Copy(h1pixelData, 0, pixelData, (AtmoLightObject.captureHeight - i - 1) * AtmoLightObject.captureWidth * rgb, AtmoLightObject.captureWidth * rgb);
    32.             Array.Copy(h2pixelData, 0, pixelData, i * AtmoLightObject.captureWidth * rgb, AtmoLightObject.captureWidth * rgb);
    33.           }
    34.  
    35.           AtmoLightObject.SetPixelData(bmiInfoHeader, pixelData);
    36.  
    37.           stream.Close();
    38.           stream.Dispose();
    39.  
    40.         }
    41.         catch (Exception ex)
    42.         {
    43.           Log.Error("ex: {0}", ex.Message);
    44.         }
    45.       }
    46.       System.Threading.Thread.Sleep(10);
    47.     }
    Lots of red squgily lines in vs for a long time, because directx surfaces are not the same as sharpdx surfaces blabla..., after trying to convert one to another for some time i found the ToStream method in sharpdx, which looked to be my savior. However my error seems to be even before that. Running this i get this exception:

    Code (Text):
    1. [2014-04-23 03:08:20,811] [21474  ] [112      ] [ERROR] - AtmoLight: ex: Could not find the MediaPortal.UI.SkinEngine.Players.ISharpDXVideoPlayer service
    its late, im tiered, if i make no sense or did obvious mistakes, please forgive me. Wanted to let this here as its still fresh and i still know what i actually did... ;).
    Maybe someone has an idea ;).
     
  10. morpheus_xx
    • Team MediaPortal

    morpheus_xx Lead Dev MP2

    Joined:
    March 24, 2007
    Messages:
    11,090
    Likes Received:
    4,766
    Ratings:
    +6,826 / 11
    Home Country:
    Germany Germany
    Show System Specs
    In principle you are on the right way, but you cannot access the player itself via ServiceRegistration, because MP2 handles two or even more players concurrently. You need to use the IPlayerManger service to get the active instances. Look into the StatsRenderer plugin, it also enumerates players.
     
    • Thank You! Thank You! x 1
  11. morpheus_xx
    • Team MediaPortal

    morpheus_xx Lead Dev MP2

    Joined:
    March 24, 2007
    Messages:
    11,090
    Likes Received:
    4,766
    Ratings:
    +6,826 / 11
    Home Country:
    Germany Germany
    Show System Specs
    I think the StatsRenderer approach might even work better: you could get the full screen once it is rendered from backbuffer. Then it doesnt matter if one or more videos are playing, and also if fullscreen, window or PiP is used. Check the plugin code, it directly hooks into render events.
     
    • Thank You! Thank You! x 1
Loading...

Users Viewing Thread (Users: 0, Guests: 0)

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice
  • About The Project

    The vision of the MediaPortal project is to create a free open source media centre application, which supports all advanced media centre functions, and is accessible to all Windows users.

    In reaching this goal we are working every day to make sure our software is one of the best.

             

  • Support MediaPortal!

    The team works very hard to make sure the community is running the best HTPC-software. We give away MediaPortal for free but hosting and software is not for us.

    Care to support our work with a few bucks? We'd really appreciate it!