HISE Logo Forum
    • Categories
    • Register
    • Login

    Broadcasters best practices

    Scheduled Pinned Locked Moved Solved Scripting
    53 Posts 6 Posters 3.3k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • d.healeyD
      d.healey @aaronventure
      last edited by d.healey

      @aaronventure But why should the about namespace know or care if there is a thing called Header? The only thing it needs to know is should it show the pop-up. And perhaps in the future I will want other triggers to show the About pop-up that aren't in the header.

      I really like code to be as portable and self-contained as possible. It makes future extension and maintenance easier - usually.

      Libre Wave - Freedom respecting instruments and effects
      My Patreon - HISE tutorials
      YouTube Channel - Public HISE tutorials

      Christoph HartC 1 Reply Last reply Reply Quote 0
      • Christoph HartC
        Christoph Hart @d.healey
        last edited by

        @d-healey said in [Broadcasters

        I really like code to be as portable and self-contained as possible. It makes future extension and maintenance easier - usually.

        Makes sense but if you write two modules which need to listen to each other‘s broadcaster then they are not self-contained and blaming the broadcaster is just shooting the messenger - literally :)

        d.healeyD 1 Reply Last reply Reply Quote 0
        • d.healeyD
          d.healey @Christoph Hart
          last edited by d.healey

          @Christoph-Hart Sure, but let's say both namespaces are aware of a third namespace called Broadcasters. They can both check if there is an isDownload, or showAboutPopup broadcaster there and do whatever they need to do. The implementation of the broadcaster is totally independent and is therefore easily transferred to other projects or used in different contexts.

          If the Header is looking for a specific About namespace or vice versa then they are more coupled than if they are looking for a generic Broadcasters namespace.

          I think what I'm closing in on is having a dedicated Broadcaster namespace. I'll have to play with it and see if I like the workflow.

          Libre Wave - Freedom respecting instruments and effects
          My Patreon - HISE tutorials
          YouTube Channel - Public HISE tutorials

          Christoph HartC 1 Reply Last reply Reply Quote 0
          • Christoph HartC
            Christoph Hart @d.healey
            last edited by

            @d-healey said in Broadcasters best practices:

            I think what I'm closing in on is having a dedicated Broadcaster namespace. I'll have to play with it and see if I like the workflow.

            Actually that's what I've been doing, a namespace called DataGlobal which houses reference arrays, broadcasters & constants that can be picked up by other scripts. I started out with local broadcasters and then decided to refactor it midway, so what I did was keep the old variable name and just point to the broadcaster defined in the DataGlobal namespace.

            Before:

            namespace Something
            {
            const var somethingBroadcaster = Engine.createBroadcaster({});
            
            somethingBroadcaster.addListener(...);
            
            }
            

            After:

            namespace DataGlobal
            {
            const var somethingBroadcaster = Engine.createBroadcaster({});
            }
            
            namespace Something
            {
            const var somethingBroadcaster = DataGlobal.somethingBroadcaster;
            
            // This line (and everything that uses it doesn't need to change).
            somethingBroadcaster.addListener(...);
            }
            

            You could even go as far as use the globally defined broadcaster (if it exists) or create a local one if you want to modularize the codebase even further:

            namespace Something
            {
                const var someBroadcaster = isDefined(DataGlobal.someBroadcaster) ?
                                                DataGlobal.someBroadcaster : 
                                                Engine.createBroadcaster({});
            }
            
            O d.healeyD 2 Replies Last reply Reply Quote 2
            • O
              Orvillain @Christoph Hart
              last edited by

              Just to sorta blunder in and ask possibly a stupid question... namespaces are just containers for related functions and variables right? You can't actually instance a namespace IE: use it as a kind of class ?

              Christoph HartC clevername27C 2 Replies Last reply Reply Quote 0
              • Christoph HartC
                Christoph Hart @Orvillain
                last edited by

                Link Preview Image
                HISE | Docs

                favicon

                (docs.hise.dev)

                O 1 Reply Last reply Reply Quote 1
                • O
                  Orvillain @Christoph Hart
                  last edited by

                  @Christoph-Hart

                  Right I see. So an Object Factory is what I would want if I wanted to create a class.

                  Christoph HartC 1 Reply Last reply Reply Quote 0
                  • Christoph HartC
                    Christoph Hart @Orvillain
                    last edited by

                    @Orvillain not really. A object factory creates a data structure with a densely packed memory layout that can be used for a neat implementation of MIDI logic, but it lacks most of the features that you would expect from a object-oriented class object (like methods or polymorphism).

                    What are you trying to achieve?

                    O 1 Reply Last reply Reply Quote 1
                    • O
                      Orvillain @Christoph Hart
                      last edited by Orvillain

                      @Christoph-Hart said in Broadcasters best practices:

                      @Orvillain not really. A object factory creates a data structure with a densely packed memory layout that can be used for a neat implementation of MIDI logic, but it lacks most of the features that you would expect from a object-oriented class object (like methods or polymorphism).

                      What are you trying to achieve?

                      I'm mainly pondering what would be the cleanest way to create an object prototype and then instantiate however many of them I'd like - and each instance automatically creates the relevant DSP nodes, UI widgets, and various methods and callbacks required.

                      In Python you'd do something like:

                      class WhateverTheClassIsCalled(inheritance here)
                      
                      def __init__(self, and then any initialisation arguments here)
                          self.blah = blah
                      
                      def do_a_thing(self, blahblahblah)
                         thing_is_done = blahblahblah(bloo bloo bloo)
                          return thing_is_done
                      
                      
                      for i in range(0, 32):
                         instance_var = WhateverTheClassIsCalled(blahblahblah, bloloooooloooo)
                      

                      That sort of thing. In Python it is fairly trivial to put together a class this way, and tbh, syntax aside it looks like the Factory Object approach might do the same sort of thing???

                      BTW - the above is probably the best code I've ever written. :face_with_tears_of_joy:

                      1 Reply Last reply Reply Quote 0
                      • clevername27C
                        clevername27 @Orvillain
                        last edited by

                        @Orvillain One cool thing about namespaces is that each comes with 32 high-speed reg variables.

                        Christoph HartC 1 Reply Last reply Reply Quote 1
                        • Christoph HartC
                          Christoph Hart @clevername27
                          last edited by Christoph Hart

                          You can do this kind of simple object oriented stuff by creating a JSON object and attaching functions as member, which will then access the JSON properties through the this.property syntax:

                          // This as close as you'll get to object oriented programming in HISE Script
                          function createInstance(valueToUse)
                          {
                              var prototype = {
                                  create: function()
                                  {
                                      // Access properties of the "class" object with this
                                      Console.print(this.value);
                                  },
                                  value: valueToUse // store the "constructor argument" as "class member"
                              };
                              
                              return prototype;
                          }
                          
                          // And now let's add polymorphism:
                          function createSubClassInstance(valueToUse)
                          {
                              var prototype = createInstance(valueToUse);
                              prototype.create = function()
                              {
                                  Console.print(this.value + ": SUBCLASS");
                              };
                              
                              return prototype;
                          }
                          
                          // Create two instances of the "class"
                          var x1 = createInstance(90);
                          var x2 = createInstance(120);
                          
                          var x3 = createSubClassInstance(500);
                          
                          // call the method of each instance
                          x1.create();
                          x2.create();
                          x3.create();
                          
                          O 2 Replies Last reply Reply Quote 1
                          • O
                            Orvillain @Christoph Hart
                            last edited by

                            @Christoph-Hart said in Broadcasters best practices:

                            You can do this kind of simple object oriented stuff by creating a JSON object and attaching functions as member, which will then access the JSON properties through the this.property syntax:

                            // This as close as you'll get to object oriented programming in HISE Script
                            function createInstance(valueToUse)
                            {
                                var prototype = {
                                    create: function()
                                    {
                                        // Access properties of the "class" object with this
                                        Console.print(this.value);
                                    },
                                    value: valueToUse // store the "constructor argument" as "class member"
                                };
                                
                                return prototype;
                            }
                            
                            // And now let's add polymorphism:
                            function createSubClassInstance(valueToUse)
                            {
                                var prototype = createInstance(valueToUse);
                                prototype.create = function()
                                {
                                    Console.print(this.value + ": SUBCLASS");
                                };
                                
                                return prototype;
                            }
                            
                            // Create two instances of the "class"
                            var x1 = createInstance(90);
                            var x2 = createInstance(120);
                            
                            var x3 = createSubClassInstance(500);
                            
                            // call the method of each instance
                            x1.create();
                            x2.create();
                            x3.create();
                            

                            Ahhhhhh, yes I think I get that. I will give it a try! Thank you!

                            1 Reply Last reply Reply Quote 0
                            • d.healeyD
                              d.healey @Christoph Hart
                              last edited by

                              @Christoph-Hart Nice, that's the kind of thing I was thinking of

                              Libre Wave - Freedom respecting instruments and effects
                              My Patreon - HISE tutorials
                              YouTube Channel - Public HISE tutorials

                              1 Reply Last reply Reply Quote 0
                              • d.healeyD d.healey has marked this topic as solved on
                              • d.healeyD
                                d.healey
                                last edited by d.healey

                                I just tried using the broadcaster wizard for the first time. I selected ComponentVisibility in the second screen, this is what it gave me

                                const var showAboutBroadcaster = Engine.createBroadcaster({
                                  "id": "showAboutBroadcaster",
                                  "args": ["component", "isVisible"],
                                  "tags": []
                                });
                                
                                // attach to event Type
                                showAboutBroadcaster.attachToComponentProperties(["pnlAboutContainer"], "Temp");
                                
                                // attach first listener
                                showAboutBroadcaster.addComponentPropertyListener(["pnlAboutContainer"], ["visible"], "temp", function(index, component, isVisible){
                                	return isVisible;
                                });
                                

                                This gives an error argument amount mismatch: 2, Expected: 3

                                I changed it to attachToComponentVisibility and the issue is resolved.

                                Libre Wave - Freedom respecting instruments and effects
                                My Patreon - HISE tutorials
                                YouTube Channel - Public HISE tutorials

                                d.healeyD 1 Reply Last reply Reply Quote 0
                                • O
                                  Orvillain @Christoph Hart
                                  last edited by Orvillain

                                  @Christoph-Hart said in Broadcasters best practices:

                                  You can do this kind of simple object oriented stuff by creating a JSON object and attaching functions as member, which will then access the JSON properties through the this.property syntax:

                                  // This as close as you'll get to object oriented programming in HISE Script
                                  function createInstance(valueToUse)
                                  {
                                      var prototype = {
                                          create: function()
                                          {
                                              // Access properties of the "class" object with this
                                              Console.print(this.value);
                                          },
                                          value: valueToUse // store the "constructor argument" as "class member"
                                      };
                                      
                                      return prototype;
                                  }
                                  
                                  // And now let's add polymorphism:
                                  function createSubClassInstance(valueToUse)
                                  {
                                      var prototype = createInstance(valueToUse);
                                      prototype.create = function()
                                      {
                                          Console.print(this.value + ": SUBCLASS");
                                      };
                                      
                                      return prototype;
                                  }
                                  
                                  // Create two instances of the "class"
                                  var x1 = createInstance(90);
                                  var x2 = createInstance(120);
                                  
                                  var x3 = createSubClassInstance(500);
                                  
                                  // call the method of each instance
                                  x1.create();
                                  x2.create();
                                  x3.create();
                                  

                                  So just looking at this. I think I get it, and I can see how this would help me. For example here is what I have so far:

                                  function Sampler(id)
                                  {
                                  	var sampler = {
                                  		connectComponents: function()
                                  		{
                                  			this.pad = Content.getComponent("panel_" + this.id);
                                  			this.sampler = Synth.getChildSynth("sampler_" + this.id);
                                  			this.processor = Synth.getAudioSampleProcessor("sampler_" + this.id);
                                  			this.sequencer = undefined;
                                  			
                                  			
                                  		},
                                  		
                                  		populateLayers: function()
                                  		{
                                  			for (i = 0; i < layer_count; i++)
                                  			{
                                  				this.layers[i] = {
                                  					'audiofile': this.processor.getAudioFile(i),
                                  					'ui_parameters': {},
                                  					'loop_panel': Content.getComponent("loopdragger_" + this.id),
                                  					'waveform_panel': Content.getComponent("waveform_" + this.id),
                                  
                                  
                                  				};
                                  			}
                                  		},
                                  		
                                  		connectCallbacks: function()
                                  		{
                                  			this.pad.setFileDropCallback("Drop Only", "*.wav", load_sample);
                                  		},
                                  		id: id,
                                  		layers: {},
                                  	};
                                  	
                                  	
                                  	return sampler;
                                  }
                                  

                                  It'll get more interesting when I actually write a function to check if a component exists, and if it doesn't, create it.

                                  1 Reply Last reply Reply Quote 0
                                  • d.healeyD
                                    d.healey @d.healey
                                    last edited by

                                    @d-healey said in Broadcasters best practices:

                                    I just tried using the broadcaster wizard for the first time. I selected ComponentVisibility in the second screen, this is what it gave me

                                    const var showAboutBroadcaster = Engine.createBroadcaster({
                                      "id": "showAboutBroadcaster",
                                      "args": ["component", "isVisible"],
                                      "tags": []
                                    });
                                    
                                    // attach to event Type
                                    showAboutBroadcaster.attachToComponentProperties(["pnlAboutContainer"], "Temp");
                                    
                                    // attach first listener
                                    showAboutBroadcaster.addComponentPropertyListener(["pnlAboutContainer"], ["visible"], "temp", function(index, component, isVisible){
                                    	return isVisible;
                                    });
                                    

                                    This gives an error argument amount mismatch: 2, Expected: 3

                                    I changed it to attachToComponentVisibility and the issue is resolved.

                                    Any ideas about this one Christoph? Is it a bug or did I use the wrong settings in the wizard?

                                    Libre Wave - Freedom respecting instruments and effects
                                    My Patreon - HISE tutorials
                                    YouTube Channel - Public HISE tutorials

                                    A 1 Reply Last reply Reply Quote 0
                                    • A
                                      aaronventure @d.healey
                                      last edited by

                                      @d-healey your function prototype is correct, now just make the arguments for the broadcaster match, i. e. add index to the args

                                      d.healeyD 1 Reply Last reply Reply Quote 0
                                      • d.healeyD
                                        d.healey @aaronventure
                                        last edited by

                                        @aaronventure This is auto-generated by the broadcaster wizard - and it doesn't work, therefore I think it's a bug. It should be using attachToComponentVisibility, but it isn't.

                                        Libre Wave - Freedom respecting instruments and effects
                                        My Patreon - HISE tutorials
                                        YouTube Channel - Public HISE tutorials

                                        A 1 Reply Last reply Reply Quote 0
                                        • A
                                          aaronventure @d.healey
                                          last edited by

                                          @d-healey ah gotcha

                                          1 Reply Last reply Reply Quote 0
                                          • d.healeyD d.healey referenced this topic on
                                          • d.healeyD
                                            d.healey
                                            last edited by d.healey

                                            This is confusing

                                            00155799-f272-4d29-a9c4-a6c465dabe08-image.png

                                            I had no idea what was wanted here, but it's a string (must have quotes)

                                            I tried to add multiple events to the EQ broadcaster and the output was "BandAdded, BandRemoved, BandSelected" which doesn't work. It should be ["BandAdded", "BandRemoved", "BandSelected"]

                                            Libre Wave - Freedom respecting instruments and effects
                                            My Patreon - HISE tutorials
                                            YouTube Channel - Public HISE tutorials

                                            Christoph HartC 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            35

                                            Online

                                            1.7k

                                            Users

                                            11.7k

                                            Topics

                                            102.2k

                                            Posts