diff --git a/lib/BigBlueButton/API.php b/lib/BigBlueButton/API.php index 1a069d1..1b5645c 100644 --- a/lib/BigBlueButton/API.php +++ b/lib/BigBlueButton/API.php @@ -148,6 +148,7 @@ class API { $createMeetingParams->setRecord($room->record); $createMeetingParams->setAllowStartStopRecording($room->record); $createMeetingParams->setLogoutUrl($this->urlGenerator->getBaseUrl()); + $createMeetingParams->setMuteOnStart($room->getJoinMuted()); $mac = $this->crypto->calculateHMAC($room->uid); diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 3a72119..a5252c5 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -118,7 +118,8 @@ class RoomController extends Controller { ?string $moderatorToken, bool $listenOnly, bool $mediaCheck, - bool $cleanLayout + bool $cleanLayout, + bool $joinMuted ): DataResponse { $room = $this->service->find($id); @@ -141,8 +142,8 @@ class RoomController extends Controller { return new DataResponse(['message' => 'Access type not allowed.'], Http::STATUS_BAD_REQUEST); } - return $this->handleNotFound(function () use ($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator, $moderatorToken, $listenOnly, $mediaCheck, $cleanLayout) { - return $this->service->update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator, $moderatorToken, $listenOnly, $mediaCheck, $cleanLayout); + return $this->handleNotFound(function () use ($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator, $moderatorToken, $listenOnly, $mediaCheck, $cleanLayout, $joinMuted) { + return $this->service->update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator, $moderatorToken, $listenOnly, $mediaCheck, $cleanLayout, $joinMuted); }); } diff --git a/lib/Db/Room.php b/lib/Db/Room.php index a057f3d..318c3ef 100644 --- a/lib/Db/Room.php +++ b/lib/Db/Room.php @@ -24,6 +24,7 @@ use OCP\AppFramework\Db\Entity; * @method bool getListenOnly() * @method bool getMediaCheck() * @method bool getCleanLayout() + * @method bool getJoinMuted() * @method void setUid(string $uid) * @method void setName(string $name) * @method void setAttendeePassword(string $pw) @@ -40,6 +41,7 @@ use OCP\AppFramework\Db\Entity; * @method void setListenOnly(bool $listenOnly) * @method void setMediaCheck(bool $mediaCheck) * @method void setCleanLayout(bool $cleanLayout) + * @method void setJoinMuted(bool $joinMuted) */ class Room extends Entity implements JsonSerializable { public const ACCESS_PUBLIC = 'public'; @@ -67,6 +69,7 @@ class Room extends Entity implements JsonSerializable { public $listenOnly; public $mediaCheck; public $cleanLayout; + public $joinMuted; public function __construct() { $this->addType('maxParticipants', 'integer'); @@ -77,6 +80,7 @@ class Room extends Entity implements JsonSerializable { $this->addType('listenOnly', 'boolean'); $this->addType('mediaCheck', 'boolean'); $this->addType('cleanLayout', 'boolean'); + $this->addType('joinMuted', 'boolean'); } public function jsonSerialize(): array { @@ -97,6 +101,7 @@ class Room extends Entity implements JsonSerializable { 'listenOnly' => boolval($this->listenOnly), 'mediaCheck' => boolval($this->mediaCheck), 'cleanLayout' => boolval($this->cleanLayout), + 'joinMuted' => boolval($this->joinMuted), ]; } } diff --git a/lib/Migration/Version000000Date20210729200144.php b/lib/Migration/Version000000Date20210729200144.php new file mode 100644 index 0000000..fbe989b --- /dev/null +++ b/lib/Migration/Version000000Date20210729200144.php @@ -0,0 +1,42 @@ +hasTable('bbb_rooms')) { + $table = $schema->getTable('bbb_rooms'); + + if (!$table->hasColumn('join_muted')) { + $table->addColumn('join_muted', 'boolean', [ + 'notnull' => false, + 'default' => false + ]); + } + + return $schema; + } + + return null; + } +} diff --git a/lib/Service/RoomService.php b/lib/Service/RoomService.php index 8d46c76..d662009 100644 --- a/lib/Service/RoomService.php +++ b/lib/Service/RoomService.php @@ -88,6 +88,7 @@ class RoomService { $room->setListenOnly(true); $room->setMediaCheck(true); $room->setCleanLayout(false); + $room->setJoinMuted(false); if ($access === Room::ACCESS_PASSWORD) { $room->setPassword($this->humanReadableRandom(8)); @@ -117,7 +118,8 @@ class RoomService { ?string $moderatorToken, bool $listenOnly, bool $mediaCheck, - bool $cleanLayout) { + bool $cleanLayout, + bool $joinMuted) { try { $room = $this->mapper->find($id); @@ -139,6 +141,7 @@ class RoomService { $room->setListenOnly($listenOnly); $room->setMediaCheck($mediaCheck); $room->setCleanLayout($cleanLayout); + $room->setJoinMuted($joinMuted); return $this->mapper->update($room); } catch (Exception $e) { diff --git a/ts/Common/Api.ts b/ts/Common/Api.ts index 2360164..198f6ce 100644 --- a/ts/Common/Api.ts +++ b/ts/Common/Api.ts @@ -42,6 +42,7 @@ export interface Room { listenOnly: boolean, mediaCheck: boolean, cleanLayout: boolean, + joinMuted: boolean, } export interface RoomShare { diff --git a/ts/Manager/EditRoomDialog.tsx b/ts/Manager/EditRoomDialog.tsx index 74dc07d..ba0ff44 100644 --- a/ts/Manager/EditRoomDialog.tsx +++ b/ts/Manager/EditRoomDialog.tsx @@ -20,6 +20,7 @@ const descriptions: { [key: string]: string } = { listenOnly: t('bbb', 'If disabled, a microphone is needed to join the conference.'), mediaCheck: t('bbb', 'If enabled, the user has not to perform an echo call and webcam preview on the first join (available since BBB server 2.3).'), cleanLayout: t('bbb', 'If enabled, the user list, chat area and presentation are hidden by default.'), + joinMuted: t('bbb', 'If enabled, all users will join the meeting muted.'), }; const LOGO_QR = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGnSURBVFiF7de9TxRBHMbxzxG5BonRBOGsVRJfIvGFPwFKX0tjJGqsrfwvCC0YtbJSQyT4J0hB1BhtjZFCI4FoqTRCsbO43g24e+5Q3ZNsZm9+z8zzvZns7Rw9/a0jeIx1bNZ8rYe5WzuFt7CSILj9WsFwHtooADzA7XD/DG/CgDrUwHlcDZ/ncLfdtBoCn9cUGtN8yPiWd/QVikOhfZcQ4G1oD8cA8u2oa9ljyufe3vq+HYx7ph7Avv8YO4Rx2b4uy35oKqubFWhiBl+wiJf4imn0V52smxWYxc22vn7cwwHcqjJZ1RUYi4QXNYUzKQEm/1FvYCIlwEAJz/6UAB9KeN6nBFjAp13qH2VPRjKADdkr9Uek9h3XgicZwGk8wcFI7VConUoFMIZXOLGL5ySWVHgUywI08RSDJbyDwdusE+AGjpb0wjFcrxPgSoXwXJerAnScVgo63gXAaKSv49RVBFgL7dnIwN9dAMR0LrSreUfxbfgCd3BJdix/7Q/pBn5WDPuF++G+gQu4WMjq0Ii9+WPyWeFU3K4WHsm2o+7gNTwMX7SnbW0BScCZl0uGVe8AAAAASUVORK5CYII='; @@ -214,6 +215,17 @@ const EditRoomDialog: React.FC = ({ room, restriction, updateProperty, op

{descriptions.cleanLayout}

+
+
+ updateProperty('joinMuted', event.target.checked)} /> + +
+

{descriptions.joinMuted}

+
);