Any Plugin Experts Out There?

Jaxel

Member
I want to start writing OBS plugins. But I don't know where to get started.

Is anyone out there willing to help me walk through some stuff?
 

dodgepong

Administrator
Community Helper
First, a caveat: OBS Multiplatform is still early in development, but eventually it will overtake the current version of OBS in terms of features and functionality, and the original will be deprecated. I'm not sure when that point will be, but keep that in mind when choosing which version to develop plugins for.

A good way to start is to check out the source code and try to get OBS building. Feel free to join #obs-dev on Quakenet if you need help.

The API for original OBS (OBS1) is not documented at all, unfortunately. To learn the API, you'll basically have to read the source code. You may also consider using the CLR Host Plugin to develop plugins in C#/VB.NET instead of C++. Many plugins are open source, so you can check out the source to see how they work.

The API for OBS-Studio is much better documented and easier to use. Most of the core elements to OBS-Studio are actually plugins, as you can see in the plugins folder. It should be a lot easier to get an idea of how the OBS-Studio API works. Again, checking out the code from git and getting it to build is a good first step.
 

Jaxel

Member
Here is the documentation from the CLR Host plugin author: http://catchexception.org/docs/creating-a-plugin/

And the CLR Host plugin itself: https://obsproject.com/forum/resources/clr-host-plugin.21/

One thing nice about developing using the CLR Host is that the CLR Host API actually does include some documentation, as opposed to the raw OBS API, which does not.
The problem is I don't need help with C#; C# I got... what I need help on is the ABSOLUTE basics of VS.

There is so much that documentation doesn't explain.
 

dodgepong

Administrator
Community Helper
I suppose if you're going to make a plugin using the CLR Host, you can skip the step where you build OBS yourself, so you don't need to use Visual Studio for that. What have you done your C# development with in the past? I assumed you were familiar with Visual Studio, since Visual Studio is the tool of choice for virtually all C# development.
 

Jaxel

Member
I dont really do any C# development... Scoreboard Assistant is it (which I use VS2013e). I come from the areas of procedural programming, and scripting languages. I am a web developer. Things like "MVVC", and "Compiling" are weird to me. My main languages are PHP, Perl, JS and HTML.

Following the CLR documentation, it tells you how to basically hook into CLR Host. But it doesn't tell you much more than that. For instance, how do I tell it WHAT to display on OBS? How do I set up a configuration page? What methodology does it use to save variables? There are a lot of unanswered questions.
 

Jaxel

Member
Okay... I've got it mostly working so far... Have a plugin, have the config screen, have it rendering the proper size... I just don't know how to set it to render my animated UserControl on the display screen. Again, lack of documentation that pretty much explains anything. This is my code:

Code:
using CLROBS;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SbaEvent
{
    class SbaEventSource : AbstractImageSource
    {
        private Object textureLock = new Object();
        private Texture texture = null;
        private XElement config;

        public SbaEventSource(XElement config)
        {
            this.config = config;
            UpdateSettings();
        }

        override public void UpdateSettings()
        {
            uint width = (uint)config.GetInt("width", 640);
            uint height = (uint)config.GetInt("height", 480);

            Size.X = width;
            Size.Y = height;

            config.Parent.SetInt("cx", (int)width);
            config.Parent.SetInt("cy", (int)height);

            lock (textureLock)
            {
                if (texture != null)
                {
                    texture.Dispose();
                    texture = null;
                }

                texture = GS.CreateTexture(width, height, GSColorFormat.GS_BGRA, null, false, false);
            }
        }

        override public void Render(float x, float y, float width, float height)
        {
            lock (textureLock)
            {
                if (texture != null)
                {
                    GS.DrawSprite(texture, 0xFFFFFFFF, x, y, x + width, y + height);
                }
            }
        }

        public void Dispose()
        {
            lock (textureLock)
            {
                if (texture != null)
                {
                    texture.Dispose();
                    texture = null;
                }
            }
        }
    }
}
 

dodgepong

Administrator
Community Helper
I understand it's frustrating not having sufficient documentation, requiring a lot of learning on your own. Not having documentation makes it harder for developers to get involved, which means less engagement, which is not what we want to happen, and better documentation is a goal of OBS2 for that reason.

You might try coming by #obs-dev to get some more help from people who develop for OBS.
 

Faruton

Developer
I'm not sure you are reading the code right

It converts to image every tine obs requests it which is up to 60 times a second making it animated
 

Jaxel

Member
I'm not sure you are reading the code right

It converts to image every tine obs requests it which is up to 60 times a second making it animated
See I can't get ANY animation to work... at all. This is my code:
Code:
using CLROBS;
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace SbaEvent
{
    class SbaEventSource : AbstractImageSource, IDisposable
    {
        private Object textureLock = new Object();
        private Texture texture = null;
        private XElement config;

        private SbaEventControl eventControl;

        public SbaEventSource(XElement config)
        {
            this.config = config;
            UpdateSettings();
        }

        override public void UpdateSettings()
        {
            UInt32 width = (UInt32)config.GetInt("width", 1280);
            UInt32 height = (UInt32)config.GetInt("height", 40);

            if (eventControl == null)
            {
                eventControl = new SbaEventControl(this.config);
                eventControl.Arrange(new Rect(new Size(width, height)));
            }

            lock (textureLock)
            {
                if (texture != null)
                {
                    texture.Dispose();
                    texture = null;
                }

                Size.X = width;
                Size.Y = height;

                texture = GS.CreateTexture(width, height, GSColorFormat.GS_BGRA, null, false, false);
            }
        }

        private delegate void TickFunctionDelegate();
        private void renderBitmap()
        {
            lock (textureLock)
            {
                if (texture != null)
                {
                    int width = config.GetInt("width", 1280);
                    int height = config.GetInt("height", 40);

                    RenderTargetBitmap bitmap = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
                    bitmap.Render(eventControl);
                    WriteableBitmap wBitmap = new WriteableBitmap(bitmap);

                    texture.SetImage(wBitmap.BackBuffer, GSImageFormat.GS_IMAGEFORMAT_BGRA, (UInt32)(wBitmap.PixelWidth * 4));
                }
            }
        }
        public override void Tick(float fSeconds)
        {
            Application.Current.Dispatcher.Invoke(new TickFunctionDelegate(renderBitmap));
        }

        override public void Render(float x, float y, float width, float height)
        {
            lock (textureLock)
            {
                if (texture != null)
                {
                    GS.DrawSprite(texture, 0xFFFFFFFF, x, y, x + width, y + height);
                }
            }
        }

        public void Dispose()
        {
            lock (textureLock)
            {
                if (texture != null)
                {
                    texture.Dispose();
                    texture = null;
                }
            }
        }
    }
}
Code:
using CLROBS;
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Xml;

namespace SbaEvent
{
    /// <summary>
    /// Interaction logic for SbaEventControl.xaml
    /// </summary>
    public partial class SbaEventControl : UserControl
    {
        private CircleEase easeIn = new CircleEase();
        private CircleEase easeOut = new CircleEase();
        private TimeSpan speedIn = TimeSpan.FromSeconds(1);
        private TimeSpan speedOut = TimeSpan.FromSeconds(1);

        private XElement config;

        public SbaEventControl(XElement config)
        {
            InitializeComponent();
            this.config = config;

            easeIn.EasingMode = EasingMode.EaseOut;
            easeOut.EasingMode = EasingMode.EaseOut;

            imageEE.Source = new ImageSourceConverter().ConvertFromString(config.GetString("imgFile")) as System.Windows.Media.ImageSource;

            ThicknessAnimation animateIn = new ThicknessAnimation(new Thickness(0, 0, 0, -40), speedIn);
            animateIn.EasingFunction = easeIn;
            canvasEE.BeginAnimation(Canvas.MarginProperty, animateIn);
        }
    }
}
The user control does render. It shows the image, as well as other stuff within the control. However, it never shows any animation... and when I close OBS, it now crashes.
 

Jaxel

Member
Okay... I got the animations working. Don't know what I did; but its magically working now.

I have 2 issues.
  1. My config screen has options for width/height of the element. When I add the element however, it doesn't create the element with the width/height I specified. It creates it 100x100 and I have to click "Reset Size (ctrl+r)" to fix it. Its a minor annoyance.
  2. When I close OBS, or click "Stop Preview"; OBS crashes.
 

Jaxel

Member
New interesting issue...

Sometimes when I first click "Preview Stream", the element doesn't work. However, the moment I double click the element in the sources list and open the config window... it magically starts working.

I then have to click "Cancel" on the config window to continue. As if I click "OK", the issue with #2 posted above occurs and OBS crashes.
 

Faruton

Developer
Can I see the crash log? Otherwise I can't really diagnose that problem.

Is there a repository you have all this? I can probably take a lo
 

Jaxel

Member
I dont have a repository... but I've attached it in a zip file. The zip file also includes an image and an XML file; which is required to setup the plugin.

Issues:
  1. Plugin doesn't seem to dispose properly. If I change scenes or close OBS, it crashes. If I edit the plugin config and click OK, it crashes as well.
  2. If I load up OBS, with an existing plugin element, it doesn't properly load the plugin. I have to bring up the plugin config window before it starts loading.
  3. When first setting up the plugin, it doesn't size correctly and forces me to hit Ctrl+R to get it to the correct size.

Also, the crash log is completely unhelpful.

Code:
OBS has encountered an unhandled exception and has terminated. If you are able to
reproduce this crash, please submit this crash report on the forums at
http://www.obsproject.com/ - include the contents of this crash log and the
minidump .dmp file (if available) as well as your regular OBS log files and
a description of what you were doing at the time of the crash.

This crash appears to have occured in the 'c:\windows\syswow64\kernelbase.dll' module.

**** UNHANDLED EXCEPTION: 80000003
Fault address: 77083226 (c:\windows\syswow64\kernelbase.dll)
OBS version: Open Broadcaster Software v0.637b
Windows version: 6.1 (Build 7601) Service Pack 1
CPU: Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz

Crashing thread stack trace:
Stack    EIP      Arg0     Arg1     Arg2     Arg3     Address
0018F048 77083226 0000089C 00007532 763B78E2 002C0800 kernelbase.dll!0x77083226
0018F058 012D84FA 00000001 00000001 763B78E2 002C0800 obs.exe!OBS::Stop+0x19a
0018F0A0 012D199E 682C4C40 0018F9A4 012C9DAC 00000001 obs.exe!OBS::~OBS+0x2e
0018F4D0 012D190B 00000001 00000000 00000001 00000000 obs.exe!OBS::`vector deleting destructor'+0xb
0018F4DC 012C9DAC 01280000 00000000 002E3165 00000001 obs.exe!WinMain+0x9bc
0018F9AC 0131AB2A FFFDE000 0018FA3C 776F9F72 FFFDE000 obs.exe!__tmainCRTStartup+0xfd
0018F9F8 76A3338A FFFDE000 7712CC95 00000000 00000000 kernel32.dll!0x76a3338a
0018FA04 776F9F72 0131AA23 FFFDE000 00000000 00000000 ntdll.dll!0x776f9f72
0018FA44 776F9F45 0131AA23 FFFDE000 00000000 00000000 ntdll.dll!0x776f9f45

Video thread stack trace:
Stack    EIP      Arg0     Arg1     Arg2     Arg3     Address
1A5EECE4 776E015D 1A5EED34 1A5EEDA8 00000001 FFFFFFFF ntdll.dll!0x776e015d
1A5EED88 76A319F8 00000001 FFFDE000 00000001 FFFFFFFF kernel32.dll!0x76a319f8
1A5EEDD0 67ABCABF 00000001 FFFFFFFF 00000001 0B8902A8 clr.dll!0x67abcabf
1A5EEE20 67ABC81B 00000001 1A5EEFE0 00000001 FFFFFFFF clr.dll!0x67abc81b
1A5EEEAC 67ABC90C 00000001 1A5EEFE0 00000001 FFFFFFFF clr.dll!0x67abc90c
1A5EEF18 67AC0282 00000000 00000000 65B0B67F 04AB83A8 clr.dll!0x67ac0282
1A5EF008 66B36DD2 00000000 FFFFFFFF FFFFFFFF 04D26F38 mscorlib.ni.dll!0x66b36dd2
1A5EF020 66B4E3A0 FFFFD8F0 FFFFFFFF 00000000 00000000 mscorlib.ni.dll!0x66b4e3a0
1A5EF040 65B6294F BFF00000 04D2700C 04A82578 04AB8324 windowsbase.ni.dll!0x65b6294f
1A5EF074 65BD44CF FFFFD8F0 FFFFFFFF 00000000 FFFFD8F0 windowsbase.ni.dll!0x65bd44cf
1A5EF08C 65953AF5 FFFFD8F0 FFFFFFFF 00000000 00000000 windowsbase.ni.dll!0x65953af5
1A5EF0D8 6595AB8D FFFFFFFF 04D26F28 04D26F08 FFFFD8F0 windowsbase.ni.dll!0x6595ab8d
1A5EF124 65B0A14B 3D888888 073AFAD0 1A5EF1D8 67963315 windowsbase.ni.dll!0x65b0a14b
1A5EF17C 67953DE2 1A5EF3E0 1A5EF1C8 67AA2C66 1A5EF49C clr.dll!0x67953de2
1A5EF18C 67963315 0B891E80 00000001 073AFAD0 00000000 clr.dll!0x67963315
1A5EF1E0 679CB84C 0000A2D8 04D26ED4 66BFFE8C 0000001D clr.dll!0x679cb84c
1A5EF220 679CB714 00000000 04BF2050 04B53600 00000001 clr.dll!0x679cb714
1A5EF530 66B29B5D 04D26EF4 04D26ED4 00000000 04D26EF4 mscorlib.ni.dll!0x66b29b5d
1A5EF554 66BCE52D 00000000 04D26ED4 00000000 00000000 mscorlib.ni.dll!0x66bce52d
1A5EF580 66BCE4B4 04D26ED4 66C125EC 00000001 0100000C mscorlib.ni.dll!0x66bce4b4
1A5EF598 671BA40C 00000000 0000000D 00000000 0430FECC mscorlib.ni.dll!0x671ba40c
1A5EF5FC 6795421E 671BA384 66BCE4A0 1A5EF8F4 00000005 clr.dll!0x6795421e
1A5EF630 67ACE670 00F0E520 1A5EF8B0 0B8914E8 00F0E520 clr.dll!0x67ace670
1A5EF6A8 67ACE8B5 00F0E520 1A5EF8B0 FFFFFFFF 1A5EF8E4 clr.dll!0x67ace8b5
1A5EF878 67ACE4C1 002B8400 1BA91210 00000000 1A5EF948 clr.dll!0x67ace4c1
1A5EF8D4 680C653D 00F0E528 0000000D 00000000 0430FECC clrhostplugin.dll!0x680c653d
1A5EF8F4 680C653D 3D888888 01CFEF01 0000000D 00000000 clrhostplugin.dll!0x680c653d
1A5EF928 682C97C9 1A5EF964 682B5870 3D888888 002C0800 obsapi.dll!OSGetTimeMicroseconds+0xe9
1A5EF950 680C1A20 3D888888 002C0800 00000000 1A5EFCBC clrhostplugin.dll!0x680c1a20
1A5EF958 682B5870 3D888888 00000000 00000000 00000001 obsapi.dll!Scene::Tick+0x30
1A5EF96C 012DD512 76A3338A 00000000 1A5EFD0C 776F9F72 obs.exe!OBS::MainCaptureLoop+0xb52
1A5EFCC4 012DB285 00000000 1A5EFD0C 776F9F72 00000000 obs.exe!OBS::MainCaptureThread+0x5
1A5EFCC8 76A3338A 00000000 6D54CBA5 00000000 00000000 kernel32.dll!0x76a3338a
1A5EFCD4 776F9F72 012DB280 00000000 00000000 00000000 ntdll.dll!0x776f9f72
1A5EFD14 776F9F45 012DB280 00000000 00000000 00000000 ntdll.dll!0x776f9f45

A minidump was saved to C:\Users\Jaxel\AppData\Roaming\OBS\crashDumps\OBSCrashDump2014-10-23_17.dmp.
Please include this file when posting a crash report.

List of loaded modules:
Base Address      Module
 

Attachments

  • SbaEvent.zip
    22.6 KB · Views: 40
Top