| 438 | } |
| 439 | |
| 440 | func (r *Room) Join( |
| 441 | participant types.LocalParticipant, |
| 442 | requestSource routing.MessageSource, |
| 443 | opts *ParticipantOptions, |
| 444 | iceServers []*livekit.ICEServer, |
| 445 | ) error { |
| 446 | r.lock.Lock() |
| 447 | defer r.lock.Unlock() |
| 448 | |
| 449 | if r.IsClosed() { |
| 450 | return ErrRoomClosed |
| 451 | } |
| 452 | |
| 453 | if r.participants[participant.Identity()] != nil { |
| 454 | return ErrAlreadyJoined |
| 455 | } |
| 456 | if r.protoRoom.MaxParticipants > 0 && !participant.IsDependent() { |
| 457 | numParticipants := uint32(0) |
| 458 | for _, p := range r.participants { |
| 459 | if !p.IsDependent() { |
| 460 | numParticipants++ |
| 461 | } |
| 462 | } |
| 463 | if numParticipants >= r.protoRoom.MaxParticipants { |
| 464 | return ErrMaxParticipantsExceeded |
| 465 | } |
| 466 | } |
| 467 | |
| 468 | if r.FirstJoinedAt() == 0 && !participant.IsDependent() { |
| 469 | r.joinedAt.Store(time.Now().Unix()) |
| 470 | } |
| 471 | |
| 472 | r.launchTargetAgents(slices.Collect(maps.Values(r.agentDispatches)), participant, livekit.JobType_JT_PARTICIPANT) |
| 473 | |
| 474 | r.logger.Debugw( |
| 475 | "new participant joined", |
| 476 | "participantID", participant.ID(), |
| 477 | "participant", participant.Identity(), |
| 478 | "clientInfo", logger.Proto(participant.GetClientInfo()), |
| 479 | "options", opts, |
| 480 | "numParticipants", len(r.participants), |
| 481 | ) |
| 482 | |
| 483 | if participant.IsRecorder() && !r.protoRoom.ActiveRecording { |
| 484 | r.protoRoom.ActiveRecording = true |
| 485 | r.protoProxy.MarkDirty(true) |
| 486 | } else { |
| 487 | r.protoProxy.MarkDirty(false) |
| 488 | } |
| 489 | |
| 490 | r.participants[participant.Identity()] = participant |
| 491 | r.participantOpts[participant.Identity()] = opts |
| 492 | r.participantRequestSources[participant.Identity()] = requestSource |
| 493 | |
| 494 | if r.onParticipantChanged != nil { |
| 495 | r.onParticipantChanged(participant) |
| 496 | } |
| 497 | |