├── services.php ├── .gitignore ├── composer.json ├── src ├── Controller │ └── HelloWorld.php ├── EventHandler │ └── AllTheListeners.php └── Command │ └── ListStations.php ├── templates └── hello_world.phtml ├── events.php ├── README.md └── LICENSE /services.php: -------------------------------------------------------------------------------- 1 | getView() 17 | ->renderToResponse($response, 'example::hello_world'); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /templates/hello_world.phtml: -------------------------------------------------------------------------------- 1 | layout('minimal', ['title' => __('Hello World!'), 'page_class' => 'example-content']) ?> 2 | 3 |
4 |
5 |
6 |
7 |

Hello World!

8 |
9 | 10 |
11 | This is an example page. 12 |
13 | 14 | 18 |
19 |
20 |
21 | -------------------------------------------------------------------------------- /events.php: -------------------------------------------------------------------------------- 1 | addListener( 10 | Event\BuildConsoleCommands::class, 11 | function (Event\BuildConsoleCommands $event) use ($dispatcher) { 12 | $event->addAliases([ 13 | 'example:list-stations' => Plugin\ExamplePlugin\Command\ListStations::class, 14 | ]); 15 | } 16 | ); 17 | 18 | // Tell the view handler to look for templates in this directory too 19 | $dispatcher->addListener(Event\BuildView::class, function(Event\BuildView $event) { 20 | $event->getView()->addFolder('example', __DIR__.'/templates'); 21 | }); 22 | 23 | // Add a new route handled exclusively by the plugin. 24 | $dispatcher->addListener(Event\BuildRoutes::class, function(Event\BuildRoutes $event) { 25 | $app = $event->getApp(); 26 | 27 | $app->get('/example', \Plugin\ExamplePlugin\Controller\HelloWorld::class) 28 | ->setName('example-plugin:index:index') 29 | ->add(\App\Middleware\EnableView::class); 30 | }); 31 | 32 | // You can also add classes that implement the EventSubscriberInterface 33 | $dispatcher->addSubscriber(new \Plugin\ExamplePlugin\EventHandler\AllTheListeners); 34 | }; 35 | -------------------------------------------------------------------------------- /src/EventHandler/AllTheListeners.php: -------------------------------------------------------------------------------- 1 | 'methodName') 26 | * * array('eventName' => array('methodName', $priority)) 27 | * * array('eventName' => array(array('methodName1', $priority), array('methodName2'))) 28 | * 29 | * @return array The event names to listen to 30 | */ 31 | public static function getSubscribedEvents() 32 | { 33 | return [ 34 | Event\Radio\GenerateRawNowPlaying::class => [ 35 | ['setListenerCount', -20] 36 | ], 37 | ]; 38 | } 39 | 40 | public function setListenerCount(Event\Radio\GenerateRawNowPlaying $event) 41 | { 42 | $np_raw = $event->getResult()->toArray(); 43 | 44 | $np_raw['listeners']['current'] = mt_rand(5, 25); 45 | $np_raw['listeners']['unique'] = mt_rand(0, $np_raw['listeners']['current']); 46 | $np_raw['listeners']['total'] = $np_raw['listeners']['current']; 47 | 48 | $event->setResult(Result::fromArray($np_raw)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Command/ListStations.php: -------------------------------------------------------------------------------- 1 | title('Example Plugin: Stations'); 34 | 35 | $headers = [ 36 | 'ID', 37 | 'Name', 38 | 'Frontend', 39 | 'Backend', 40 | 'Remotes', 41 | ]; 42 | 43 | $rows = []; 44 | 45 | $stations = $this->em->getRepository(Station::class)->findAll(); 46 | 47 | /** @var Station $station */ 48 | foreach($stations as $station) { 49 | $backend = $this->adapters->getBackendAdapter($station); 50 | $frontend = $this->adapters->getFrontendAdapter($station); 51 | 52 | $rows[] = [ 53 | $station->getId(), 54 | $station->getName(), 55 | $station->getBackendType() 56 | ->getName() . ' (' . ($backend->isRunning($station) ? 'Running' : 'Stopped') . ')', 57 | $station->getFrontendType() 58 | ->getName() . ' (' . ($frontend->isRunning($station) ? 'Running' : 'Stopped') . ')', 59 | $station->getRemotes()->count(), 60 | ]; 61 | } 62 | 63 | $io->table($headers, $rows); 64 | 65 | return 0; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Extending AzuraCast with Plugins 2 | 3 | This repository contains documentation for the AzuraCast plugin system, as well as a working example of some of the more 4 | common modifications that might be made to the AzuraCast system via plugins. 5 | 6 | More information on plugins is available via 7 | the [AzuraCast Documentation](https://www.azuracast.com/docs/developers/plugins/). 8 | 9 | ## Including Plugins 10 | 11 | Plugins are automatically discovered if they're located in the `/plugins` directory relative to the main AzuraCast 12 | installation. Plugins are ignored by the parent AzuraCast instance, so you can update your instance any time you like 13 | without worrying about your plugins being removed. 14 | 15 | ### Docker Installations 16 | 17 | You can clone the plugin directory anywhere you want on the host machine, though it's recommended to have it as a 18 | subdirectory of your AzuraCast install directory (like `/var/azuracast`). To mount the plugin as a volume so Docker 19 | recognizes it, you should create a new file named `docker-compose.override.yml` alongside the 20 | existing `docker-compose.yml` file. If you already have such a file, you can update it to include the extra lines. 21 | 22 | ```yaml 23 | services: 24 | web: 25 | environment: 26 | AZURACAST_PLUGIN_MODE: true 27 | volumes: 28 | - ./path_to_plugin:/var/azuracast/www/plugins/example-plugin 29 | ``` 30 | 31 | Make sure to restart the Docker containers afterward (using `./docker.sh restart`). 32 | 33 | ## Naming Convention 34 | 35 | ### Autoloaded Files 36 | 37 | The following files are automatically loaded along with the relevant section of code: 38 | 39 | - `/services.php`: Register or extend services with the application's Dependency Injection (DI) container. 40 | - `/events.php`: Register listeners for the Event Dispatcher. 41 | 42 | ### Classes 43 | 44 | AzuraCast autoloads PHP files inside `/plugins/(plugin_name)/src` as long as they are in the appropriate namespace. 45 | 46 | The function used to convert from the plugin folder name into the PHP class name is: 47 | 48 | ```php 49 |