mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Temp
This commit is contained in:
commit
1a07e3f206
@ -3,7 +3,7 @@
|
||||
@implementation Serialization
|
||||
|
||||
- (NSUInteger)currentLayer {
|
||||
return 124;
|
||||
return 125;
|
||||
}
|
||||
|
||||
- (id _Nullable)parseMessage:(NSData * _Nullable)data {
|
||||
|
@ -98,16 +98,11 @@ class BuildEnvironment:
|
||||
self,
|
||||
base_path,
|
||||
bazel_path,
|
||||
bazel_x86_64_path,
|
||||
override_bazel_version,
|
||||
override_xcode_version
|
||||
):
|
||||
self.base_path = os.path.expanduser(base_path)
|
||||
self.bazel_path = os.path.expanduser(bazel_path)
|
||||
if bazel_x86_64_path is not None:
|
||||
self.bazel_x86_64_path = os.path.expanduser(bazel_x86_64_path)
|
||||
else:
|
||||
self.bazel_x86_64_path = None
|
||||
|
||||
configuration_path = os.path.join(self.base_path, 'versions.json')
|
||||
with open(configuration_path) as file:
|
||||
|
@ -12,11 +12,10 @@ from ProjectGeneration import generate
|
||||
|
||||
|
||||
class BazelCommandLine:
|
||||
def __init__(self, bazel_path, bazel_x86_64_path, override_bazel_version, override_xcode_version, bazel_user_root):
|
||||
def __init__(self, bazel_path, override_bazel_version, override_xcode_version, bazel_user_root):
|
||||
self.build_environment = BuildEnvironment(
|
||||
base_path=os.getcwd(),
|
||||
bazel_path=bazel_path,
|
||||
bazel_x86_64_path=bazel_x86_64_path,
|
||||
override_bazel_version=override_bazel_version,
|
||||
override_xcode_version=override_xcode_version
|
||||
)
|
||||
@ -298,7 +297,6 @@ class BazelCommandLine:
|
||||
def clean(arguments):
|
||||
bazel_command_line = BazelCommandLine(
|
||||
bazel_path=arguments.bazel,
|
||||
bazel_x86_64_path=None,
|
||||
override_bazel_version=arguments.overrideBazelVersion,
|
||||
override_xcode_version=arguments.overrideXcodeVersion,
|
||||
bazel_user_root=arguments.bazelUserRoot
|
||||
@ -337,14 +335,9 @@ def resolve_configuration(bazel_command_line: BazelCommandLine, arguments):
|
||||
raise Exception('Neither configurationPath nor configurationGenerator are set')
|
||||
|
||||
|
||||
def generate_project(arguments):
|
||||
bazel_x86_64_path = None
|
||||
if is_apple_silicon():
|
||||
bazel_x86_64_path = arguments.bazel_x86_64
|
||||
|
||||
def generate_project(arguments):
|
||||
bazel_command_line = BazelCommandLine(
|
||||
bazel_path=arguments.bazel,
|
||||
bazel_x86_64_path=bazel_x86_64_path,
|
||||
override_bazel_version=arguments.overrideBazelVersion,
|
||||
override_xcode_version=arguments.overrideXcodeVersion,
|
||||
bazel_user_root=arguments.bazelUserRoot
|
||||
@ -379,7 +372,6 @@ def generate_project(arguments):
|
||||
def build(arguments):
|
||||
bazel_command_line = BazelCommandLine(
|
||||
bazel_path=arguments.bazel,
|
||||
bazel_x86_64_path=None,
|
||||
override_bazel_version=arguments.overrideBazelVersion,
|
||||
override_xcode_version=arguments.overrideXcodeVersion,
|
||||
bazel_user_root=arguments.bazelUserRoot
|
||||
@ -491,13 +483,6 @@ if __name__ == '__main__':
|
||||
)
|
||||
|
||||
generateProjectParser = subparsers.add_parser('generateProject', help='Generate Xcode project')
|
||||
if is_apple_silicon():
|
||||
generateProjectParser.add_argument(
|
||||
'--bazel_x86_64',
|
||||
required=True,
|
||||
help='A standalone bazel x86_64 binary is required to generate a project on Apple Silicon.',
|
||||
metavar='path'
|
||||
)
|
||||
generateProjectParser.add_argument(
|
||||
'--buildNumber',
|
||||
required=False,
|
||||
|
@ -20,23 +20,20 @@ def generate(build_environment: BuildEnvironment, disable_extensions, disable_pr
|
||||
|
||||
tulsi_path = os.path.join(project_path, 'Tulsi.app/Contents/MacOS/Tulsi')
|
||||
|
||||
if is_apple_silicon():
|
||||
tulsi_build_bazel_path = build_environment.bazel_x86_64_path
|
||||
if tulsi_build_bazel_path is None or not os.path.isfile(tulsi_build_bazel_path):
|
||||
print('Could not find a valid bazel x86_64 binary at {}'.format(tulsi_build_bazel_path))
|
||||
exit(1)
|
||||
else:
|
||||
tulsi_build_bazel_path = build_environment.bazel_path
|
||||
tulsi_build_bazel_path = build_environment.bazel_path
|
||||
|
||||
current_dir = os.getcwd()
|
||||
os.chdir(os.path.join(build_environment.base_path, 'build-system/tulsi'))
|
||||
call_executable([
|
||||
tulsi_build_bazel_path,
|
||||
'build', '//:tulsi',
|
||||
'--xcode_version={}'.format(build_environment.xcode_version),
|
||||
'--use_top_level_targets_for_symlinks',
|
||||
'--verbose_failures'
|
||||
])
|
||||
|
||||
tulsi_build_command = []
|
||||
tulsi_build_command += [tulsi_build_bazel_path]
|
||||
tulsi_build_command += ['build', '//:tulsi']
|
||||
if is_apple_silicon():
|
||||
tulsi_build_command += ['--macos_cpus=arm64']
|
||||
tulsi_build_command += ['--xcode_version={}'.format(build_environment.xcode_version)]
|
||||
tulsi_build_command += ['--use_top_level_targets_for_symlinks']
|
||||
tulsi_build_command += ['--verbose_failures']
|
||||
|
||||
os.chdir(current_dir)
|
||||
|
||||
bazel_wrapper_path = os.path.abspath('build-input/gen/project/bazel')
|
||||
|
@ -727,6 +727,6 @@ public protocol AccountContext: class {
|
||||
func chatLocationOutgoingReadState(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>) -> Signal<MessageId?, NoError>
|
||||
func applyMaxReadIndex(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>, messageIndex: MessageIndex)
|
||||
|
||||
func joinGroupCall(peerId: PeerId, activeCall: CachedChannelData.ActiveCall)
|
||||
func joinGroupCall(peerId: PeerId, joinAsPeerId: PeerId?, activeCall: CachedChannelData.ActiveCall)
|
||||
func requestCall(peerId: PeerId, isVideo: Bool, completion: @escaping () -> Void)
|
||||
}
|
||||
|
@ -177,19 +177,22 @@ public struct PresentationGroupCallState: Equatable {
|
||||
public var adminIds: Set<PeerId>
|
||||
public var muteState: GroupCallParticipantsContext.Participant.MuteState?
|
||||
public var defaultParticipantMuteState: DefaultParticipantMuteState?
|
||||
public var recordingStartTimestamp: Int32?
|
||||
|
||||
public init(
|
||||
networkState: NetworkState,
|
||||
canManageCall: Bool,
|
||||
adminIds: Set<PeerId>,
|
||||
muteState: GroupCallParticipantsContext.Participant.MuteState?,
|
||||
defaultParticipantMuteState: DefaultParticipantMuteState?
|
||||
defaultParticipantMuteState: DefaultParticipantMuteState?,
|
||||
recordingStartTimestamp: Int32?
|
||||
) {
|
||||
self.networkState = networkState
|
||||
self.canManageCall = canManageCall
|
||||
self.adminIds = adminIds
|
||||
self.muteState = muteState
|
||||
self.defaultParticipantMuteState = defaultParticipantMuteState
|
||||
self.recordingStartTimestamp = recordingStartTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,6 +282,7 @@ public protocol PresentationGroupCall: class {
|
||||
var accountContext: AccountContext { get }
|
||||
var internalId: CallSessionInternalId { get }
|
||||
var peerId: PeerId { get }
|
||||
var myPeerId: PeerId { get }
|
||||
|
||||
var isVideo: Bool { get }
|
||||
|
||||
@ -306,6 +310,7 @@ public protocol PresentationGroupCall: class {
|
||||
func setCurrentAudioOutput(_ output: AudioSessionOutput)
|
||||
|
||||
func updateMuteState(peerId: PeerId, isMuted: Bool) -> GroupCallParticipantsContext.Participant.MuteState?
|
||||
func setShouldBeRecording(_ shouldBeRecording: Bool)
|
||||
|
||||
func invitePeer(_ peerId: PeerId) -> Bool
|
||||
func removedPeer(_ peerId: PeerId)
|
||||
@ -323,5 +328,5 @@ public protocol PresentationCallManager: class {
|
||||
var currentGroupCallSignal: Signal<PresentationGroupCall?, NoError> { get }
|
||||
|
||||
func requestCall(context: AccountContext, peerId: PeerId, isVideo: Bool, endCurrentIfAny: Bool) -> RequestCallResult
|
||||
func joinGroupCall(context: AccountContext, peerId: PeerId, initialCall: CachedChannelData.ActiveCall, endCurrentIfAny: Bool) -> JoinGroupCallManagerResult
|
||||
func joinGroupCall(context: AccountContext, peerId: PeerId, joinAsPeerId: PeerId?, initialCall: CachedChannelData.ActiveCall, endCurrentIfAny: Bool) -> JoinGroupCallManagerResult
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ final class CallListControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
if let activeCall = activeCall {
|
||||
strongSelf.context.joinGroupCall(peerId: peerId, activeCall: activeCall)
|
||||
strongSelf.context.joinGroupCall(peerId: peerId, joinAsPeerId: nil, activeCall: activeCall)
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
@ -822,7 +822,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
let peersDisablingAddressNameAssignment = Promise<[Peer]?>()
|
||||
peersDisablingAddressNameAssignment.set(.single(nil) |> then(channelAddressNameAssignmentAvailability(account: context.account, peerId: peerId.namespace == Namespaces.Peer.CloudChannel ? peerId : nil) |> mapToSignal { result -> Signal<[Peer]?, NoError> in
|
||||
if case .addressNameLimitReached = result {
|
||||
return adminedPublicChannels(account: context.account, location: false)
|
||||
return adminedPublicChannels(account: context.account, scope: .all)
|
||||
|> map(Optional.init)
|
||||
} else {
|
||||
return .single([])
|
||||
|
@ -199,6 +199,7 @@ public final class CachedChannelData: CachedPeerData {
|
||||
public let invitedBy: PeerId?
|
||||
public let photo: TelegramMediaImage?
|
||||
public let activeCall: ActiveCall?
|
||||
public let callJoinPeerId: PeerId?
|
||||
public let pendingSuggestions: [String]
|
||||
|
||||
public let peerIds: Set<PeerId>
|
||||
@ -231,10 +232,11 @@ public final class CachedChannelData: CachedPeerData {
|
||||
self.invitedBy = nil
|
||||
self.photo = nil
|
||||
self.activeCall = nil
|
||||
self.callJoinPeerId = nil
|
||||
self.pendingSuggestions = []
|
||||
}
|
||||
|
||||
public init(isNotAccessible: Bool, flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, stickerPack: StickerPackCollectionInfo?, minAvailableMessageId: MessageId?, migrationReference: ChannelMigrationReference?, linkedDiscussionPeerId: LinkedDiscussionPeerId, peerGeoLocation: PeerGeoLocation?, slowModeTimeout: Int32?, slowModeValidUntilTimestamp: Int32?, hasScheduledMessages: Bool, statsDatacenterId: Int32, invitedBy: PeerId?, photo: TelegramMediaImage?, activeCall: ActiveCall?, autoremoveTimeout: CachedPeerAutoremoveTimeout, pendingSuggestions: [String]) {
|
||||
public init(isNotAccessible: Bool, flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, stickerPack: StickerPackCollectionInfo?, minAvailableMessageId: MessageId?, migrationReference: ChannelMigrationReference?, linkedDiscussionPeerId: LinkedDiscussionPeerId, peerGeoLocation: PeerGeoLocation?, slowModeTimeout: Int32?, slowModeValidUntilTimestamp: Int32?, hasScheduledMessages: Bool, statsDatacenterId: Int32, invitedBy: PeerId?, photo: TelegramMediaImage?, activeCall: ActiveCall?, callJoinPeerId: PeerId?, autoremoveTimeout: CachedPeerAutoremoveTimeout, pendingSuggestions: [String]) {
|
||||
self.isNotAccessible = isNotAccessible
|
||||
self.flags = flags
|
||||
self.about = about
|
||||
@ -255,6 +257,7 @@ public final class CachedChannelData: CachedPeerData {
|
||||
self.invitedBy = invitedBy
|
||||
self.photo = photo
|
||||
self.activeCall = activeCall
|
||||
self.callJoinPeerId = callJoinPeerId
|
||||
self.autoremoveTimeout = autoremoveTimeout
|
||||
self.pendingSuggestions = pendingSuggestions
|
||||
|
||||
@ -284,91 +287,95 @@ public final class CachedChannelData: CachedPeerData {
|
||||
}
|
||||
|
||||
public func withUpdatedIsNotAccessible(_ isNotAccessible: Bool) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedFlags(_ flags: CachedChannelFlags) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedAbout(_ about: String?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedParticipantsSummary(_ participantsSummary: CachedChannelParticipantsSummary) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedStickerPack(_ stickerPack: StickerPackCollectionInfo?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedMinAvailableMessageId(_ minAvailableMessageId: MessageId?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedMigrationReference(_ migrationReference: ChannelMigrationReference?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedLinkedDiscussionPeerId(_ linkedDiscussionPeerId: LinkedDiscussionPeerId) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedPeerGeoLocation(_ peerGeoLocation: PeerGeoLocation?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedSlowModeTimeout(_ slowModeTimeout: Int32?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedSlowModeValidUntilTimestamp(_ slowModeValidUntilTimestamp: Int32?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedStatsDatacenterId(_ statsDatacenterId: Int32) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedInvitedBy(_ invitedBy: PeerId?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedActiveCall(_ activeCall: ActiveCall?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedCallJoinPeerId(_ callJoinPeerId: PeerId?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
||||
}
|
||||
|
||||
public func withUpdatedPendingSuggestions(_ pendingSuggestions: [String]) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions)
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions)
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
@ -399,6 +406,8 @@ public final class CachedChannelData: CachedPeerData {
|
||||
self.activeCall = nil
|
||||
}
|
||||
|
||||
self.callJoinPeerId = decoder.decodeOptionalInt64ForKey("callJoinPeerId").flatMap(PeerId.init)
|
||||
|
||||
if let stickerPack = decoder.decodeObjectForKey("sp", decoder: { StickerPackCollectionInfo(decoder: $0) }) as? StickerPackCollectionInfo {
|
||||
self.stickerPack = stickerPack
|
||||
} else {
|
||||
@ -500,6 +509,12 @@ public final class CachedChannelData: CachedPeerData {
|
||||
encoder.encodeNil(forKey: "activeCall")
|
||||
}
|
||||
|
||||
if let callJoinPeerId = self.callJoinPeerId {
|
||||
encoder.encodeInt64(callJoinPeerId.toInt64(), forKey: "callJoinPeerId")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "callJoinPeerId")
|
||||
}
|
||||
|
||||
if let stickerPack = self.stickerPack {
|
||||
encoder.encodeObject(stickerPack, forKey: "sp")
|
||||
} else {
|
||||
@ -653,6 +668,10 @@ public final class CachedChannelData: CachedPeerData {
|
||||
return false
|
||||
}
|
||||
|
||||
if other.callJoinPeerId != self.callJoinPeerId {
|
||||
return false
|
||||
}
|
||||
|
||||
if other.pendingSuggestions != self.pendingSuggestions {
|
||||
return false
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ public final class CachedGroupData: CachedPeerData {
|
||||
public let associatedHistoryMessageId: MessageId? = nil
|
||||
|
||||
public let activeCall: CachedChannelData.ActiveCall?
|
||||
public let callJoinPeerId: PeerId?
|
||||
|
||||
public init() {
|
||||
self.participants = nil
|
||||
@ -74,9 +75,10 @@ public final class CachedGroupData: CachedPeerData {
|
||||
self.autoremoveTimeout = .unknown
|
||||
|
||||
self.activeCall = nil
|
||||
self.callJoinPeerId = nil
|
||||
}
|
||||
|
||||
public init(participants: CachedGroupParticipants?, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, about: String?, flags: CachedGroupFlags, hasScheduledMessages: Bool, invitedBy: PeerId?, photo: TelegramMediaImage?, activeCall: CachedChannelData.ActiveCall?, autoremoveTimeout: CachedPeerAutoremoveTimeout) {
|
||||
public init(participants: CachedGroupParticipants?, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, about: String?, flags: CachedGroupFlags, hasScheduledMessages: Bool, invitedBy: PeerId?, photo: TelegramMediaImage?, activeCall: CachedChannelData.ActiveCall?, autoremoveTimeout: CachedPeerAutoremoveTimeout, callJoinPeerId: PeerId?) {
|
||||
self.participants = participants
|
||||
self.exportedInvitation = exportedInvitation
|
||||
self.botInfos = botInfos
|
||||
@ -89,6 +91,7 @@ public final class CachedGroupData: CachedPeerData {
|
||||
self.photo = photo
|
||||
self.activeCall = activeCall
|
||||
self.autoremoveTimeout = autoremoveTimeout
|
||||
self.callJoinPeerId = callJoinPeerId
|
||||
|
||||
var messageIds = Set<MessageId>()
|
||||
if let pinnedMessageId = self.pinnedMessageId {
|
||||
@ -147,6 +150,8 @@ public final class CachedGroupData: CachedPeerData {
|
||||
self.activeCall = nil
|
||||
}
|
||||
|
||||
self.callJoinPeerId = decoder.decodeOptionalInt64ForKey("callJoinPeerId").flatMap(PeerId.init)
|
||||
|
||||
var messageIds = Set<MessageId>()
|
||||
if let pinnedMessageId = self.pinnedMessageId {
|
||||
messageIds.insert(pinnedMessageId)
|
||||
@ -218,6 +223,12 @@ public final class CachedGroupData: CachedPeerData {
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "activeCall")
|
||||
}
|
||||
|
||||
if let callJoinPeerId = self.callJoinPeerId {
|
||||
encoder.encodeInt64(callJoinPeerId.toInt64(), forKey: "callJoinPeerId")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "callJoinPeerId")
|
||||
}
|
||||
}
|
||||
|
||||
public func isEqual(to: CachedPeerData) -> Bool {
|
||||
@ -229,54 +240,62 @@ public final class CachedGroupData: CachedPeerData {
|
||||
return false
|
||||
}
|
||||
|
||||
if self.callJoinPeerId != other.callJoinPeerId {
|
||||
return false
|
||||
}
|
||||
|
||||
return self.participants == other.participants && self.exportedInvitation == other.exportedInvitation && self.botInfos == other.botInfos && self.peerStatusSettings == other.peerStatusSettings && self.pinnedMessageId == other.pinnedMessageId && self.about == other.about && self.flags == other.flags && self.hasScheduledMessages == other.hasScheduledMessages && self.autoremoveTimeout == other.autoremoveTimeout && self.invitedBy == other.invitedBy
|
||||
}
|
||||
|
||||
public func withUpdatedParticipants(_ participants: CachedGroupParticipants?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedAbout(_ about: String?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedFlags(_ flags: CachedGroupFlags) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedInvitedBy(_ invitedBy: PeerId?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedActiveCall(_ activeCall: CachedChannelData.ActiveCall?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: activeCall, autoremoveTimeout: self.autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: autoremoveTimeout)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
||||
}
|
||||
|
||||
public func withUpdatedCallJoinPeerId(_ callJoinPeerId: PeerId?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: callJoinPeerId)
|
||||
}
|
||||
}
|
||||
|
@ -7,12 +7,12 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1255641564] = { return parseString($0) }
|
||||
dict[-1240849242] = { return Api.messages.StickerSet.parse_stickerSet($0) }
|
||||
dict[2004925620] = { return Api.GroupCall.parse_groupCallDiscarded($0) }
|
||||
dict[1435512961] = { return Api.GroupCall.parse_groupCall($0) }
|
||||
dict[-1061026514] = { return Api.GroupCall.parse_groupCall($0) }
|
||||
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
|
||||
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
|
||||
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
|
||||
dict[-261341160] = { return Api.ChatFull.parse_chatFull($0) }
|
||||
dict[625524791] = { return Api.ChatFull.parse_channelFull($0) }
|
||||
dict[-1977734781] = { return Api.ChatFull.parse_chatFull($0) }
|
||||
dict[1418477459] = { return Api.ChatFull.parse_channelFull($0) }
|
||||
dict[-1159937629] = { return Api.PollResults.parse_pollResults($0) }
|
||||
dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) }
|
||||
dict[-636267638] = { return Api.ChatParticipant.parse_chatParticipantCreator($0) }
|
||||
@ -142,7 +142,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[767652808] = { return Api.InputEncryptedFile.parse_inputEncryptedFileBigUploaded($0) }
|
||||
dict[1304052993] = { return Api.account.Takeout.parse_takeout($0) }
|
||||
dict[-1456996667] = { return Api.messages.InactiveChats.parse_inactiveChats($0) }
|
||||
dict[1690708501] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) }
|
||||
dict[-763544865] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) }
|
||||
dict[1443858741] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedMessage($0) }
|
||||
dict[-1802240206] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedFile($0) }
|
||||
dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) }
|
||||
@ -277,8 +277,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-219423922] = { return Api.Update.parse_updateGroupCallParticipants($0) }
|
||||
dict[-1537295973] = { return Api.Update.parse_updateGroupCall($0) }
|
||||
dict[-1147422299] = { return Api.Update.parse_updatePeerHistoryTTL($0) }
|
||||
dict[1620733652] = { return Api.Update.parse_updateChatParticipant($0) }
|
||||
dict[1708307556] = { return Api.Update.parse_updateChannelParticipant($0) }
|
||||
dict[-206342113] = { return Api.Update.parse_updateChatParticipant($0) }
|
||||
dict[2146218476] = { return Api.Update.parse_updateChannelParticipant($0) }
|
||||
dict[133777546] = { return Api.Update.parse_updateBotStopped($0) }
|
||||
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
||||
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
||||
@ -535,7 +535,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1495959709] = { return Api.MessageReplyHeader.parse_messageReplyHeader($0) }
|
||||
dict[411017418] = { return Api.SecureValue.parse_secureValue($0) }
|
||||
dict[-316748368] = { return Api.SecureValueHash.parse_secureValueHash($0) }
|
||||
dict[1722485756] = { return Api.phone.GroupCall.parse_groupCall($0) }
|
||||
dict[-1636664659] = { return Api.phone.GroupCall.parse_groupCall($0) }
|
||||
dict[-398136321] = { return Api.messages.SearchCounter.parse_searchCounter($0) }
|
||||
dict[-1188055347] = { return Api.PageListItem.parse_pageListItemText($0) }
|
||||
dict[635466748] = { return Api.PageListItem.parse_pageListItemBlocks($0) }
|
||||
@ -563,7 +563,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-2042159726] = { return Api.SecurePasswordKdfAlgo.parse_securePasswordKdfAlgoSHA512($0) }
|
||||
dict[-1032140601] = { return Api.BotCommand.parse_botCommand($0) }
|
||||
dict[1474462241] = { return Api.account.ContentSettings.parse_contentSettings($0) }
|
||||
dict[-1661028051] = { return Api.phone.GroupParticipants.parse_groupParticipants($0) }
|
||||
dict[-193506890] = { return Api.phone.GroupParticipants.parse_groupParticipants($0) }
|
||||
dict[507405952] = { return Api.ChatInviteImporter.parse_chatInviteImporter($0) }
|
||||
dict[-2066640507] = { return Api.messages.AffectedMessages.parse_affectedMessages($0) }
|
||||
dict[-402498398] = { return Api.messages.SavedGifs.parse_savedGifsNotModified($0) }
|
||||
@ -667,6 +667,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-667654413] = { return Api.InputFileLocation.parse_inputPhotoLegacyFileLocation($0) }
|
||||
dict[668375447] = { return Api.InputFileLocation.parse_inputPeerPhotoFileLocation($0) }
|
||||
dict[230353641] = { return Api.InputFileLocation.parse_inputStickerSetThumb($0) }
|
||||
dict[-775148961] = { return Api.InputFileLocation.parse_inputGroupCallStream($0) }
|
||||
dict[286776671] = { return Api.GeoPoint.parse_geoPointEmpty($0) }
|
||||
dict[-1297942941] = { return Api.GeoPoint.parse_geoPoint($0) }
|
||||
dict[506920429] = { return Api.InputPhoneCall.parse_inputPhoneCall($0) }
|
||||
|
@ -1,7 +1,7 @@
|
||||
public extension Api {
|
||||
public enum GroupCall: TypeConstructorDescription {
|
||||
case groupCallDiscarded(id: Int64, accessHash: Int64, duration: Int32)
|
||||
case groupCall(flags: Int32, id: Int64, accessHash: Int64, participantsCount: Int32, params: Api.DataJSON?, version: Int32)
|
||||
case groupCall(flags: Int32, id: Int64, accessHash: Int64, participantsCount: Int32, params: Api.DataJSON?, title: String?, streamDcId: Int32?, recordStartDate: Int32?, version: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -13,15 +13,18 @@ public extension Api {
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeInt32(duration, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .groupCall(let flags, let id, let accessHash, let participantsCount, let params, let version):
|
||||
case .groupCall(let flags, let id, let accessHash, let participantsCount, let params, let title, let streamDcId, let recordStartDate, let version):
|
||||
if boxed {
|
||||
buffer.appendInt32(1435512961)
|
||||
buffer.appendInt32(-1061026514)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeInt32(participantsCount, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {params!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(streamDcId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 5) != 0 {serializeInt32(recordStartDate!, buffer: buffer, boxed: false)}
|
||||
serializeInt32(version, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
@ -31,8 +34,8 @@ public extension Api {
|
||||
switch self {
|
||||
case .groupCallDiscarded(let id, let accessHash, let duration):
|
||||
return ("groupCallDiscarded", [("id", id), ("accessHash", accessHash), ("duration", duration)])
|
||||
case .groupCall(let flags, let id, let accessHash, let participantsCount, let params, let version):
|
||||
return ("groupCall", [("flags", flags), ("id", id), ("accessHash", accessHash), ("participantsCount", participantsCount), ("params", params), ("version", version)])
|
||||
case .groupCall(let flags, let id, let accessHash, let participantsCount, let params, let title, let streamDcId, let recordStartDate, let version):
|
||||
return ("groupCall", [("flags", flags), ("id", id), ("accessHash", accessHash), ("participantsCount", participantsCount), ("params", params), ("title", title), ("streamDcId", streamDcId), ("recordStartDate", recordStartDate), ("version", version)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,16 +69,25 @@ public extension Api {
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.DataJSON
|
||||
} }
|
||||
var _6: Int32?
|
||||
_6 = reader.readInt32()
|
||||
var _6: String?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) }
|
||||
var _7: Int32?
|
||||
if Int(_1!) & Int(1 << 4) != 0 {_7 = reader.readInt32() }
|
||||
var _8: Int32?
|
||||
if Int(_1!) & Int(1 << 5) != 0 {_8 = reader.readInt32() }
|
||||
var _9: Int32?
|
||||
_9 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.GroupCall.groupCall(flags: _1!, id: _2!, accessHash: _3!, participantsCount: _4!, params: _5, version: _6!)
|
||||
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 5) == 0) || _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.GroupCall.groupCall(flags: _1!, id: _2!, accessHash: _3!, participantsCount: _4!, params: _5, title: _6, streamDcId: _7, recordStartDate: _8, version: _9!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -142,14 +154,14 @@ public extension Api {
|
||||
|
||||
}
|
||||
public enum ChatFull: TypeConstructorDescription {
|
||||
case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?, call: Api.InputGroupCall?, ttlPeriod: Int32?)
|
||||
case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int32?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?, ttlPeriod: Int32?, pendingSuggestions: [String]?)
|
||||
case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?, call: Api.InputGroupCall?, ttlPeriod: Int32?, groupcallDefaultJoinAs: Api.Peer?)
|
||||
case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int32?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?, ttlPeriod: Int32?, pendingSuggestions: [String]?, groupcallDefaultJoinAs: Api.Peer?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod):
|
||||
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod, let groupcallDefaultJoinAs):
|
||||
if boxed {
|
||||
buffer.appendInt32(-261341160)
|
||||
buffer.appendInt32(-1977734781)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
@ -167,10 +179,11 @@ public extension Api {
|
||||
if Int(flags) & Int(1 << 11) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 12) != 0 {call!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 14) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 15) != 0 {groupcallDefaultJoinAs!.serialize(buffer, true)}
|
||||
break
|
||||
case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions):
|
||||
case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs):
|
||||
if boxed {
|
||||
buffer.appendInt32(625524791)
|
||||
buffer.appendInt32(1418477459)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
@ -210,16 +223,17 @@ public extension Api {
|
||||
for item in pendingSuggestions! {
|
||||
serializeString(item, buffer: buffer, boxed: false)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 26) != 0 {groupcallDefaultJoinAs!.serialize(buffer, true)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod):
|
||||
return ("chatFull", [("flags", flags), ("id", id), ("about", about), ("participants", participants), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId), ("folderId", folderId), ("call", call), ("ttlPeriod", ttlPeriod)])
|
||||
case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions):
|
||||
return ("channelFull", [("flags", flags), ("id", id), ("about", about), ("participantsCount", participantsCount), ("adminsCount", adminsCount), ("kickedCount", kickedCount), ("bannedCount", bannedCount), ("onlineCount", onlineCount), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("unreadCount", unreadCount), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("migratedFromChatId", migratedFromChatId), ("migratedFromMaxId", migratedFromMaxId), ("pinnedMsgId", pinnedMsgId), ("stickerset", stickerset), ("availableMinId", availableMinId), ("folderId", folderId), ("linkedChatId", linkedChatId), ("location", location), ("slowmodeSeconds", slowmodeSeconds), ("slowmodeNextSendDate", slowmodeNextSendDate), ("statsDc", statsDc), ("pts", pts), ("call", call), ("ttlPeriod", ttlPeriod), ("pendingSuggestions", pendingSuggestions)])
|
||||
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod, let groupcallDefaultJoinAs):
|
||||
return ("chatFull", [("flags", flags), ("id", id), ("about", about), ("participants", participants), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId), ("folderId", folderId), ("call", call), ("ttlPeriod", ttlPeriod), ("groupcallDefaultJoinAs", groupcallDefaultJoinAs)])
|
||||
case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs):
|
||||
return ("channelFull", [("flags", flags), ("id", id), ("about", about), ("participantsCount", participantsCount), ("adminsCount", adminsCount), ("kickedCount", kickedCount), ("bannedCount", bannedCount), ("onlineCount", onlineCount), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("unreadCount", unreadCount), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("migratedFromChatId", migratedFromChatId), ("migratedFromMaxId", migratedFromMaxId), ("pinnedMsgId", pinnedMsgId), ("stickerset", stickerset), ("availableMinId", availableMinId), ("folderId", folderId), ("linkedChatId", linkedChatId), ("location", location), ("slowmodeSeconds", slowmodeSeconds), ("slowmodeNextSendDate", slowmodeNextSendDate), ("statsDc", statsDc), ("pts", pts), ("call", call), ("ttlPeriod", ttlPeriod), ("pendingSuggestions", pendingSuggestions), ("groupcallDefaultJoinAs", groupcallDefaultJoinAs)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,6 +274,10 @@ public extension Api {
|
||||
} }
|
||||
var _12: Int32?
|
||||
if Int(_1!) & Int(1 << 14) != 0 {_12 = reader.readInt32() }
|
||||
var _13: Api.Peer?
|
||||
if Int(_1!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() {
|
||||
_13 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -272,8 +290,9 @@ public extension Api {
|
||||
let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil
|
||||
let _c11 = (Int(_1!) & Int(1 << 12) == 0) || _11 != nil
|
||||
let _c12 = (Int(_1!) & Int(1 << 14) == 0) || _12 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 {
|
||||
return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11, ttlPeriod: _12)
|
||||
let _c13 = (Int(_1!) & Int(1 << 15) == 0) || _13 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 {
|
||||
return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11, ttlPeriod: _12, groupcallDefaultJoinAs: _13)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -356,6 +375,10 @@ public extension Api {
|
||||
if Int(_1!) & Int(1 << 25) != 0 {if let _ = reader.readInt32() {
|
||||
_30 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self)
|
||||
} }
|
||||
var _31: Api.Peer?
|
||||
if Int(_1!) & Int(1 << 26) != 0 {if let signature = reader.readInt32() {
|
||||
_31 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -386,8 +409,9 @@ public extension Api {
|
||||
let _c28 = (Int(_1!) & Int(1 << 21) == 0) || _28 != nil
|
||||
let _c29 = (Int(_1!) & Int(1 << 24) == 0) || _29 != nil
|
||||
let _c30 = (Int(_1!) & Int(1 << 25) == 0) || _30 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 {
|
||||
return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20, folderId: _21, linkedChatId: _22, location: _23, slowmodeSeconds: _24, slowmodeNextSendDate: _25, statsDc: _26, pts: _27!, call: _28, ttlPeriod: _29, pendingSuggestions: _30)
|
||||
let _c31 = (Int(_1!) & Int(1 << 26) == 0) || _31 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 {
|
||||
return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20, folderId: _21, linkedChatId: _22, location: _23, slowmodeSeconds: _24, slowmodeNextSendDate: _25, statsDc: _26, pts: _27!, call: _28, ttlPeriod: _29, pendingSuggestions: _30, groupcallDefaultJoinAs: _31)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -3580,36 +3604,39 @@ public extension Api {
|
||||
|
||||
}
|
||||
public enum GroupCallParticipant: TypeConstructorDescription {
|
||||
case groupCallParticipant(flags: Int32, userId: Int32, date: Int32, activeDate: Int32?, source: Int32, volume: Int32?)
|
||||
case groupCallParticipant(flags: Int32, peer: Api.Peer, date: Int32, activeDate: Int32?, source: Int32, volume: Int32?, about: String?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupCallParticipant(let flags, let userId, let date, let activeDate, let source, let volume):
|
||||
case .groupCallParticipant(let flags, let peer, let date, let activeDate, let source, let volume, let about):
|
||||
if boxed {
|
||||
buffer.appendInt32(1690708501)
|
||||
buffer.appendInt32(-763544865)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(activeDate!, buffer: buffer, boxed: false)}
|
||||
serializeInt32(source, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(volume!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 11) != 0 {serializeString(about!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupCallParticipant(let flags, let userId, let date, let activeDate, let source, let volume):
|
||||
return ("groupCallParticipant", [("flags", flags), ("userId", userId), ("date", date), ("activeDate", activeDate), ("source", source), ("volume", volume)])
|
||||
case .groupCallParticipant(let flags, let peer, let date, let activeDate, let source, let volume, let about):
|
||||
return ("groupCallParticipant", [("flags", flags), ("peer", peer), ("date", date), ("activeDate", activeDate), ("source", source), ("volume", volume), ("about", about)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_groupCallParticipant(_ reader: BufferReader) -> GroupCallParticipant? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _2: Api.Peer?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
}
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
@ -3618,14 +3645,17 @@ public extension Api {
|
||||
_5 = reader.readInt32()
|
||||
var _6: Int32?
|
||||
if Int(_1!) & Int(1 << 7) != 0 {_6 = reader.readInt32() }
|
||||
var _7: String?
|
||||
if Int(_1!) & Int(1 << 11) != 0 {_7 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 7) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.GroupCallParticipant.groupCallParticipant(flags: _1!, userId: _2!, date: _3!, activeDate: _4, source: _5!, volume: _6)
|
||||
let _c7 = (Int(_1!) & Int(1 << 11) == 0) || _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.GroupCallParticipant.groupCallParticipant(flags: _1!, peer: _2!, date: _3!, activeDate: _4, source: _5!, volume: _6, about: _7)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -4640,8 +4670,8 @@ public extension Api {
|
||||
case updateGroupCallParticipants(call: Api.InputGroupCall, participants: [Api.GroupCallParticipant], version: Int32)
|
||||
case updateGroupCall(chatId: Int32, call: Api.GroupCall)
|
||||
case updatePeerHistoryTTL(flags: Int32, peer: Api.Peer, ttlPeriod: Int32?)
|
||||
case updateChatParticipant(flags: Int32, chatId: Int32, date: Int32, userId: Int32, prevParticipant: Api.ChatParticipant?, newParticipant: Api.ChatParticipant?, qts: Int32)
|
||||
case updateChannelParticipant(flags: Int32, channelId: Int32, date: Int32, userId: Int32, prevParticipant: Api.ChannelParticipant?, newParticipant: Api.ChannelParticipant?, qts: Int32)
|
||||
case updateChatParticipant(flags: Int32, chatId: Int32, date: Int32, actorId: Int32, userId: Int32, prevParticipant: Api.ChatParticipant?, newParticipant: Api.ChatParticipant?, invite: Api.ExportedChatInvite?, qts: Int32)
|
||||
case updateChannelParticipant(flags: Int32, channelId: Int32, date: Int32, actorId: Int32, userId: Int32, prevParticipant: Api.ChannelParticipant?, newParticipant: Api.ChannelParticipant?, invite: Api.ExportedChatInvite?, qts: Int32)
|
||||
case updateBotStopped(userId: Int32, date: Int32, stopped: Api.Bool, qts: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
@ -5400,28 +5430,32 @@ public extension Api {
|
||||
peer.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .updateChatParticipant(let flags, let chatId, let date, let userId, let prevParticipant, let newParticipant, let qts):
|
||||
case .updateChatParticipant(let flags, let chatId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts):
|
||||
if boxed {
|
||||
buffer.appendInt32(1620733652)
|
||||
buffer.appendInt32(-206342113)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(chatId, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
serializeInt32(actorId, buffer: buffer, boxed: false)
|
||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {prevParticipant!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {newParticipant!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {invite!.serialize(buffer, true)}
|
||||
serializeInt32(qts, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .updateChannelParticipant(let flags, let channelId, let date, let userId, let prevParticipant, let newParticipant, let qts):
|
||||
case .updateChannelParticipant(let flags, let channelId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts):
|
||||
if boxed {
|
||||
buffer.appendInt32(1708307556)
|
||||
buffer.appendInt32(2146218476)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(channelId, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
serializeInt32(actorId, buffer: buffer, boxed: false)
|
||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {prevParticipant!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {newParticipant!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {invite!.serialize(buffer, true)}
|
||||
serializeInt32(qts, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .updateBotStopped(let userId, let date, let stopped, let qts):
|
||||
@ -5614,10 +5648,10 @@ public extension Api {
|
||||
return ("updateGroupCall", [("chatId", chatId), ("call", call)])
|
||||
case .updatePeerHistoryTTL(let flags, let peer, let ttlPeriod):
|
||||
return ("updatePeerHistoryTTL", [("flags", flags), ("peer", peer), ("ttlPeriod", ttlPeriod)])
|
||||
case .updateChatParticipant(let flags, let chatId, let date, let userId, let prevParticipant, let newParticipant, let qts):
|
||||
return ("updateChatParticipant", [("flags", flags), ("chatId", chatId), ("date", date), ("userId", userId), ("prevParticipant", prevParticipant), ("newParticipant", newParticipant), ("qts", qts)])
|
||||
case .updateChannelParticipant(let flags, let channelId, let date, let userId, let prevParticipant, let newParticipant, let qts):
|
||||
return ("updateChannelParticipant", [("flags", flags), ("channelId", channelId), ("date", date), ("userId", userId), ("prevParticipant", prevParticipant), ("newParticipant", newParticipant), ("qts", qts)])
|
||||
case .updateChatParticipant(let flags, let chatId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts):
|
||||
return ("updateChatParticipant", [("flags", flags), ("chatId", chatId), ("date", date), ("actorId", actorId), ("userId", userId), ("prevParticipant", prevParticipant), ("newParticipant", newParticipant), ("invite", invite), ("qts", qts)])
|
||||
case .updateChannelParticipant(let flags, let channelId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts):
|
||||
return ("updateChannelParticipant", [("flags", flags), ("channelId", channelId), ("date", date), ("actorId", actorId), ("userId", userId), ("prevParticipant", prevParticipant), ("newParticipant", newParticipant), ("invite", invite), ("qts", qts)])
|
||||
case .updateBotStopped(let userId, let date, let stopped, let qts):
|
||||
return ("updateBotStopped", [("userId", userId), ("date", date), ("stopped", stopped), ("qts", qts)])
|
||||
}
|
||||
@ -7140,25 +7174,33 @@ public extension Api {
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Api.ChatParticipant?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.ChatParticipant
|
||||
} }
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Api.ChatParticipant?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.ChatParticipant
|
||||
} }
|
||||
var _7: Int32?
|
||||
_7 = reader.readInt32()
|
||||
var _7: Api.ChatParticipant?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.ChatParticipant
|
||||
} }
|
||||
var _8: Api.ExportedChatInvite?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
|
||||
} }
|
||||
var _9: Int32?
|
||||
_9 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.Update.updateChatParticipant(flags: _1!, chatId: _2!, date: _3!, userId: _4!, prevParticipant: _5, newParticipant: _6, qts: _7!)
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.Update.updateChatParticipant(flags: _1!, chatId: _2!, date: _3!, actorId: _4!, userId: _5!, prevParticipant: _6, newParticipant: _7, invite: _8, qts: _9!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -7173,25 +7215,33 @@ public extension Api {
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Api.ChannelParticipant?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant
|
||||
} }
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Api.ChannelParticipant?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant
|
||||
} }
|
||||
var _7: Int32?
|
||||
_7 = reader.readInt32()
|
||||
var _7: Api.ChannelParticipant?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant
|
||||
} }
|
||||
var _8: Api.ExportedChatInvite?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
|
||||
} }
|
||||
var _9: Int32?
|
||||
_9 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.Update.updateChannelParticipant(flags: _1!, channelId: _2!, date: _3!, userId: _4!, prevParticipant: _5, newParticipant: _6, qts: _7!)
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.Update.updateChannelParticipant(flags: _1!, channelId: _2!, date: _3!, actorId: _4!, userId: _5!, prevParticipant: _6, newParticipant: _7, invite: _8, qts: _9!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -16967,6 +17017,7 @@ public extension Api {
|
||||
case inputPhotoLegacyFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, volumeId: Int64, localId: Int32, secret: Int64)
|
||||
case inputPeerPhotoFileLocation(flags: Int32, peer: Api.InputPeer, volumeId: Int64, localId: Int32)
|
||||
case inputStickerSetThumb(stickerset: Api.InputStickerSet, volumeId: Int64, localId: Int32)
|
||||
case inputGroupCallStream(call: Api.InputGroupCall, date: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -17045,6 +17096,13 @@ public extension Api {
|
||||
serializeInt64(volumeId, buffer: buffer, boxed: false)
|
||||
serializeInt32(localId, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputGroupCallStream(let call, let date):
|
||||
if boxed {
|
||||
buffer.appendInt32(-775148961)
|
||||
}
|
||||
call.serialize(buffer, true)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -17068,6 +17126,8 @@ public extension Api {
|
||||
return ("inputPeerPhotoFileLocation", [("flags", flags), ("peer", peer), ("volumeId", volumeId), ("localId", localId)])
|
||||
case .inputStickerSetThumb(let stickerset, let volumeId, let localId):
|
||||
return ("inputStickerSetThumb", [("stickerset", stickerset), ("volumeId", volumeId), ("localId", localId)])
|
||||
case .inputGroupCallStream(let call, let date):
|
||||
return ("inputGroupCallStream", [("call", call), ("date", date)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -17229,6 +17289,22 @@ public extension Api {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputGroupCallStream(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Api.InputGroupCall?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
}
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputFileLocation.inputGroupCallStream(call: _1!, date: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum GeoPoint: TypeConstructorDescription {
|
||||
|
@ -1611,13 +1611,13 @@ public struct photos {
|
||||
public extension Api {
|
||||
public struct phone {
|
||||
public enum GroupCall: TypeConstructorDescription {
|
||||
case groupCall(call: Api.GroupCall, participants: [Api.GroupCallParticipant], participantsNextOffset: String, users: [Api.User])
|
||||
case groupCall(call: Api.GroupCall, participants: [Api.GroupCallParticipant], participantsNextOffset: String, chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupCall(let call, let participants, let participantsNextOffset, let users):
|
||||
case .groupCall(let call, let participants, let participantsNextOffset, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(1722485756)
|
||||
buffer.appendInt32(-1636664659)
|
||||
}
|
||||
call.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
@ -1627,6 +1627,11 @@ public struct phone {
|
||||
}
|
||||
serializeString(participantsNextOffset, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
@ -1637,8 +1642,8 @@ public struct phone {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupCall(let call, let participants, let participantsNextOffset, let users):
|
||||
return ("groupCall", [("call", call), ("participants", participants), ("participantsNextOffset", participantsNextOffset), ("users", users)])
|
||||
case .groupCall(let call, let participants, let participantsNextOffset, let chats, let users):
|
||||
return ("groupCall", [("call", call), ("participants", participants), ("participantsNextOffset", participantsNextOffset), ("chats", chats), ("users", users)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -1653,16 +1658,21 @@ public struct phone {
|
||||
}
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: [Api.User]?
|
||||
var _4: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _5: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.phone.GroupCall.groupCall(call: _1!, participants: _2!, participantsNextOffset: _3!, users: _4!)
|
||||
let _c5 = _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.phone.GroupCall.groupCall(call: _1!, participants: _2!, participantsNextOffset: _3!, chats: _4!, users: _5!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -1671,13 +1681,13 @@ public struct phone {
|
||||
|
||||
}
|
||||
public enum GroupParticipants: TypeConstructorDescription {
|
||||
case groupParticipants(count: Int32, participants: [Api.GroupCallParticipant], nextOffset: String, users: [Api.User], version: Int32)
|
||||
case groupParticipants(count: Int32, participants: [Api.GroupCallParticipant], nextOffset: String, chats: [Api.Chat], users: [Api.User], version: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupParticipants(let count, let participants, let nextOffset, let users, let version):
|
||||
case .groupParticipants(let count, let participants, let nextOffset, let chats, let users, let version):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1661028051)
|
||||
buffer.appendInt32(-193506890)
|
||||
}
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
@ -1687,6 +1697,11 @@ public struct phone {
|
||||
}
|
||||
serializeString(nextOffset, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
@ -1698,8 +1713,8 @@ public struct phone {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupParticipants(let count, let participants, let nextOffset, let users, let version):
|
||||
return ("groupParticipants", [("count", count), ("participants", participants), ("nextOffset", nextOffset), ("users", users), ("version", version)])
|
||||
case .groupParticipants(let count, let participants, let nextOffset, let chats, let users, let version):
|
||||
return ("groupParticipants", [("count", count), ("participants", participants), ("nextOffset", nextOffset), ("chats", chats), ("users", users), ("version", version)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -1712,19 +1727,24 @@ public struct phone {
|
||||
}
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: [Api.User]?
|
||||
var _4: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _5: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
var _6: Int32?
|
||||
_6 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.phone.GroupParticipants.groupParticipants(count: _1!, participants: _2!, nextOffset: _3!, users: _4!, version: _5!)
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.phone.GroupParticipants.groupParticipants(count: _1!, participants: _2!, nextOffset: _3!, chats: _4!, users: _5!, version: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -3617,13 +3637,15 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func requestUrlAuth(peer: Api.InputPeer, msgId: Int32, buttonId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.UrlAuthResult>) {
|
||||
public static func requestUrlAuth(flags: Int32, peer: Api.InputPeer?, msgId: Int32?, buttonId: Int32?, url: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.UrlAuthResult>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-482388461)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
serializeInt32(buttonId, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.requestUrlAuth", parameters: [("peer", peer), ("msgId", msgId), ("buttonId", buttonId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.UrlAuthResult? in
|
||||
buffer.appendInt32(428848198)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {peer!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(buttonId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)}
|
||||
return (FunctionDescription(name: "messages.requestUrlAuth", parameters: [("flags", flags), ("peer", peer), ("msgId", msgId), ("buttonId", buttonId), ("url", url)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.UrlAuthResult? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.UrlAuthResult?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -3633,14 +3655,15 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func acceptUrlAuth(flags: Int32, peer: Api.InputPeer, msgId: Int32, buttonId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.UrlAuthResult>) {
|
||||
public static func acceptUrlAuth(flags: Int32, peer: Api.InputPeer?, msgId: Int32?, buttonId: Int32?, url: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.UrlAuthResult>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-148247912)
|
||||
buffer.appendInt32(-1322487515)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
serializeInt32(buttonId, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.acceptUrlAuth", parameters: [("flags", flags), ("peer", peer), ("msgId", msgId), ("buttonId", buttonId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.UrlAuthResult? in
|
||||
if Int(flags) & Int(1 << 1) != 0 {peer!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(buttonId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)}
|
||||
return (FunctionDescription(name: "messages.acceptUrlAuth", parameters: [("flags", flags), ("peer", peer), ("msgId", msgId), ("buttonId", buttonId), ("url", url)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.UrlAuthResult? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.UrlAuthResult?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -4028,6 +4051,21 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func getExportedChatInvite(peer: Api.InputPeer, link: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.ExportedChatInvite>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1937010524)
|
||||
peer.serialize(buffer, true)
|
||||
serializeString(link, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getExportedChatInvite", parameters: [("peer", peer), ("link", link)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvite? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.ExportedChatInvite?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.messages.ExportedChatInvite
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func editExportedChatInvite(flags: Int32, peer: Api.InputPeer, link: String, expireDate: Int32?, usageLimit: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.ExportedChatInvite>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(48562110)
|
||||
@ -7557,12 +7595,14 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func createGroupCall(peer: Api.InputPeer, randomId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
public static func createGroupCall(flags: Int32, peer: Api.InputPeer, joinAs: Api.InputPeer?, randomId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1120031776)
|
||||
buffer.appendInt32(534090322)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {joinAs!.serialize(buffer, true)}
|
||||
serializeInt32(randomId, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "phone.createGroupCall", parameters: [("peer", peer), ("randomId", randomId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
return (FunctionDescription(name: "phone.createGroupCall", parameters: [("flags", flags), ("peer", peer), ("joinAs", joinAs), ("randomId", randomId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -7572,13 +7612,14 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func joinGroupCall(flags: Int32, call: Api.InputGroupCall, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
public static func joinGroupCall(flags: Int32, call: Api.InputGroupCall, joinAs: Api.InputPeer?, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1604095586)
|
||||
buffer.appendInt32(780232376)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
call.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 1) != 0 {joinAs!.serialize(buffer, true)}
|
||||
params.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "phone.joinGroupCall", parameters: [("flags", flags), ("call", call), ("params", params)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
return (FunctionDescription(name: "phone.joinGroupCall", parameters: [("flags", flags), ("call", call), ("joinAs", joinAs), ("params", params)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -7603,23 +7644,6 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func editGroupCallMember(flags: Int32, call: Api.InputGroupCall, userId: Api.InputUser, volume: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1511559976)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
call.serialize(buffer, true)
|
||||
userId.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(volume!, buffer: buffer, boxed: false)}
|
||||
return (FunctionDescription(name: "phone.editGroupCallMember", parameters: [("flags", flags), ("call", call), ("userId", userId), ("volume", volume)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func inviteToGroupCall(call: Api.InputGroupCall, users: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(2067345760)
|
||||
@ -7723,6 +7747,53 @@ public extension Api {
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func toggleGroupCallRecord(call: Api.InputGroupCall, start: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1990430344)
|
||||
call.serialize(buffer, true)
|
||||
start.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "phone.toggleGroupCallRecord", parameters: [("call", call), ("start", start)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func editGroupCallParticipant(flags: Int32, call: Api.InputGroupCall, participant: Api.InputPeer, volume: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1192486819)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
call.serialize(buffer, true)
|
||||
participant.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(volume!, buffer: buffer, boxed: false)}
|
||||
return (FunctionDescription(name: "phone.editGroupCallParticipant", parameters: [("flags", flags), ("call", call), ("participant", participant), ("volume", volume)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func editGroupCallTitle(call: Api.InputGroupCall, title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(480685066)
|
||||
call.serialize(buffer, true)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "phone.editGroupCallTitle", parameters: [("call", call), ("title", title)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,6 +405,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
|
||||
}
|
||||
strongSelf.joinGroupCall(
|
||||
peerId: groupCallPanelData.peerId,
|
||||
joinAsPeerId: nil,
|
||||
info: groupCallPanelData.info
|
||||
)
|
||||
})
|
||||
@ -851,7 +852,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
|
||||
})]
|
||||
}
|
||||
|
||||
open func joinGroupCall(peerId: PeerId, info: GroupCallInfo) {
|
||||
self.context.joinGroupCall(peerId: peerId, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash))
|
||||
open func joinGroupCall(peerId: PeerId, joinAsPeerId: PeerId?, info: GroupCallInfo) {
|
||||
self.context.joinGroupCall(peerId: peerId, joinAsPeerId: joinAsPeerId, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash))
|
||||
}
|
||||
}
|
||||
|
@ -624,9 +624,9 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
}
|
||||
}
|
||||
|
||||
public func joinGroupCall(context: AccountContext, peerId: PeerId, initialCall: CachedChannelData.ActiveCall, endCurrentIfAny: Bool) -> JoinGroupCallManagerResult {
|
||||
public func joinGroupCall(context: AccountContext, peerId: PeerId, joinAsPeerId: PeerId?, initialCall: CachedChannelData.ActiveCall, endCurrentIfAny: Bool) -> JoinGroupCallManagerResult {
|
||||
let begin: () -> Void = { [weak self] in
|
||||
let _ = self?.startGroupCall(accountContext: context, peerId: peerId, initialCall: initialCall).start()
|
||||
let _ = self?.startGroupCall(accountContext: context, peerId: peerId, joinAsPeerId: joinAsPeerId, initialCall: initialCall).start()
|
||||
}
|
||||
|
||||
if let currentGroupCall = self.currentGroupCallValue {
|
||||
@ -660,6 +660,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
private func startGroupCall(
|
||||
accountContext: AccountContext,
|
||||
peerId: PeerId,
|
||||
joinAsPeerId: PeerId?,
|
||||
initialCall: CachedChannelData.ActiveCall,
|
||||
internalId: CallSessionInternalId = CallSessionInternalId()
|
||||
) -> Signal<Bool, NoError> {
|
||||
@ -710,7 +711,8 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
initialCall: initialCall,
|
||||
internalId: internalId,
|
||||
peerId: peerId,
|
||||
peer: nil
|
||||
peer: nil,
|
||||
joinAsPeerId: joinAsPeerId
|
||||
)
|
||||
strongSelf.updateCurrentGroupCall(call)
|
||||
strongSelf.currentGroupCallPromise.set(.single(call))
|
||||
|
@ -70,7 +70,10 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
|
||||
id: call.id,
|
||||
accessHash: call.accessHash,
|
||||
participantCount: 0,
|
||||
clientParams: nil
|
||||
clientParams: nil,
|
||||
streamDcId: nil,
|
||||
title: nil,
|
||||
recordingStartTimestamp: nil
|
||||
),
|
||||
topParticipants: [],
|
||||
participantCount: 0,
|
||||
@ -110,7 +113,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
|
||||
}
|
||||
return GroupCallPanelData(
|
||||
peerId: peerId,
|
||||
info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil),
|
||||
info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil, streamDcId: nil, title: nil, recordingStartTimestamp: nil),
|
||||
topParticipants: topParticipants,
|
||||
participantCount: state.totalCount,
|
||||
activeSpeakers: activeSpeakers,
|
||||
@ -194,7 +197,8 @@ private extension PresentationGroupCallState {
|
||||
canManageCall: false,
|
||||
adminIds: Set(),
|
||||
muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false),
|
||||
defaultParticipantMuteState: nil
|
||||
defaultParticipantMuteState: nil,
|
||||
recordingStartTimestamp: nil
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -333,6 +337,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
private var initialCall: CachedChannelData.ActiveCall?
|
||||
public let internalId: CallSessionInternalId
|
||||
public let peerId: PeerId
|
||||
private let joinAsPeerId: PeerId
|
||||
public let myPeerId: PeerId
|
||||
public let peer: Peer?
|
||||
|
||||
public private(set) var isVideo: Bool
|
||||
@ -502,7 +508,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
initialCall: CachedChannelData.ActiveCall?,
|
||||
internalId: CallSessionInternalId,
|
||||
peerId: PeerId,
|
||||
peer: Peer?
|
||||
peer: Peer?,
|
||||
joinAsPeerId: PeerId?
|
||||
) {
|
||||
self.account = accountContext.account
|
||||
self.accountContext = accountContext
|
||||
@ -514,6 +521,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
self.internalId = internalId
|
||||
self.peerId = peerId
|
||||
self.peer = peer
|
||||
self.joinAsPeerId = joinAsPeerId ?? accountContext.account.peerId
|
||||
self.myPeerId = joinAsPeerId ?? accountContext.account.peerId
|
||||
|
||||
self.temporaryJoinTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
|
||||
@ -632,12 +641,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
if case .left = participantUpdate.participationStatusChange {
|
||||
removedSsrc.append(participantUpdate.ssrc)
|
||||
|
||||
if participantUpdate.peerId == strongSelf.accountContext.account.peerId {
|
||||
if participantUpdate.peerId == strongSelf.joinAsPeerId {
|
||||
if case let .estabilished(_, _, ssrc, _) = strongSelf.internalState, ssrc == participantUpdate.ssrc {
|
||||
strongSelf._canBeRemoved.set(.single(true))
|
||||
}
|
||||
}
|
||||
} else if participantUpdate.peerId == strongSelf.accountContext.account.peerId {
|
||||
} else if participantUpdate.peerId == strongSelf.joinAsPeerId {
|
||||
if case let .estabilished(_, _, ssrc, _) = strongSelf.internalState, ssrc != participantUpdate.ssrc {
|
||||
strongSelf._canBeRemoved.set(.single(true))
|
||||
}
|
||||
@ -647,7 +656,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
addedParticipants.append((participantUpdate.ssrc, participantUpdate.jsonParams))
|
||||
}
|
||||
}
|
||||
case let .call(isTerminated, _):
|
||||
case let .call(isTerminated, _, _, _):
|
||||
if isTerminated {
|
||||
strongSelf._canBeRemoved.set(.single(true))
|
||||
}
|
||||
@ -683,15 +692,15 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
impl.get(account: accountContext.account, peerId: peerId, call: CachedChannelData.ActiveCall(id: initialCall.id, accessHash: initialCall.accessHash))
|
||||
}) {
|
||||
if let participantsContext = temporaryParticipantsContext.context.participantsContext {
|
||||
let accountPeerId = self.accountContext.account.peerId
|
||||
let accountPeer = self.accountContext.account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(accountPeerId)
|
||||
let myPeerId = self.joinAsPeerId
|
||||
let myPeer = self.accountContext.account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(myPeerId)
|
||||
}
|
||||
self.participantsContextStateDisposable.set(combineLatest(queue: .mainQueue(),
|
||||
accountPeer,
|
||||
myPeer,
|
||||
participantsContext.state,
|
||||
participantsContext.activeSpeakers
|
||||
).start(next: { [weak self] accountPeer, state, activeSpeakers in
|
||||
).start(next: { [weak self] myPeer, state, activeSpeakers in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -710,17 +719,18 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
var participants = state.participants
|
||||
|
||||
if !participants.contains(where: { $0.peer.id == accountPeerId }) {
|
||||
if let accountPeer = accountPeer {
|
||||
if !participants.contains(where: { $0.peer.id == myPeerId }) {
|
||||
if let myPeer = myPeer {
|
||||
participants.append(GroupCallParticipantsContext.Participant(
|
||||
peer: accountPeer,
|
||||
peer: myPeer,
|
||||
ssrc: 0,
|
||||
jsonParams: nil,
|
||||
joinTimestamp: strongSelf.temporaryJoinTimestamp,
|
||||
activityTimestamp: nil,
|
||||
activityRank: nil,
|
||||
muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false),
|
||||
volume: nil
|
||||
volume: nil,
|
||||
about: nil
|
||||
))
|
||||
participants.sort()
|
||||
}
|
||||
@ -845,7 +855,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
strongSelf.maybeRequestParticipants(ssrcs: ssrcs)
|
||||
}
|
||||
}, demoAudioStream: self.accountContext.sharedContext.immediateExperimentalUISettings.demoAudioStream)
|
||||
}, audioStreamData: OngoingGroupCallContext.AudioStreamData(account: self.accountContext.account, callId: callInfo.id, accessHash: callInfo.accessHash, datacenterId: callInfo.streamDcId.flatMap(Int.init)))
|
||||
self.incomingVideoSourcePromise.set(callContext.videoSources
|
||||
|> deliverOnMainQueue
|
||||
|> map { [weak self] sources -> [PeerId: UInt32] in
|
||||
@ -878,6 +888,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
strongSelf.requestDisposable.set((joinGroupCall(
|
||||
account: strongSelf.account,
|
||||
peerId: strongSelf.peerId,
|
||||
joinAs: strongSelf.joinAsPeerId == strongSelf.account.peerId ? nil : strongSelf.joinAsPeerId,
|
||||
callId: callInfo.id,
|
||||
accessHash: callInfo.accessHash,
|
||||
preferMuted: true,
|
||||
@ -984,7 +995,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
let ssrcValue: UInt32
|
||||
switch ssrcKey {
|
||||
case .local:
|
||||
peerId = strongSelf.accountContext.account.peerId
|
||||
peerId = strongSelf.joinAsPeerId
|
||||
ssrcValue = 0
|
||||
case let .source(ssrc):
|
||||
peerId = strongSelf.ssrcMapping[ssrc]
|
||||
@ -1027,6 +1038,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
if self.stateValue.canManageCall && initialState.defaultParticipantsAreMuted.canChange {
|
||||
self.stateValue.defaultParticipantMuteState = initialState.defaultParticipantsAreMuted.isMuted ? .muted : .unmuted
|
||||
}
|
||||
if self.stateValue.recordingStartTimestamp != initialState.recordingStartTimestamp {
|
||||
self.stateValue.recordingStartTimestamp = initialState.recordingStartTimestamp
|
||||
}
|
||||
|
||||
let accountContext = self.accountContext
|
||||
let peerId = self.peerId
|
||||
@ -1115,7 +1129,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
strongSelf.ssrcMapping[participant.ssrc] = participant.peer.id
|
||||
|
||||
if participant.peer.id == strongSelf.accountContext.account.peerId {
|
||||
if participant.peer.id == strongSelf.joinAsPeerId {
|
||||
if let muteState = participant.muteState {
|
||||
if muteState.canUnmute {
|
||||
switch strongSelf.isMutedValue {
|
||||
@ -1162,6 +1176,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
if (state.isCreator || strongSelf.stateValue.adminIds.contains(strongSelf.accountContext.account.peerId)) && state.defaultParticipantsAreMuted.canChange {
|
||||
strongSelf.stateValue.defaultParticipantMuteState = state.defaultParticipantsAreMuted.isMuted ? .muted : .unmuted
|
||||
}
|
||||
strongSelf.stateValue.recordingStartTimestamp = state.recordingStartTimestamp
|
||||
|
||||
strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState(
|
||||
participantCount: state.totalCount,
|
||||
@ -1385,11 +1400,11 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
case let .muted(isPushToTalkActive):
|
||||
isEffectivelyMuted = !isPushToTalkActive
|
||||
isVisuallyMuted = true
|
||||
let _ = self.updateMuteState(peerId: self.accountContext.account.peerId, isMuted: true)
|
||||
let _ = self.updateMuteState(peerId: self.joinAsPeerId, isMuted: true)
|
||||
case .unmuted:
|
||||
isEffectivelyMuted = false
|
||||
isVisuallyMuted = false
|
||||
let _ = self.updateMuteState(peerId: self.accountContext.account.peerId, isMuted: false)
|
||||
let _ = self.updateMuteState(peerId: self.joinAsPeerId, isMuted: false)
|
||||
}
|
||||
self.callContext?.setIsMuted(isEffectivelyMuted)
|
||||
|
||||
@ -1516,7 +1531,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
let canThenUnmute: Bool
|
||||
if isMuted {
|
||||
var mutedByYou = false
|
||||
if peerId == self.accountContext.account.peerId {
|
||||
if peerId == self.joinAsPeerId {
|
||||
canThenUnmute = true
|
||||
} else if self.stateValue.canManageCall {
|
||||
if self.stateValue.adminIds.contains(peerId) {
|
||||
@ -1535,7 +1550,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, volume: nil)
|
||||
return muteState
|
||||
} else {
|
||||
if peerId == self.accountContext.account.peerId {
|
||||
if peerId == self.joinAsPeerId {
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: nil)
|
||||
return nil
|
||||
} else if self.stateValue.canManageCall || self.stateValue.adminIds.contains(self.accountContext.account.peerId) {
|
||||
@ -1550,6 +1565,16 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
}
|
||||
|
||||
public func setShouldBeRecording(_ shouldBeRecording: Bool) {
|
||||
if !self.stateValue.canManageCall {
|
||||
return
|
||||
}
|
||||
if (self.stateValue.recordingStartTimestamp != nil) == shouldBeRecording {
|
||||
return
|
||||
}
|
||||
self.participantsContext?.updateShouldBeRecording(shouldBeRecording)
|
||||
}
|
||||
|
||||
private func requestCall() {
|
||||
self.callContext?.stop()
|
||||
self.callContext = nil
|
||||
|
@ -370,6 +370,7 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
|
||||
var peer: Peer
|
||||
var myPeerId: PeerId
|
||||
var ssrc: UInt32
|
||||
var presence: TelegramUserPresence?
|
||||
var activityTimestamp: Int32
|
||||
@ -387,6 +388,9 @@ public final class VoiceChatController: ViewController {
|
||||
if !lhs.peer.isEqual(rhs.peer) {
|
||||
return false
|
||||
}
|
||||
if lhs.myPeerId != rhs.myPeerId {
|
||||
return false
|
||||
}
|
||||
if lhs.ssrc != rhs.ssrc {
|
||||
return false
|
||||
}
|
||||
@ -540,7 +544,7 @@ public final class VoiceChatController: ViewController {
|
||||
|
||||
let revealOptions: [VoiceChatParticipantItem.RevealOption] = []
|
||||
|
||||
return VoiceChatParticipantItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: peer, ssrc: peerEntry.ssrc, presence: peerEntry.presence, text: text, icon: icon, enabled: true, selectable: peer.id != context.account.peerId || peerEntry.canManageCall, getAudioLevel: { return interaction.getAudioLevel(peer.id) }, getVideo: {
|
||||
return VoiceChatParticipantItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: peer, ssrc: peerEntry.ssrc, presence: peerEntry.presence, text: text, icon: icon, enabled: true, selectable: peer.id != peerEntry.myPeerId || peerEntry.canManageCall, getAudioLevel: { return interaction.getAudioLevel(peer.id) }, getVideo: {
|
||||
return interaction.getPeerVideo(peerEntry.ssrc)
|
||||
}, revealOptions: revealOptions, revealed: peerEntry.revealed, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
interaction.setPeerIdWithRevealedOptions(peerId, fromPeerId)
|
||||
@ -608,7 +612,6 @@ public final class VoiceChatController: ViewController {
|
||||
private var currentSpeakingPeers: Set<PeerId>?
|
||||
private var currentContentOffset: CGFloat?
|
||||
private var ignoreScrolling = false
|
||||
private var accountPeer: Peer?
|
||||
private var currentAudioButtonColor: UIColor?
|
||||
|
||||
private var currentEntries: [ListEntry] = []
|
||||
@ -824,7 +827,7 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
if peer.id == strongSelf.context.account.peerId {
|
||||
if peer.id == strongSelf.call.myPeerId {
|
||||
return
|
||||
}
|
||||
if let participant = participant {
|
||||
@ -1047,7 +1050,7 @@ public final class VoiceChatController: ViewController {
|
||||
f(.default)
|
||||
})))*/
|
||||
|
||||
if peer.id != strongSelf.context.account.peerId {
|
||||
if peer.id != strongSelf.call.myPeerId {
|
||||
if let callState = strongSelf.callState, (callState.canManageCall || callState.adminIds.contains(strongSelf.context.account.peerId)) {
|
||||
if callState.adminIds.contains(peer.id) {
|
||||
if let _ = muteState {
|
||||
@ -1296,8 +1299,8 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
})
|
||||
|
||||
self.peerViewDisposable = (combineLatest(self.context.account.viewTracker.peerView(self.call.peerId), self.context.account.postbox.loadedPeerWithId(self.context.account.peerId))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] view, accountPeer in
|
||||
self.peerViewDisposable = (self.context.account.viewTracker.peerView(self.call.peerId)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] view in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -1307,7 +1310,6 @@ public final class VoiceChatController: ViewController {
|
||||
strongSelf.currentTitle = peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)
|
||||
}
|
||||
if !strongSelf.didSetDataReady {
|
||||
strongSelf.accountPeer = accountPeer
|
||||
strongSelf.updateMembers(muteState: strongSelf.effectiveMuteState, callMembers: strongSelf.currentCallMembers ?? ([], nil), invitedPeers: strongSelf.currentInvitedPeers ?? [], speakingPeers: strongSelf.currentSpeakingPeers ?? Set())
|
||||
|
||||
strongSelf.didSetDataReady = true
|
||||
@ -1337,7 +1339,7 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
var levels = levels
|
||||
if strongSelf.effectiveMuteState != nil {
|
||||
levels = levels.filter { $0.0 != strongSelf.context.account.peerId }
|
||||
levels = levels.filter { $0.0 != strongSelf.call.myPeerId }
|
||||
}
|
||||
|
||||
var maxLevelWithVideo: (PeerId, UInt32, Float)?
|
||||
@ -1456,6 +1458,15 @@ public final class VoiceChatController: ViewController {
|
||||
})])
|
||||
strongSelf.controller?.present(alert, in: .window(.root))
|
||||
})))
|
||||
|
||||
//TODO:localize
|
||||
items.append(.action(ContextMenuActionItem(text: callState.recordingStartTimestamp == nil ? "Begin Recording" : "End Recording", textColor: .destructive, icon: { _ in
|
||||
return nil
|
||||
}, action: { _, f in
|
||||
f(.dismissWithoutContent)
|
||||
|
||||
strongSelf.call.setShouldBeRecording(callState.recordingStartTimestamp == nil ? true : false)
|
||||
})))
|
||||
}
|
||||
|
||||
if items.isEmpty {
|
||||
@ -1747,7 +1758,7 @@ public final class VoiceChatController: ViewController {
|
||||
self.call.setIsMuted(action: .muted(isPushToTalkActive: false))
|
||||
}
|
||||
|
||||
self.itemInteraction?.updateAudioLevels([(self.context.account.peerId, 0, 0.0, false)], reset: true)
|
||||
self.itemInteraction?.updateAudioLevels([(self.call.myPeerId, 0, 0.0, false)], reset: true)
|
||||
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.3, curve: .spring))
|
||||
@ -2497,7 +2508,7 @@ public final class VoiceChatController: ViewController {
|
||||
|
||||
let memberState: PeerEntry.State
|
||||
var memberMuteState: GroupCallParticipantsContext.Participant.MuteState?
|
||||
if member.peer.id == self.context.account.peerId {
|
||||
if member.peer.id == self.call.myPeerId {
|
||||
if muteState == nil {
|
||||
memberState = speakingPeers.contains(member.peer.id) ? .speaking : .listening
|
||||
} else {
|
||||
@ -2511,6 +2522,7 @@ public final class VoiceChatController: ViewController {
|
||||
|
||||
entries.append(.peer(PeerEntry(
|
||||
peer: member.peer,
|
||||
myPeerId: self.call.myPeerId,
|
||||
ssrc: member.ssrc,
|
||||
presence: nil,
|
||||
activityTimestamp: Int32.max - 1 - index,
|
||||
@ -2522,19 +2534,6 @@ public final class VoiceChatController: ViewController {
|
||||
index += 1
|
||||
}
|
||||
|
||||
if let accountPeer = self.accountPeer, !processedPeerIds.contains(accountPeer.id) {
|
||||
entries.insert(.peer(PeerEntry(
|
||||
peer: accountPeer,
|
||||
ssrc: 0,
|
||||
presence: nil,
|
||||
activityTimestamp: Int32.max - 1 - index,
|
||||
state: .listening,
|
||||
muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false),
|
||||
canManageCall: self.callState?.canManageCall ?? false,
|
||||
volume: nil
|
||||
)), at: 1)
|
||||
}
|
||||
|
||||
for peer in invitedPeers {
|
||||
if processedPeerIds.contains(peer.id) {
|
||||
continue
|
||||
@ -2543,6 +2542,7 @@ public final class VoiceChatController: ViewController {
|
||||
|
||||
entries.append(.peer(PeerEntry(
|
||||
peer: peer,
|
||||
myPeerId: self.call.myPeerId,
|
||||
ssrc: 0,
|
||||
presence: nil,
|
||||
activityTimestamp: Int32.max - 1 - index,
|
||||
|
@ -2987,13 +2987,13 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
||||
})
|
||||
|
||||
switch call {
|
||||
case let .groupCall(flags, _, _, _, _, _):
|
||||
case let .groupCall(flags, _, _, _, _, title, streamDcId, recordStartDate, _):
|
||||
let isMuted = (flags & (1 << 1)) != 0
|
||||
let canChange = (flags & (1 << 2)) != 0
|
||||
let defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: canChange)
|
||||
updatedGroupCallParticipants.append((
|
||||
info.id,
|
||||
.call(isTerminated: false, defaultParticipantsAreMuted: defaultParticipantsAreMuted)
|
||||
.call(isTerminated: false, defaultParticipantsAreMuted: defaultParticipantsAreMuted, title: title, recordingStartTimestamp: recordStartDate)
|
||||
))
|
||||
default:
|
||||
break
|
||||
@ -3002,7 +3002,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
||||
case let .groupCallDiscarded(callId, _, _):
|
||||
updatedGroupCallParticipants.append((
|
||||
callId,
|
||||
.call(isTerminated: true, defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false))
|
||||
.call(isTerminated: true, defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false), title: nil, recordingStartTimestamp: nil)
|
||||
))
|
||||
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
|
@ -188,10 +188,21 @@ public func checkPublicChannelCreationAvailability(account: Account, location: B
|
||||
}
|
||||
}
|
||||
|
||||
public func adminedPublicChannels(account: Account, location: Bool = false) -> Signal<[Peer], NoError> {
|
||||
public enum AdminedPublicChannelsScope {
|
||||
case all
|
||||
case forLocation
|
||||
case forVoiceChat
|
||||
}
|
||||
|
||||
public func adminedPublicChannels(account: Account, scope: AdminedPublicChannelsScope = .all) -> Signal<[Peer], NoError> {
|
||||
var flags: Int32 = 0
|
||||
if location {
|
||||
switch scope {
|
||||
case .all:
|
||||
break
|
||||
case .forLocation:
|
||||
flags |= (1 << 0)
|
||||
case .forVoiceChat:
|
||||
flags |= (1 << 2)
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.channels.getAdminedPublicChannels(flags: flags))
|
||||
|
@ -24,7 +24,7 @@ public struct BotPaymentInvoiceFields: OptionSet {
|
||||
public static let flexibleShipping = BotPaymentInvoiceFields(rawValue: 1 << 4)
|
||||
}
|
||||
|
||||
public struct BotPaymentPrice {
|
||||
public struct BotPaymentPrice : Equatable {
|
||||
public let label: String
|
||||
public let amount: Int64
|
||||
|
||||
@ -34,14 +34,14 @@ public struct BotPaymentPrice {
|
||||
}
|
||||
}
|
||||
|
||||
public struct BotPaymentInvoice {
|
||||
public struct BotPaymentInvoice : Equatable {
|
||||
public let isTest: Bool
|
||||
public let requestedFields: BotPaymentInvoiceFields
|
||||
public let currency: String
|
||||
public let prices: [BotPaymentPrice]
|
||||
}
|
||||
|
||||
public struct BotPaymentNativeProvider {
|
||||
public struct BotPaymentNativeProvider : Equatable {
|
||||
public let name: String
|
||||
public let params: String
|
||||
}
|
||||
@ -62,28 +62,6 @@ public struct BotPaymentShippingAddress: Equatable {
|
||||
self.countryIso2 = countryIso2
|
||||
self.postCode = postCode
|
||||
}
|
||||
|
||||
public static func ==(lhs: BotPaymentShippingAddress, rhs: BotPaymentShippingAddress) -> Bool {
|
||||
if lhs.streetLine1 != rhs.streetLine1 {
|
||||
return false
|
||||
}
|
||||
if lhs.streetLine2 != rhs.streetLine2 {
|
||||
return false
|
||||
}
|
||||
if lhs.city != rhs.city {
|
||||
return false
|
||||
}
|
||||
if lhs.state != rhs.state {
|
||||
return false
|
||||
}
|
||||
if lhs.countryIso2 != rhs.countryIso2 {
|
||||
return false
|
||||
}
|
||||
if lhs.postCode != rhs.postCode {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public struct BotPaymentRequestedInfo: Equatable {
|
||||
@ -98,22 +76,6 @@ public struct BotPaymentRequestedInfo: Equatable {
|
||||
self.email = email
|
||||
self.shippingAddress = shippingAddress
|
||||
}
|
||||
|
||||
public static func ==(lhs: BotPaymentRequestedInfo, rhs: BotPaymentRequestedInfo) -> Bool {
|
||||
if lhs.name != rhs.name {
|
||||
return false
|
||||
}
|
||||
if lhs.phone != rhs.phone {
|
||||
return false
|
||||
}
|
||||
if lhs.email != rhs.email {
|
||||
return false
|
||||
}
|
||||
if lhs.shippingAddress != rhs.shippingAddress {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public enum BotPaymentSavedCredentials: Equatable {
|
||||
@ -131,7 +93,7 @@ public enum BotPaymentSavedCredentials: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct BotPaymentForm {
|
||||
public struct BotPaymentForm : Equatable {
|
||||
public let canSaveCredentials: Bool
|
||||
public let passwordMissing: Bool
|
||||
public let invoice: BotPaymentInvoice
|
||||
@ -243,13 +205,13 @@ public enum ValidateBotPaymentFormError {
|
||||
case phoneInvalid
|
||||
}
|
||||
|
||||
public struct BotPaymentShippingOption {
|
||||
public struct BotPaymentShippingOption : Equatable {
|
||||
public let id: String
|
||||
public let title: String
|
||||
public let prices: [BotPaymentPrice]
|
||||
}
|
||||
|
||||
public struct BotPaymentValidatedFormInfo {
|
||||
public struct BotPaymentValidatedFormInfo : Equatable {
|
||||
public let id: String?
|
||||
public let shippingOptions: [BotPaymentShippingOption]?
|
||||
}
|
||||
@ -379,7 +341,7 @@ public func sendBotPaymentForm(account: Account, messageId: MessageId, validated
|
||||
}
|
||||
}
|
||||
|
||||
public struct BotPaymentReceipt {
|
||||
public struct BotPaymentReceipt : Equatable {
|
||||
public let invoice: BotPaymentInvoice
|
||||
public let info: BotPaymentRequestedInfo?
|
||||
public let shippingOption: BotPaymentShippingOption?
|
||||
|
@ -325,7 +325,7 @@ class Download: NSObject, MTRequestMessageServiceDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func rawRequest(_ data: (FunctionDescription, Buffer, (Buffer) -> Any?)) -> Signal<Any, MTRpcError> {
|
||||
func rawRequest(_ data: (FunctionDescription, Buffer, (Buffer) -> Any?), automaticFloodWait: Bool = true) -> Signal<Any, MTRpcError> {
|
||||
let requestService = self.requestService
|
||||
return Signal { subscriber in
|
||||
let request = MTRequest()
|
||||
@ -340,6 +340,12 @@ class Download: NSObject, MTRequestMessageServiceDelegate {
|
||||
request.dependsOnPasswordEntry = false
|
||||
|
||||
request.shouldContinueExecutionWithErrorContext = { errorContext in
|
||||
guard let errorContext = errorContext else {
|
||||
return true
|
||||
}
|
||||
if errorContext.floodWaitSeconds > 0 && !automaticFloodWait {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -9,17 +9,26 @@ public struct GroupCallInfo: Equatable {
|
||||
public var accessHash: Int64
|
||||
public var participantCount: Int
|
||||
public var clientParams: String?
|
||||
public var streamDcId: Int32?
|
||||
public var title: String?
|
||||
public var recordingStartTimestamp: Int32?
|
||||
|
||||
public init(
|
||||
id: Int64,
|
||||
accessHash: Int64,
|
||||
participantCount: Int,
|
||||
clientParams: String?
|
||||
clientParams: String?,
|
||||
streamDcId: Int32?,
|
||||
title: String?,
|
||||
recordingStartTimestamp: Int32?
|
||||
) {
|
||||
self.id = id
|
||||
self.accessHash = accessHash
|
||||
self.participantCount = participantCount
|
||||
self.clientParams = clientParams
|
||||
self.streamDcId = streamDcId
|
||||
self.title = title
|
||||
self.recordingStartTimestamp = recordingStartTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +40,7 @@ public struct GroupCallSummary: Equatable {
|
||||
extension GroupCallInfo {
|
||||
init?(_ call: Api.GroupCall) {
|
||||
switch call {
|
||||
case let .groupCall(_, id, accessHash, participantCount, params, _):
|
||||
case let .groupCall(_, id, accessHash, participantCount, params, title, recordStartDate, streamDcId, _):
|
||||
var clientParams: String?
|
||||
if let params = params {
|
||||
switch params {
|
||||
@ -43,7 +52,10 @@ extension GroupCallInfo {
|
||||
id: id,
|
||||
accessHash: accessHash,
|
||||
participantCount: Int(participantCount),
|
||||
clientParams: clientParams
|
||||
clientParams: clientParams,
|
||||
streamDcId: streamDcId,
|
||||
title: title,
|
||||
recordingStartTimestamp: recordStartDate
|
||||
)
|
||||
case .groupCallDiscarded:
|
||||
return nil
|
||||
@ -62,7 +74,7 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
|
||||
}
|
||||
|> mapToSignal { result -> Signal<GroupCallSummary?, GetCurrentGroupCallError> in
|
||||
switch result {
|
||||
case let .groupCall(call, participants, _, users):
|
||||
case let .groupCall(call, participants, _, chats, users):
|
||||
return account.postbox.transaction { transaction -> GroupCallSummary? in
|
||||
guard let info = GroupCallInfo(call) else {
|
||||
return nil
|
||||
@ -79,6 +91,12 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
|
||||
}
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
@ -88,8 +106,18 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
|
||||
|
||||
loop: for participant in participants {
|
||||
switch participant {
|
||||
case let .groupCallParticipant(flags, userId, date, activeDate, source, volume):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about):
|
||||
|
||||
let peerId: PeerId
|
||||
switch apiPeerId {
|
||||
case let .peerUser(userId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .peerChat(chatId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
|
||||
case let .peerChannel(channelId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||
}
|
||||
|
||||
let ssrc = UInt32(bitPattern: source)
|
||||
guard let peer = transaction.getPeer(peerId) else {
|
||||
continue loop
|
||||
@ -118,7 +146,8 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
activityRank: nil,
|
||||
muteState: muteState,
|
||||
volume: volume
|
||||
volume: volume,
|
||||
about: about
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -139,17 +168,26 @@ public enum CreateGroupCallError {
|
||||
case anonymousNotAllowed
|
||||
}
|
||||
|
||||
public func createGroupCall(account: Account, peerId: PeerId) -> Signal<GroupCallInfo, CreateGroupCallError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
public func createGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?) -> Signal<GroupCallInfo, CreateGroupCallError> {
|
||||
return account.postbox.transaction { transaction -> (Api.InputPeer?, Api.InputPeer?) in
|
||||
let callPeer = transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
if let joinAs = joinAs {
|
||||
return (callPeer, transaction.getPeer(joinAs).flatMap(apiInputPeer))
|
||||
} else {
|
||||
return (callPeer, nil)
|
||||
}
|
||||
}
|
||||
|> castError(CreateGroupCallError.self)
|
||||
|> mapToSignal { inputPeer -> Signal<GroupCallInfo, CreateGroupCallError> in
|
||||
|> mapToSignal { (inputPeer, inputJoinAs) -> Signal<GroupCallInfo, CreateGroupCallError> in
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.phone.createGroupCall(peer: inputPeer, randomId: Int32.random(in: Int32.min ... Int32.max)))
|
||||
var flags: Int32 = 0
|
||||
if let _ = inputJoinAs {
|
||||
flags |= (1 << 0)
|
||||
}
|
||||
return account.network.request(Api.functions.phone.createGroupCall(flags: flags, peer: inputPeer, joinAs: inputJoinAs, randomId: Int32.random(in: Int32.min ... Int32.max)))
|
||||
|> mapError { error -> CreateGroupCallError in
|
||||
if error.errorDescription == "ANONYMOUS_CALLS_DISABLED" {
|
||||
return .anonymousNotAllowed
|
||||
@ -209,7 +247,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
|
||||
let nextParticipantsFetchOffset: String?
|
||||
|
||||
switch result {
|
||||
case let .groupParticipants(count, participants, nextOffset, users, apiVersion):
|
||||
case let .groupParticipants(count, participants, nextOffset, chats, users, apiVersion):
|
||||
totalCount = Int(count)
|
||||
version = apiVersion
|
||||
|
||||
@ -230,6 +268,12 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
|
||||
}
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
@ -237,8 +281,17 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
|
||||
|
||||
loop: for participant in participants {
|
||||
switch participant {
|
||||
case let .groupCallParticipant(flags, userId, date, activeDate, source, volume):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about):
|
||||
|
||||
let peerId: PeerId
|
||||
switch apiPeerId {
|
||||
case let .peerUser(userId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .peerChat(chatId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
|
||||
case let .peerChannel(channelId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||
}
|
||||
let ssrc = UInt32(bitPattern: source)
|
||||
guard let peer = transaction.getPeer(peerId) else {
|
||||
continue loop
|
||||
@ -267,7 +320,8 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
activityRank: nil,
|
||||
muteState: muteState,
|
||||
volume: volume
|
||||
volume: volume,
|
||||
about: about
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -281,6 +335,8 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
|
||||
adminIds: Set(),
|
||||
isCreator: false,
|
||||
defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false),
|
||||
recordingStartTimestamp: nil,
|
||||
title: nil,
|
||||
totalCount: totalCount,
|
||||
version: version
|
||||
)
|
||||
@ -300,184 +356,210 @@ public struct JoinGroupCallResult {
|
||||
public var state: GroupCallParticipantsContext.State
|
||||
}
|
||||
|
||||
public func joinGroupCall(account: Account, peerId: PeerId, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String) -> Signal<JoinGroupCallResult, JoinGroupCallError> {
|
||||
var flags: Int32 = 0
|
||||
if preferMuted {
|
||||
flags |= (1 << 0)
|
||||
}
|
||||
return account.network.request(Api.functions.phone.joinGroupCall(flags: flags, call: .inputGroupCall(id: callId, accessHash: accessHash), params: .dataJSON(data: joinPayload)))
|
||||
|> mapError { error -> JoinGroupCallError in
|
||||
if error.errorDescription == "GROUPCALL_ANONYMOUS_FORBIDDEN" {
|
||||
return .anonymousNotAllowed
|
||||
} else if error.errorDescription == "GROUPCALL_PARTICIPANTS_TOO_MUCH" {
|
||||
return .tooManyParticipants
|
||||
}
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<JoinGroupCallResult, JoinGroupCallError> in
|
||||
let admins: Signal<(Set<PeerId>, [Api.User]), JoinGroupCallError>
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
admins = account.postbox.transaction { transaction -> Api.InputChannel? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputChannel)
|
||||
}
|
||||
|> castError(JoinGroupCallError.self)
|
||||
|> mapToSignal { inputChannel -> Signal<Api.channels.ChannelParticipants, JoinGroupCallError> in
|
||||
guard let inputChannel = inputChannel else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 100, hash: 0))
|
||||
|> mapError { _ -> JoinGroupCallError in
|
||||
return .generic
|
||||
}
|
||||
}
|
||||
|> map { admins -> (Set<PeerId>, [Api.User]) in
|
||||
var adminIds = Set<PeerId>()
|
||||
var apiUsers: [Api.User] = []
|
||||
|
||||
switch admins {
|
||||
case let .channelParticipants(_, participants, users):
|
||||
apiUsers.append(contentsOf: users)
|
||||
|
||||
for participant in participants {
|
||||
let parsedParticipant = ChannelParticipant(apiParticipant: participant)
|
||||
switch parsedParticipant {
|
||||
case .creator:
|
||||
adminIds.insert(parsedParticipant.peerId)
|
||||
case let .member(_, _, adminInfo, _, _):
|
||||
if let adminInfo = adminInfo, adminInfo.rights.rights.contains(.canManageCalls) {
|
||||
adminIds.insert(parsedParticipant.peerId)
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return (adminIds, apiUsers)
|
||||
}
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
admins = account.postbox.transaction { transaction -> (Set<PeerId>, [Api.User]) in
|
||||
var result = Set<PeerId>()
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedGroupData {
|
||||
if let participants = cachedData.participants {
|
||||
for participant in participants.participants {
|
||||
if case .creator = participant {
|
||||
result.insert(participant.peerId)
|
||||
} else if case .admin = participant {
|
||||
result.insert(participant.peerId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (result, [])
|
||||
}
|
||||
|> castError(JoinGroupCallError.self)
|
||||
public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String) -> Signal<JoinGroupCallResult, JoinGroupCallError> {
|
||||
|
||||
return account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
if let joinAs = joinAs {
|
||||
return transaction.getPeer(joinAs).flatMap(apiInputPeer)
|
||||
} else {
|
||||
admins = .fail(.generic)
|
||||
return .inputPeerSelf
|
||||
}
|
||||
}
|
||||
|> castError(JoinGroupCallError.self)
|
||||
|> mapToSignal { inputJoinAs in
|
||||
|
||||
var flags: Int32 = 0
|
||||
if preferMuted {
|
||||
flags |= (1 << 0)
|
||||
}
|
||||
|
||||
let peer = account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
if let _ = inputJoinAs {
|
||||
flags |= (1 << 1)
|
||||
}
|
||||
|> castError(JoinGroupCallError.self)
|
||||
|
||||
return combineLatest(
|
||||
account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash)))
|
||||
|> mapError { _ -> JoinGroupCallError in
|
||||
return .generic
|
||||
},
|
||||
getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", ssrcs: [], limit: 100)
|
||||
|> mapError { _ -> JoinGroupCallError in
|
||||
return .generic
|
||||
},
|
||||
admins,
|
||||
peer
|
||||
)
|
||||
|> mapToSignal { result, state, admins, peer -> Signal<JoinGroupCallResult, JoinGroupCallError> in
|
||||
guard let peer = peer else {
|
||||
return .fail(.generic)
|
||||
return account.network.request(Api.functions.phone.joinGroupCall(flags: flags, call: .inputGroupCall(id: callId, accessHash: accessHash), joinAs: inputJoinAs, params: .dataJSON(data: joinPayload)))
|
||||
|> mapError { error -> JoinGroupCallError in
|
||||
if error.errorDescription == "GROUPCALL_ANONYMOUS_FORBIDDEN" {
|
||||
return .anonymousNotAllowed
|
||||
} else if error.errorDescription == "GROUPCALL_PARTICIPANTS_TOO_MUCH" {
|
||||
return .tooManyParticipants
|
||||
}
|
||||
|
||||
var state = state
|
||||
if let channel = peer as? TelegramChannel {
|
||||
state.isCreator = channel.flags.contains(.isCreator)
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if case .creator = group.role {
|
||||
state.isCreator = true
|
||||
} else {
|
||||
state.isCreator = false
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<JoinGroupCallResult, JoinGroupCallError> in
|
||||
let admins: Signal<(Set<PeerId>, [Api.User]), JoinGroupCallError>
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
admins = account.postbox.transaction { transaction -> Api.InputChannel? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputChannel)
|
||||
}
|
||||
}
|
||||
|
||||
account.stateManager.addUpdates(updates)
|
||||
|
||||
var maybeParsedCall: GroupCallInfo?
|
||||
loop: for update in updates.allUpdates {
|
||||
switch update {
|
||||
case let .updateGroupCall(_, call):
|
||||
maybeParsedCall = GroupCallInfo(call)
|
||||
|> castError(JoinGroupCallError.self)
|
||||
|> mapToSignal { inputChannel -> Signal<Api.channels.ChannelParticipants, JoinGroupCallError> in
|
||||
guard let inputChannel = inputChannel else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
switch call {
|
||||
case let .groupCall(flags, _, _, _, _, _):
|
||||
let isMuted = (flags & (1 << 1)) != 0
|
||||
let canChange = (flags & (1 << 2)) != 0
|
||||
state.defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: canChange)
|
||||
return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 100, hash: 0))
|
||||
|> mapError { _ -> JoinGroupCallError in
|
||||
return .generic
|
||||
}
|
||||
}
|
||||
|> map { admins -> (Set<PeerId>, [Api.User]) in
|
||||
var adminIds = Set<PeerId>()
|
||||
var apiUsers: [Api.User] = []
|
||||
|
||||
switch admins {
|
||||
case let .channelParticipants(_, participants, users):
|
||||
apiUsers.append(contentsOf: users)
|
||||
|
||||
for participant in participants {
|
||||
let parsedParticipant = ChannelParticipant(apiParticipant: participant)
|
||||
switch parsedParticipant {
|
||||
case .creator:
|
||||
adminIds.insert(parsedParticipant.peerId)
|
||||
case let .member(_, _, adminInfo, _, _):
|
||||
if let adminInfo = adminInfo, adminInfo.rights.rights.contains(.canManageCalls) {
|
||||
adminIds.insert(parsedParticipant.peerId)
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
break loop
|
||||
default:
|
||||
break
|
||||
return (adminIds, apiUsers)
|
||||
}
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
admins = account.postbox.transaction { transaction -> (Set<PeerId>, [Api.User]) in
|
||||
var result = Set<PeerId>()
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedGroupData {
|
||||
if let participants = cachedData.participants {
|
||||
for participant in participants.participants {
|
||||
if case .creator = participant {
|
||||
result.insert(participant.peerId)
|
||||
} else if case .admin = participant {
|
||||
result.insert(participant.peerId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (result, [])
|
||||
}
|
||||
|> castError(JoinGroupCallError.self)
|
||||
} else {
|
||||
admins = .fail(.generic)
|
||||
}
|
||||
|
||||
guard let parsedCall = maybeParsedCall else {
|
||||
return .fail(.generic)
|
||||
let peer = account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
|> castError(JoinGroupCallError.self)
|
||||
|
||||
var apiUsers: [Api.User] = []
|
||||
|
||||
let (adminIds, adminUsers) = admins
|
||||
apiUsers.append(contentsOf: adminUsers)
|
||||
|
||||
state.adminIds = adminIds
|
||||
|
||||
switch result {
|
||||
case let .groupCall(call, _, _, users):
|
||||
guard let _ = GroupCallInfo(call) else {
|
||||
return combineLatest(
|
||||
account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash)))
|
||||
|> mapError { _ -> JoinGroupCallError in
|
||||
return .generic
|
||||
},
|
||||
getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", ssrcs: [], limit: 100)
|
||||
|> mapError { _ -> JoinGroupCallError in
|
||||
return .generic
|
||||
},
|
||||
admins,
|
||||
peer
|
||||
)
|
||||
|> mapToSignal { result, state, admins, peer -> Signal<JoinGroupCallResult, JoinGroupCallError> in
|
||||
guard let peer = peer else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
apiUsers.append(contentsOf: users)
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
|
||||
for user in apiUsers {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
if let presence = TelegramUserPresence(apiUser: user) {
|
||||
peerPresences[telegramUser.id] = presence
|
||||
var state = state
|
||||
if let channel = peer as? TelegramChannel {
|
||||
state.isCreator = channel.flags.contains(.isCreator)
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if case .creator = group.role {
|
||||
state.isCreator = true
|
||||
} else {
|
||||
state.isCreator = false
|
||||
}
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> JoinGroupCallResult in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
|
||||
return JoinGroupCallResult(
|
||||
callInfo: parsedCall,
|
||||
state: state
|
||||
)
|
||||
account.stateManager.addUpdates(updates)
|
||||
|
||||
var maybeParsedCall: GroupCallInfo?
|
||||
loop: for update in updates.allUpdates {
|
||||
switch update {
|
||||
case let .updateGroupCall(_, call):
|
||||
maybeParsedCall = GroupCallInfo(call)
|
||||
|
||||
switch call {
|
||||
case let .groupCall(flags, _, _, _, _, title, streamDcId, recordStartDate, _):
|
||||
let isMuted = (flags & (1 << 1)) != 0
|
||||
let canChange = (flags & (1 << 2)) != 0
|
||||
state.defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: canChange)
|
||||
state.title = title
|
||||
state.recordingStartTimestamp = recordStartDate
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
break loop
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
guard let parsedCall = maybeParsedCall else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
var apiUsers: [Api.User] = []
|
||||
|
||||
let (adminIds, adminUsers) = admins
|
||||
apiUsers.append(contentsOf: adminUsers)
|
||||
|
||||
state.adminIds = adminIds
|
||||
|
||||
switch result {
|
||||
case let .groupCall(call, _, _, chats, users):
|
||||
guard let _ = GroupCallInfo(call) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
apiUsers.append(contentsOf: users)
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
|
||||
for user in apiUsers {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
if let presence = TelegramUserPresence(apiUser: user) {
|
||||
peerPresences[telegramUser.id] = presence
|
||||
}
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> JoinGroupCallResult in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
|
||||
return JoinGroupCallResult(
|
||||
callInfo: parsedCall,
|
||||
state: state
|
||||
)
|
||||
}
|
||||
|> castError(JoinGroupCallError.self)
|
||||
}
|
||||
|> castError(JoinGroupCallError.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum LeaveGroupCallError {
|
||||
@ -598,7 +680,7 @@ public final class GroupCallParticipantsContext {
|
||||
public var activityRank: Int?
|
||||
public var muteState: MuteState?
|
||||
public var volume: Int32?
|
||||
|
||||
public var about: String?
|
||||
public init(
|
||||
peer: Peer,
|
||||
ssrc: UInt32,
|
||||
@ -607,7 +689,8 @@ public final class GroupCallParticipantsContext {
|
||||
activityTimestamp: Double?,
|
||||
activityRank: Int?,
|
||||
muteState: MuteState?,
|
||||
volume: Int32?
|
||||
volume: Int32?,
|
||||
about: String?
|
||||
) {
|
||||
self.peer = peer
|
||||
self.ssrc = ssrc
|
||||
@ -617,6 +700,7 @@ public final class GroupCallParticipantsContext {
|
||||
self.activityRank = activityRank
|
||||
self.muteState = muteState
|
||||
self.volume = volume
|
||||
self.about = about
|
||||
}
|
||||
|
||||
public static func ==(lhs: Participant, rhs: Participant) -> Bool {
|
||||
@ -641,6 +725,9 @@ public final class GroupCallParticipantsContext {
|
||||
if lhs.volume != rhs.volume {
|
||||
return false
|
||||
}
|
||||
if lhs.about != rhs.about {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -684,6 +771,8 @@ public final class GroupCallParticipantsContext {
|
||||
public var adminIds: Set<PeerId>
|
||||
public var isCreator: Bool
|
||||
public var defaultParticipantsAreMuted: DefaultParticipantsAreMuted
|
||||
public var recordingStartTimestamp: Int32?
|
||||
public var title: String?
|
||||
public var totalCount: Int
|
||||
public var version: Int32
|
||||
}
|
||||
@ -740,7 +829,7 @@ public final class GroupCallParticipantsContext {
|
||||
public var muteState: Participant.MuteState?
|
||||
public var participationStatusChange: ParticipationStatusChange
|
||||
public var volume: Int32?
|
||||
|
||||
public var about: String?
|
||||
init(
|
||||
peerId: PeerId,
|
||||
ssrc: UInt32,
|
||||
@ -749,7 +838,8 @@ public final class GroupCallParticipantsContext {
|
||||
activityTimestamp: Double?,
|
||||
muteState: Participant.MuteState?,
|
||||
participationStatusChange: ParticipationStatusChange,
|
||||
volume: Int32?
|
||||
volume: Int32?,
|
||||
about: String?
|
||||
) {
|
||||
self.peerId = peerId
|
||||
self.ssrc = ssrc
|
||||
@ -759,6 +849,7 @@ public final class GroupCallParticipantsContext {
|
||||
self.muteState = muteState
|
||||
self.participationStatusChange = participationStatusChange
|
||||
self.volume = volume
|
||||
self.about = about
|
||||
}
|
||||
}
|
||||
|
||||
@ -769,7 +860,7 @@ public final class GroupCallParticipantsContext {
|
||||
}
|
||||
|
||||
case state(update: StateUpdate)
|
||||
case call(isTerminated: Bool, defaultParticipantsAreMuted: State.DefaultParticipantsAreMuted)
|
||||
case call(isTerminated: Bool, defaultParticipantsAreMuted: State.DefaultParticipantsAreMuted, title: String?, recordingStartTimestamp: Int32?)
|
||||
}
|
||||
|
||||
public final class MemberEvent {
|
||||
@ -846,6 +937,7 @@ public final class GroupCallParticipantsContext {
|
||||
private var activityRankResetTimer: SwiftSignalKit.Timer?
|
||||
|
||||
private let updateDefaultMuteDisposable = MetaDisposable()
|
||||
private let updateShouldBeRecordingDisposable = MetaDisposable()
|
||||
|
||||
public init(account: Account, peerId: PeerId, id: Int64, accessHash: Int64, state: State) {
|
||||
self.account = account
|
||||
@ -926,6 +1018,8 @@ public final class GroupCallParticipantsContext {
|
||||
adminIds: strongSelf.stateValue.state.adminIds,
|
||||
isCreator: strongSelf.stateValue.state.isCreator,
|
||||
defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted,
|
||||
recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp,
|
||||
title: strongSelf.stateValue.state.title,
|
||||
totalCount: strongSelf.stateValue.state.totalCount,
|
||||
version: strongSelf.stateValue.state.version
|
||||
),
|
||||
@ -971,6 +1065,7 @@ public final class GroupCallParticipantsContext {
|
||||
self.updatesDisposable.dispose()
|
||||
self.activitiesDisposable?.dispose()
|
||||
self.updateDefaultMuteDisposable.dispose()
|
||||
self.updateShouldBeRecordingDisposable.dispose()
|
||||
self.activityRankResetTimer?.invalidate()
|
||||
}
|
||||
|
||||
@ -979,8 +1074,13 @@ public final class GroupCallParticipantsContext {
|
||||
for update in updates {
|
||||
if case let .state(update) = update {
|
||||
stateUpdates.append(update)
|
||||
} else if case let .call(_, defaultParticipantsAreMuted) = update {
|
||||
self.stateValue.state.defaultParticipantsAreMuted = defaultParticipantsAreMuted
|
||||
} else if case let .call(_, defaultParticipantsAreMuted, title, recordingStartTimestamp) = update {
|
||||
var state = self.stateValue.state
|
||||
state.defaultParticipantsAreMuted = defaultParticipantsAreMuted
|
||||
state.recordingStartTimestamp = recordingStartTimestamp
|
||||
state.title = title
|
||||
|
||||
self.stateValue.state = state
|
||||
}
|
||||
}
|
||||
|
||||
@ -1050,6 +1150,8 @@ public final class GroupCallParticipantsContext {
|
||||
adminIds: strongSelf.stateValue.state.adminIds,
|
||||
isCreator: strongSelf.stateValue.state.isCreator,
|
||||
defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted,
|
||||
recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp,
|
||||
title: strongSelf.stateValue.state.title,
|
||||
totalCount: strongSelf.stateValue.state.totalCount,
|
||||
version: strongSelf.stateValue.state.version
|
||||
),
|
||||
@ -1213,7 +1315,8 @@ public final class GroupCallParticipantsContext {
|
||||
activityTimestamp: activityTimestamp,
|
||||
activityRank: previousActivityRank,
|
||||
muteState: participantUpdate.muteState,
|
||||
volume: participantUpdate.volume
|
||||
volume: participantUpdate.volume,
|
||||
about: participantUpdate.about
|
||||
)
|
||||
updatedParticipants.append(participant)
|
||||
}
|
||||
@ -1230,6 +1333,8 @@ public final class GroupCallParticipantsContext {
|
||||
let adminIds = strongSelf.stateValue.state.adminIds
|
||||
let isCreator = strongSelf.stateValue.state.isCreator
|
||||
let defaultParticipantsAreMuted = strongSelf.stateValue.state.defaultParticipantsAreMuted
|
||||
let recordingStartTimestamp = strongSelf.stateValue.state.recordingStartTimestamp
|
||||
let title = strongSelf.stateValue.state.title
|
||||
|
||||
updatedParticipants.sort()
|
||||
|
||||
@ -1240,6 +1345,8 @@ public final class GroupCallParticipantsContext {
|
||||
adminIds: adminIds,
|
||||
isCreator: isCreator,
|
||||
defaultParticipantsAreMuted: defaultParticipantsAreMuted,
|
||||
recordingStartTimestamp: recordingStartTimestamp,
|
||||
title: title,
|
||||
totalCount: updatedTotalCount,
|
||||
version: update.version
|
||||
),
|
||||
@ -1300,11 +1407,11 @@ public final class GroupCallParticipantsContext {
|
||||
let id = self.id
|
||||
let accessHash = self.accessHash
|
||||
|
||||
let signal: Signal<Api.Updates?, NoError> = self.account.postbox.transaction { transaction -> Api.InputUser? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
||||
let signal: Signal<Api.Updates?, NoError> = self.account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
}
|
||||
|> mapToSignal { inputUser -> Signal<Api.Updates?, NoError> in
|
||||
guard let inputUser = inputUser else {
|
||||
|> mapToSignal { inputPeer -> Signal<Api.Updates?, NoError> in
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .single(nil)
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
@ -1314,8 +1421,8 @@ public final class GroupCallParticipantsContext {
|
||||
if let muteState = muteState, (!muteState.canUnmute || peerId == account.peerId || muteState.mutedByYou) {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.phone.editGroupCallMember(flags: flags, call: .inputGroupCall(id: id, accessHash: accessHash), userId: inputUser, volume: volume))
|
||||
|
||||
return account.network.request(Api.functions.phone.editGroupCallParticipant(flags: flags, call: .inputGroupCall(id: id, accessHash: accessHash), participant: inputPeer, volume: volume))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
@ -1355,6 +1462,16 @@ public final class GroupCallParticipantsContext {
|
||||
}))
|
||||
}
|
||||
|
||||
public func updateShouldBeRecording(_ shouldBeRecording: Bool) {
|
||||
self.updateShouldBeRecordingDisposable.set((self.account.network.request(Api.functions.phone.toggleGroupCallRecord(call: .inputGroupCall(id: self.id, accessHash: self.accessHash), start: shouldBeRecording ? .boolTrue : .boolFalse))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] updates in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.account.stateManager.addUpdates(updates)
|
||||
}))
|
||||
}
|
||||
|
||||
public func updateDefaultParticipantsAreMuted(isMuted: Bool) {
|
||||
if isMuted == self.stateValue.state.defaultParticipantsAreMuted.isMuted {
|
||||
return
|
||||
@ -1407,8 +1524,16 @@ public final class GroupCallParticipantsContext {
|
||||
extension GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate {
|
||||
init(_ apiParticipant: Api.GroupCallParticipant) {
|
||||
switch apiParticipant {
|
||||
case let .groupCallParticipant(flags, userId, date, activeDate, source, volume):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about):
|
||||
let peerId: PeerId
|
||||
switch apiPeerId {
|
||||
case let .peerUser(userId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .peerChat(chatId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
|
||||
case let .peerChannel(channelId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||
}
|
||||
let ssrc = UInt32(bitPattern: source)
|
||||
let muted = (flags & (1 << 0)) != 0
|
||||
let mutedByYou = (flags & (1 << 9)) != 0
|
||||
@ -1447,7 +1572,8 @@ extension GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate {
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
muteState: muteState,
|
||||
participationStatusChange: participationStatusChange,
|
||||
volume: volume
|
||||
volume: volume,
|
||||
about: about
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1458,8 +1584,16 @@ extension GroupCallParticipantsContext.Update.StateUpdate {
|
||||
var participantUpdates: [GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate] = []
|
||||
for participant in participants {
|
||||
switch participant {
|
||||
case let .groupCallParticipant(flags, userId, date, activeDate, source, volume):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about):
|
||||
let peerId: PeerId
|
||||
switch apiPeerId {
|
||||
case let .peerUser(userId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .peerChat(chatId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
|
||||
case let .peerChannel(channelId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||
}
|
||||
let ssrc = UInt32(bitPattern: source)
|
||||
let muted = (flags & (1 << 0)) != 0
|
||||
let mutedByYou = (flags & (1 << 9)) != 0
|
||||
@ -1498,7 +1632,8 @@ extension GroupCallParticipantsContext.Update.StateUpdate {
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
muteState: muteState,
|
||||
participationStatusChange: participationStatusChange,
|
||||
volume: volume
|
||||
volume: volume,
|
||||
about: about
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -1540,6 +1675,20 @@ public func inviteToGroupCall(account: Account, callId: Int64, accessHash: Int64
|
||||
}
|
||||
}
|
||||
|
||||
public enum EditGroupCallTitleError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public func editGroupCallTitle(account: Account, callId: Int64, accessHash: Int64, title: String) -> Signal<Never, EditGroupCallTitleError> {
|
||||
return account.network.request(Api.functions.phone.editGroupCallTitle(call: .inputGroupCall(id: callId, accessHash: accessHash), title: title)) |> mapError { _ -> EditGroupCallTitleError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Never, EditGroupCallTitleError> in
|
||||
account.stateManager.addUpdates(result)
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
public func updatedCurrentPeerGroupCall(account: Account, peerId: PeerId) -> Signal<CachedChannelData.ActiveCall?, NoError> {
|
||||
return fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox)
|
||||
|> mapToSignal { _ -> Signal<CachedChannelData.ActiveCall?, NoError> in
|
||||
@ -1568,3 +1717,22 @@ private func mergeAndSortParticipants(current currentParticipants: [GroupCallPar
|
||||
|
||||
return mergedParticipants
|
||||
}
|
||||
|
||||
public func getAudioBroadcastPart(account: Account, callId: Int64, accessHash: Int64, datacenterId: Int?, timestampId: Int32) -> Signal<Data?, NoError> {
|
||||
return account.network.multiplexedRequestManager.request(to: .main(account.network.datacenterId), consumerId: Int64.random(in: 0 ..< Int64.max), data: Api.functions.upload.getFile(flags: 0, location: .inputGroupCallStream(call: .inputGroupCall(id: callId, accessHash: accessHash), date: timestampId), offset: 0, limit: 128 * 1024), tag: nil, continueInBackground: false, automaticFloodWait: false)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.upload.File?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> map { result -> Data? in
|
||||
guard let result = result else {
|
||||
return nil
|
||||
}
|
||||
switch result {
|
||||
case let .file(_, _, bytes):
|
||||
return bytes.makeData()
|
||||
case .fileCdnRedirect:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ private final class MessageMediaPreuploadManagerContext {
|
||||
assert(self.queue.isCurrent())
|
||||
}
|
||||
|
||||
func add(network: Network, postbox: Postbox, id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal<MediaResourceData, NoError>) {
|
||||
func add(network: Network, postbox: Postbox, id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal<MediaResourceData, NoError>, onComplete:(()->Void)? = nil) {
|
||||
let context = MessageMediaPreuploadManagerUploadContext()
|
||||
self.uploadContexts[id] = context
|
||||
let queue = self.queue
|
||||
@ -47,6 +47,7 @@ private final class MessageMediaPreuploadManagerContext {
|
||||
default:
|
||||
print("result")
|
||||
context.result = next
|
||||
onComplete?()
|
||||
}
|
||||
for subscriber in context.subscribers.copyItems() {
|
||||
subscriber(next)
|
||||
@ -112,9 +113,9 @@ public final class MessageMediaPreuploadManager {
|
||||
})
|
||||
}
|
||||
|
||||
public func add(network: Network, postbox: Postbox, id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal<MediaResourceData, NoError>) {
|
||||
public func add(network: Network, postbox: Postbox, id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal<MediaResourceData, NoError>, onComplete:(()->Void)? = nil) {
|
||||
self.impl.with { context in
|
||||
context.add(network: network, postbox: postbox, id: id, encrypt: encrypt, tag: tag, source: source)
|
||||
context.add(network: network, postbox: postbox, id: id, encrypt: encrypt, tag: tag, source: source, onComplete: onComplete)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,17 +22,19 @@ private final class RequestData {
|
||||
let payload: Buffer
|
||||
let tag: MediaResourceFetchTag?
|
||||
let continueInBackground: Bool
|
||||
let automaticFloodWait: Bool
|
||||
let deserializeResponse: (Buffer) -> Any?
|
||||
let completed: (Any) -> Void
|
||||
let error: (MTRpcError) -> Void
|
||||
|
||||
init(id: Int32, consumerId: Int64, target: MultiplexedRequestTarget, functionDescription: FunctionDescription, payload: Buffer, tag: MediaResourceFetchTag?, continueInBackground: Bool, deserializeResponse: @escaping (Buffer) -> Any?, completed: @escaping (Any) -> Void, error: @escaping (MTRpcError) -> Void) {
|
||||
init(id: Int32, consumerId: Int64, target: MultiplexedRequestTarget, functionDescription: FunctionDescription, payload: Buffer, tag: MediaResourceFetchTag?, continueInBackground: Bool, automaticFloodWait: Bool, deserializeResponse: @escaping (Buffer) -> Any?, completed: @escaping (Any) -> Void, error: @escaping (MTRpcError) -> Void) {
|
||||
self.id = id
|
||||
self.consumerId = consumerId
|
||||
self.target = target
|
||||
self.functionDescription = functionDescription
|
||||
self.tag = tag
|
||||
self.continueInBackground = continueInBackground
|
||||
self.automaticFloodWait = automaticFloodWait
|
||||
self.payload = payload
|
||||
self.deserializeResponse = deserializeResponse
|
||||
self.completed = completed
|
||||
@ -98,12 +100,12 @@ private final class MultiplexedRequestManagerContext {
|
||||
}
|
||||
}
|
||||
|
||||
func request(to target: MultiplexedRequestTarget, consumerId: Int64, data: (FunctionDescription, Buffer, (Buffer) -> Any?), tag: MediaResourceFetchTag?, continueInBackground: Bool, completed: @escaping (Any) -> Void, error: @escaping (MTRpcError) -> Void) -> Disposable {
|
||||
func request(to target: MultiplexedRequestTarget, consumerId: Int64, data: (FunctionDescription, Buffer, (Buffer) -> Any?), tag: MediaResourceFetchTag?, continueInBackground: Bool, automaticFloodWait: Bool, completed: @escaping (Any) -> Void, error: @escaping (MTRpcError) -> Void) -> Disposable {
|
||||
let targetKey = MultiplexedRequestTargetKey(target: target, continueInBackground: continueInBackground)
|
||||
|
||||
let requestId = self.nextId
|
||||
self.nextId += 1
|
||||
self.queuedRequests.append(RequestData(id: requestId, consumerId: consumerId, target: target, functionDescription: data.0, payload: data.1, tag: tag, continueInBackground: continueInBackground, deserializeResponse: { buffer in
|
||||
self.queuedRequests.append(RequestData(id: requestId, consumerId: consumerId, target: target, functionDescription: data.0, payload: data.1, tag: tag, continueInBackground: continueInBackground, automaticFloodWait: automaticFloodWait, deserializeResponse: { buffer in
|
||||
return data.2(buffer)
|
||||
}, completed: { result in
|
||||
completed(result)
|
||||
@ -178,7 +180,7 @@ private final class MultiplexedRequestManagerContext {
|
||||
let requestId = request.id
|
||||
selectedContext.requests.append(ExecutingRequestData(requestId: requestId, disposable: disposable))
|
||||
let queue = self.queue
|
||||
disposable.set(selectedContext.worker.rawRequest((request.functionDescription, request.payload, request.deserializeResponse)).start(next: { [weak self, weak selectedContext] result in
|
||||
disposable.set(selectedContext.worker.rawRequest((request.functionDescription, request.payload, request.deserializeResponse), automaticFloodWait: request.automaticFloodWait).start(next: { [weak self, weak selectedContext] result in
|
||||
queue.async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -267,13 +269,13 @@ final class MultiplexedRequestManager {
|
||||
})
|
||||
}
|
||||
|
||||
func request<T>(to target: MultiplexedRequestTarget, consumerId: Int64, data: (FunctionDescription, Buffer, DeserializeFunctionResponse<T>), tag: MediaResourceFetchTag?, continueInBackground: Bool) -> Signal<T, MTRpcError> {
|
||||
func request<T>(to target: MultiplexedRequestTarget, consumerId: Int64, data: (FunctionDescription, Buffer, DeserializeFunctionResponse<T>), tag: MediaResourceFetchTag?, continueInBackground: Bool, automaticFloodWait: Bool = true) -> Signal<T, MTRpcError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
self.context.with { context in
|
||||
disposable.set(context.request(to: target, consumerId: consumerId, data: (data.0, data.1, { buffer in
|
||||
return data.2.parse(buffer)
|
||||
}), tag: tag, continueInBackground: continueInBackground, completed: { result in
|
||||
}), tag: tag, continueInBackground: continueInBackground, automaticFloodWait: automaticFloodWait, completed: { result in
|
||||
if let result = result as? T {
|
||||
subscriber.putNext(result)
|
||||
subscriber.putCompletion()
|
||||
|
@ -188,14 +188,17 @@ public func requestMessageActionUrlAuth(account: Account, subject: MessageAction
|
||||
|> castError(MTRpcError.self)
|
||||
|> mapToSignal { peer -> Signal<Api.UrlAuthResult?, MTRpcError> in
|
||||
if let inputPeer = apiInputPeer(peer) {
|
||||
return account.network.request(Api.functions.messages.requestUrlAuth(peer: inputPeer, msgId: messageId.id, buttonId: buttonId))
|
||||
let flags: Int32 = 1 << 1
|
||||
return account.network.request(Api.functions.messages.requestUrlAuth(flags: flags, peer: inputPeer, msgId: messageId.id, buttonId: buttonId, url: nil))
|
||||
|> map(Optional.init)
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
case let .url(url):
|
||||
request = account.network.request(Api.functions.messages.requestUrlAuth(peer: .inputPeerEmpty, msgId: 0, buttonId: 0))
|
||||
var flags: Int32 = 1 << 1
|
||||
flags |= (1 << 2)
|
||||
request = account.network.request(Api.functions.messages.requestUrlAuth(flags: flags, peer: .inputPeerEmpty, msgId: 0, buttonId: 0, url: url))
|
||||
|> map(Optional.init)
|
||||
}
|
||||
|
||||
@ -232,14 +235,17 @@ public func acceptMessageActionUrlAuth(account: Account, subject: MessageActionU
|
||||
|> castError(MTRpcError.self)
|
||||
|> mapToSignal { peer -> Signal<Api.UrlAuthResult?, MTRpcError> in
|
||||
if let inputPeer = apiInputPeer(peer) {
|
||||
return account.network.request(Api.functions.messages.acceptUrlAuth(flags: flags, peer: inputPeer, msgId: messageId.id, buttonId: buttonId))
|
||||
let flags: Int32 = 1 << 1
|
||||
return account.network.request(Api.functions.messages.acceptUrlAuth(flags: flags, peer: inputPeer, msgId: messageId.id, buttonId: buttonId, url: nil))
|
||||
|> map(Optional.init)
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
case let .url(url):
|
||||
request = account.network.request(Api.functions.messages.acceptUrlAuth(flags: flags, peer: .inputPeerEmpty, msgId: 0, buttonId: 0))
|
||||
var flags: Int32 = 1 << 1
|
||||
flags |= (1 << 2)
|
||||
request = account.network.request(Api.functions.messages.acceptUrlAuth(flags: flags, peer: .inputPeerEmpty, msgId: 0, buttonId: 0, url: url))
|
||||
|> map(Optional.init)
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 124
|
||||
return 125
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
@ -300,6 +300,8 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
||||
}
|
||||
}
|
||||
|
||||
let groupcallDefaultJoinAs = chatFull.groupcallDefaultJoinAs
|
||||
|
||||
transaction.updatePeerCachedData(peerIds: [peerId], update: { _, current in
|
||||
let previous: CachedGroupData
|
||||
if let current = current as? CachedGroupData {
|
||||
@ -318,6 +320,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
||||
.withUpdatedInvitedBy(invitedBy)
|
||||
.withUpdatedPhoto(photo)
|
||||
.withUpdatedActiveCall(updatedActiveCall)
|
||||
.withUpdatedCallJoinPeerId(groupcallDefaultJoinAs?.peerId)
|
||||
})
|
||||
case .channelFull:
|
||||
break
|
||||
@ -355,7 +358,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
||||
}
|
||||
|
||||
switch fullChat {
|
||||
case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, chatPhoto, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, folderId, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, pts, inputCall, ttl, pendingSuggestions):
|
||||
case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, chatPhoto, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, folderId, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, pts, inputCall, ttl, pendingSuggestions, groupcallDefaultJoinAs):
|
||||
var channelFlags = CachedChannelFlags()
|
||||
if (flags & (1 << 3)) != 0 {
|
||||
channelFlags.insert(.canDisplayParticipants)
|
||||
@ -530,6 +533,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
||||
.withUpdatedInvitedBy(invitedBy)
|
||||
.withUpdatedPhoto(photo)
|
||||
.withUpdatedActiveCall(updatedActiveCall)
|
||||
.withUpdatedCallJoinPeerId(groupcallDefaultJoinAs?.peerId)
|
||||
.withUpdatedAutoremoveTimeout(autoremoveTimeout)
|
||||
.withUpdatedPendingSuggestions(pendingSuggestions ?? [])
|
||||
})
|
||||
|
@ -300,8 +300,8 @@ public final class AccountContextImpl: AccountContext {
|
||||
}
|
||||
}
|
||||
|
||||
public func joinGroupCall(peerId: PeerId, activeCall: CachedChannelData.ActiveCall) {
|
||||
let callResult = self.sharedContext.callManager?.joinGroupCall(context: self, peerId: peerId, initialCall: activeCall, endCurrentIfAny: false)
|
||||
public func joinGroupCall(peerId: PeerId, joinAsPeerId: PeerId?, activeCall: CachedChannelData.ActiveCall) {
|
||||
let callResult = self.sharedContext.callManager?.joinGroupCall(context: self, peerId: peerId, joinAsPeerId: joinAsPeerId, initialCall: activeCall, endCurrentIfAny: false)
|
||||
if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == peerId {
|
||||
self.sharedContext.navigateToCurrentCall()
|
||||
@ -323,14 +323,14 @@ public final class AccountContextImpl: AccountContext {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.sharedContext.callManager?.joinGroupCall(context: strongSelf, peerId: peer.id, initialCall: activeCall, endCurrentIfAny: true)
|
||||
let _ = strongSelf.sharedContext.callManager?.joinGroupCall(context: strongSelf, peerId: peer.id, joinAsPeerId: joinAsPeerId, initialCall: activeCall, endCurrentIfAny: true)
|
||||
})]), on: .root)
|
||||
} else {
|
||||
strongSelf.sharedContext.mainWindow?.present(textAlertController(context: strongSelf, title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressVoiceChatMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.sharedContext.callManager?.joinGroupCall(context: strongSelf, peerId: peer.id, initialCall: activeCall, endCurrentIfAny: true)
|
||||
let _ = strongSelf.sharedContext.callManager?.joinGroupCall(context: strongSelf, peerId: peer.id, joinAsPeerId: joinAsPeerId, initialCall: activeCall, endCurrentIfAny: true)
|
||||
})]), on: .root)
|
||||
}
|
||||
} else {
|
||||
|
@ -534,7 +534,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
case .groupPhoneCall, .inviteToGroupPhoneCall:
|
||||
if let activeCall = strongSelf.presentationInterfaceState.activeGroupCallInfo?.activeCall {
|
||||
strongSelf.context.joinGroupCall(peerId: message.id.peerId, activeCall: CachedChannelData.ActiveCall(id: activeCall.id, accessHash: activeCall.accessHash))
|
||||
strongSelf.context.joinGroupCall(peerId: message.id.peerId, joinAsPeerId: nil, activeCall: CachedChannelData.ActiveCall(id: activeCall.id, accessHash: activeCall.accessHash))
|
||||
} else {
|
||||
var canManageGroupCalls = false
|
||||
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel {
|
||||
@ -563,12 +563,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
statusController?.dismiss()
|
||||
}
|
||||
strongSelf.present(statusController, in: .window(.root))
|
||||
strongSelf.createVoiceChatDisposable.set((createGroupCall(account: strongSelf.context.account, peerId: message.id.peerId)
|
||||
strongSelf.createVoiceChatDisposable.set((createGroupCall(account: strongSelf.context.account, peerId: message.id.peerId, joinAs: nil)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] info in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.context.joinGroupCall(peerId: message.id.peerId, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash))
|
||||
strongSelf.context.joinGroupCall(peerId: message.id.peerId, joinAsPeerId: nil, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash))
|
||||
}, error: { [weak self] error in
|
||||
dismissStatus?()
|
||||
|
||||
@ -6402,7 +6402,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
strongSelf.context.joinGroupCall(peerId: peer.id, activeCall: activeCall)
|
||||
strongSelf.context.joinGroupCall(peerId: peer.id, joinAsPeerId: nil, activeCall: activeCall)
|
||||
}, presentInviteMembers: { [weak self] in
|
||||
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
@ -11847,9 +11847,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return inputShortcuts + otherShortcuts
|
||||
}
|
||||
|
||||
public override func joinGroupCall(peerId: PeerId, info: GroupCallInfo) {
|
||||
public override func joinGroupCall(peerId: PeerId, joinAsPeerId: PeerId?, info: GroupCallInfo) {
|
||||
let _ = self.presentVoiceMessageDiscardAlert(action: {
|
||||
super.joinGroupCall(peerId: peerId, info: info)
|
||||
super.joinGroupCall(peerId: peerId, joinAsPeerId: joinAsPeerId, info: info)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -993,9 +993,16 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
|
||||
var canViewStats = false
|
||||
var hasDiscussion = false
|
||||
var hasVoiceChat = false
|
||||
var displayMore = true
|
||||
if let cachedChannelData = cachedData as? CachedChannelData {
|
||||
canViewStats = cachedChannelData.flags.contains(.canViewStats)
|
||||
}
|
||||
if channel.flags.contains(.hasVoiceChat) {
|
||||
hasVoiceChat = true
|
||||
}
|
||||
if channel.flags.contains(.isCreator) || channel.hasPermission(.manageCalls) {
|
||||
displayMore = true
|
||||
}
|
||||
switch channel.info {
|
||||
case let .broadcast(info):
|
||||
if !channel.flags.contains(.isCreator) {
|
||||
@ -1009,9 +1016,6 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
|
||||
if channel.flags.contains(.isCreator) || channel.hasPermission(.inviteMembers) {
|
||||
result.append(.addMember)
|
||||
}
|
||||
if channel.flags.contains(.hasVoiceChat) {
|
||||
hasVoiceChat = true
|
||||
}
|
||||
}
|
||||
switch channel.participationStatus {
|
||||
case .member:
|
||||
@ -1033,7 +1037,6 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
|
||||
if displayLeave {
|
||||
result.append(.leave)
|
||||
}
|
||||
var displayMore = true
|
||||
if displayLeave && !channel.flags.contains(.isCreator) {
|
||||
if let _ = channel.adminRights {
|
||||
displayMore = false
|
||||
|
@ -57,6 +57,7 @@ import InviteLinksUI
|
||||
import UndoUI
|
||||
import MediaResources
|
||||
import HashtagSearchUI
|
||||
import ActionSheetPeerItem
|
||||
|
||||
protocol PeerInfoScreenItem: class {
|
||||
var id: AnyHashable { get }
|
||||
@ -3256,9 +3257,69 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
self.requestCall(isVideo: true)
|
||||
case .voiceChat:
|
||||
if let cachedData = self.data?.cachedData as? CachedGroupData, let activeCall = cachedData.activeCall {
|
||||
self.context.joinGroupCall(peerId: self.peerId, activeCall: activeCall)
|
||||
self.context.joinGroupCall(peerId: self.peerId, joinAsPeerId: nil, activeCall: activeCall)
|
||||
} else if let cachedData = self.data?.cachedData as? CachedChannelData, let activeCall = cachedData.activeCall {
|
||||
self.context.joinGroupCall(peerId: self.peerId, activeCall: activeCall)
|
||||
let accountPeerId = self.context.account.peerId
|
||||
let _ = (adminedPublicChannels(account: self.context.account, scope: .forVoiceChat)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] channelPeers in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(accountPeerId)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { accountPeer in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
if channelPeers.isEmpty {
|
||||
strongSelf.context.joinGroupCall(peerId: strongSelf.peerId, joinAsPeerId: nil, activeCall: activeCall)
|
||||
} else {
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
let dismissAction: () -> Void = { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
}
|
||||
let selectAction: (PeerId) -> Void = { joinAsPeerId in
|
||||
dismissAction()
|
||||
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.context.joinGroupCall(peerId: strongSelf.peerId, joinAsPeerId: joinAsPeerId == strongSelf.context.account.peerId ? nil : joinAsPeerId, activeCall: activeCall)
|
||||
}
|
||||
var items: [ActionSheetItem] = []
|
||||
|
||||
var allPeers: [Peer] = []
|
||||
if let accountPeer = accountPeer {
|
||||
allPeers.append(accountPeer)
|
||||
}
|
||||
var channelPeers = channelPeers
|
||||
for i in 0 ..< channelPeers.count {
|
||||
if channelPeers[i].id == strongSelf.peerId {
|
||||
let peer = channelPeers[i]
|
||||
channelPeers.remove(at: i)
|
||||
channelPeers.insert(peer, at: 0)
|
||||
break
|
||||
}
|
||||
}
|
||||
allPeers.append(contentsOf: channelPeers)
|
||||
|
||||
for peer in allPeers {
|
||||
items.append(ActionSheetPeerItem(context: strongSelf.context, peer: peer, title: peer.debugDisplayTitle, isSelected: false, strings: strongSelf.presentationData.strings, theme: strongSelf.presentationData.theme, action: {
|
||||
selectAction(peer.id)
|
||||
}))
|
||||
}
|
||||
|
||||
actionSheet.setItemGroups([
|
||||
ActionSheetItemGroup(items: items),
|
||||
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
||||
])
|
||||
strongSelf.view.endEditing(true)
|
||||
controller.present(actionSheet, in: .window(.root))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
case .mute:
|
||||
if let notificationSettings = self.data?.notificationSettings, case .muted = notificationSettings.muteState {
|
||||
@ -3428,7 +3489,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
}
|
||||
}
|
||||
} else if let channel = peer as? TelegramChannel {
|
||||
if case .group = channel.info, !channel.flags.contains(.hasVoiceChat) {
|
||||
if !channel.flags.contains(.hasVoiceChat) {
|
||||
if channel.flags.contains(.isCreator) || channel.hasPermission(.manageCalls) {
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_CreateVoiceChat, color: .accent, action: { [weak self] in
|
||||
dismissAction()
|
||||
@ -3684,7 +3745,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
}
|
||||
|
||||
if let activeCall = cachedChannelData.activeCall {
|
||||
self.context.joinGroupCall(peerId: peer.id, activeCall: activeCall)
|
||||
self.context.joinGroupCall(peerId: peer.id, joinAsPeerId: nil, activeCall: activeCall)
|
||||
} else {
|
||||
self.createAndJoinGroupCall(peerId: peer.id)
|
||||
}
|
||||
@ -3695,7 +3756,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
}
|
||||
|
||||
if let activeCall = cachedGroupData.activeCall {
|
||||
self.context.joinGroupCall(peerId: peer.id, activeCall: activeCall)
|
||||
self.context.joinGroupCall(peerId: peer.id, joinAsPeerId: nil, activeCall: activeCall)
|
||||
} else {
|
||||
self.createAndJoinGroupCall(peerId: peer.id)
|
||||
}
|
||||
@ -3729,12 +3790,12 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
statusController?.dismiss()
|
||||
}
|
||||
strongSelf.controller?.present(statusController, in: .window(.root))
|
||||
strongSelf.activeActionDisposable.set((createGroupCall(account: strongSelf.context.account, peerId: peerId)
|
||||
strongSelf.activeActionDisposable.set((createGroupCall(account: strongSelf.context.account, peerId: peerId, joinAs: nil)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] info in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.context.joinGroupCall(peerId: peerId, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash))
|
||||
strongSelf.context.joinGroupCall(peerId: peerId, joinAsPeerId: nil, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash))
|
||||
}, error: { [weak self] error in
|
||||
dismissStatus?()
|
||||
|
||||
|
@ -4,6 +4,8 @@ import TgVoipWebrtc
|
||||
import UniversalMediaPlayer
|
||||
import AppBundle
|
||||
import OpusBinding
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
|
||||
private final class ContextQueueImpl: NSObject, OngoingCallThreadLocalContextQueueWebrtc {
|
||||
private let queue: Queue
|
||||
@ -29,92 +31,89 @@ private final class ContextQueueImpl: NSObject, OngoingCallThreadLocalContextQue
|
||||
}
|
||||
}
|
||||
|
||||
private final class DemoBroadcastPacketSource {
|
||||
private protocol BroadcastPartSource: class {
|
||||
var parts: Signal<[OngoingGroupCallBroadcastPart], NoError> { get }
|
||||
}
|
||||
|
||||
private final class NetworkBroadcastPartSource: BroadcastPartSource {
|
||||
private let queue: Queue
|
||||
private let account: Account
|
||||
private let callId: Int64
|
||||
private let accessHash: Int64
|
||||
private let datacenterId: Int?
|
||||
|
||||
private let packetsPipe = ValuePipe<[OngoingGroupCallBroadcastPacket]>()
|
||||
var packets: Signal<[OngoingGroupCallBroadcastPacket], NoError> {
|
||||
return self.packetsPipe.signal()
|
||||
private let partsPipe = ValuePipe<[OngoingGroupCallBroadcastPart]>()
|
||||
var parts: Signal<[OngoingGroupCallBroadcastPart], NoError> {
|
||||
return self.partsPipe.signal()
|
||||
}
|
||||
|
||||
private var timer: SwiftSignalKit.Timer?
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
private var enqueuedPackets: [OngoingGroupCallBroadcastPacket] = []
|
||||
private var delayTimer: SwiftSignalKit.Timer?
|
||||
private var nextTimestampId: Int32?
|
||||
|
||||
private var nextIndex: Int = 0
|
||||
|
||||
init(queue: Queue) {
|
||||
init(queue: Queue, account: Account, callId: Int64, accessHash: Int64, datacenterId: Int?) {
|
||||
self.queue = queue
|
||||
self.account = account
|
||||
self.callId = callId
|
||||
self.accessHash = accessHash
|
||||
self.datacenterId = datacenterId
|
||||
|
||||
self.emitPacketAndStartTimer()
|
||||
self.check()
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.timer?.invalidate()
|
||||
self.delayTimer?.invalidate()
|
||||
self.disposable.dispose()
|
||||
}
|
||||
|
||||
private func emitPacketAndStartTimer() {
|
||||
let demoPacketCount = 200
|
||||
let index = self.nextIndex % demoPacketCount
|
||||
self.nextIndex += 1
|
||||
|
||||
var packets: [OngoingGroupCallBroadcastPacket] = []
|
||||
|
||||
let fileName = String(format: "%04d", index)
|
||||
if let path = getAppBundle().path(forResource: fileName, ofType: "ogg") {
|
||||
let source1 = SoftwareAudioSource(path: path)
|
||||
let source2 = SoftwareAudioSource(path: path)
|
||||
let frames = OggOpusReader.extractFrames(try! Data(contentsOf: URL(fileURLWithPath: path)))!
|
||||
while true {
|
||||
if true {
|
||||
if let (frame, numSamples) = source1.readEncodedFrame() {
|
||||
let decodedFrame = source2.readFrame()!
|
||||
|
||||
packets.append(OngoingGroupCallBroadcastPacket(numSamples: Int32(numSamples), data: frames[packets.count].data, decodedData: decodedFrame))
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if let frame = source2.readFrame() {
|
||||
packets.append(OngoingGroupCallBroadcastPacket(numSamples: Int32(frame.count / 2), data: frame, decodedData: frame))
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
private func check() {
|
||||
let timestampId: Int32
|
||||
if let nextTimestampId = self.nextTimestampId {
|
||||
timestampId = nextTimestampId
|
||||
} else {
|
||||
timestampId = Int32(Date().timeIntervalSince1970)
|
||||
}
|
||||
|
||||
if !packets.isEmpty {
|
||||
self.enqueuedPackets.append(contentsOf: packets)
|
||||
self.startDelayTimer()
|
||||
}
|
||||
|
||||
let timer = SwiftSignalKit.Timer(timeout: 1.0, repeat: false, completion: { [weak self] in
|
||||
self?.emitPacketAndStartTimer()
|
||||
}, queue: self.queue)
|
||||
self.timer = timer
|
||||
timer.start()
|
||||
}
|
||||
|
||||
private func startDelayTimer() {
|
||||
let delayTimer = SwiftSignalKit.Timer(timeout: Double.random(in: 0.1 ... 0.3), repeat: false, completion: { [weak self] in
|
||||
self.disposable.set((getAudioBroadcastPart(account: self.account, callId: self.callId, accessHash: self.accessHash, datacenterId: self.datacenterId, timestampId: timestampId)
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] data in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let packets = strongSelf.enqueuedPackets
|
||||
strongSelf.enqueuedPackets.removeAll()
|
||||
if !packets.isEmpty {
|
||||
strongSelf.packetsPipe.putNext(packets)
|
||||
if let data = data {
|
||||
var parts: [OngoingGroupCallBroadcastPart] = []
|
||||
parts.append(OngoingGroupCallBroadcastPart(timestamp: timestampId, oggData: data))
|
||||
|
||||
strongSelf.nextTimestampId = timestampId + 1
|
||||
|
||||
if !parts.isEmpty {
|
||||
strongSelf.partsPipe.putNext(parts)
|
||||
}
|
||||
}
|
||||
}, queue: self.queue)
|
||||
self.delayTimer = delayTimer
|
||||
delayTimer.start()
|
||||
|
||||
strongSelf.timer?.invalidate()
|
||||
strongSelf.timer = SwiftSignalKit.Timer(timeout: 0.5, repeat: false, completion: {
|
||||
self?.check()
|
||||
}, queue: strongSelf.queue)
|
||||
strongSelf.timer?.start()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
public final class OngoingGroupCallContext {
|
||||
public struct AudioStreamData {
|
||||
public var account: Account
|
||||
public var callId: Int64
|
||||
public var accessHash: Int64
|
||||
public var datacenterId: Int?
|
||||
|
||||
public init(account: Account, callId: Int64, accessHash: Int64, datacenterId: Int?) {
|
||||
self.account = account
|
||||
self.callId = callId
|
||||
self.accessHash = accessHash
|
||||
self.datacenterId = datacenterId
|
||||
}
|
||||
}
|
||||
|
||||
public enum NetworkState {
|
||||
case connecting
|
||||
case connected
|
||||
@ -138,10 +137,10 @@ public final class OngoingGroupCallContext {
|
||||
|
||||
let videoSources = ValuePromise<Set<UInt32>>(Set(), ignoreRepeated: true)
|
||||
|
||||
private var broadcastPacketSource: DemoBroadcastPacketSource?
|
||||
private var broadcastPacketsDisposable: Disposable?
|
||||
private var broadcastPartsSource: BroadcastPartSource?
|
||||
private var broadcastPartsDisposable: Disposable?
|
||||
|
||||
init(queue: Queue, inputDeviceId: String, outputDeviceId: String, video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set<UInt32>) -> Void, demoAudioStream: Bool) {
|
||||
init(queue: Queue, inputDeviceId: String, outputDeviceId: String, video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set<UInt32>) -> Void, audioStreamData: AudioStreamData?) {
|
||||
self.queue = queue
|
||||
|
||||
var networkStateUpdatedImpl: ((GroupCallNetworkState) -> Void)?
|
||||
@ -164,6 +163,33 @@ public final class OngoingGroupCallContext {
|
||||
},
|
||||
participantDescriptionsRequired: { ssrcs in
|
||||
participantDescriptionsRequired(Set(ssrcs.map { $0.uint32Value }))
|
||||
},
|
||||
externalDecodeOgg: { sourceData in
|
||||
let tempFile = TempBox.shared.tempFile(fileName: "audio.ogg")
|
||||
defer {
|
||||
TempBox.shared.dispose(tempFile)
|
||||
}
|
||||
|
||||
guard let _ = try? sourceData.write(to: URL(fileURLWithPath: tempFile.path), options: .atomic) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var resultData = Data()
|
||||
|
||||
let source = SoftwareAudioSource(path: tempFile.path)
|
||||
while true {
|
||||
if let frame = source.readFrame() {
|
||||
resultData.append(frame)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if resultData.isEmpty {
|
||||
return nil
|
||||
} else {
|
||||
return resultData
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@ -216,54 +242,22 @@ public final class OngoingGroupCallContext {
|
||||
}
|
||||
})
|
||||
|
||||
if demoAudioStream {
|
||||
let broadcastPacketSource = DemoBroadcastPacketSource(queue: queue)
|
||||
self.broadcastPacketSource = broadcastPacketSource
|
||||
self.broadcastPacketsDisposable = (broadcastPacketSource.packets
|
||||
|> deliverOn(queue)).start(next: { [weak self] packets in
|
||||
if let audioStreamData = audioStreamData {
|
||||
let broadcastPartsSource = NetworkBroadcastPartSource(queue: queue, account: audioStreamData.account, callId: audioStreamData.callId, accessHash: audioStreamData.accessHash, datacenterId: audioStreamData.datacenterId)
|
||||
//let broadcastPartsSource = DemoBroadcastPartSource(queue: queue)
|
||||
self.broadcastPartsSource = broadcastPartsSource
|
||||
self.broadcastPartsDisposable = (broadcastPartsSource.parts
|
||||
|> deliverOn(queue)).start(next: { [weak self] parts in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.context.add(packets)
|
||||
strongSelf.context.add(parts)
|
||||
})
|
||||
}
|
||||
|
||||
/*var packets: [OngoingGroupCallBroadcastPacket] = []
|
||||
for i in 0 ..< 200 {
|
||||
let fileName = String(format: "%04d", i)
|
||||
if let path = getAppBundle().path(forResource: fileName, ofType: "ogg") {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: path)) {
|
||||
if let frames = OggOpusReader.extractFrames(data) {
|
||||
for frame in frames {
|
||||
packets.append(OngoingGroupCallBroadcastPacket(numSamples: frame.numSamples, data: frame.data))
|
||||
}
|
||||
}
|
||||
}
|
||||
continue
|
||||
|
||||
let source = SoftwareAudioSource(path: path)
|
||||
while true {
|
||||
if let (frame, numSamples) = source.readEncodedFrame() {
|
||||
if numSamples != 960 {
|
||||
continue
|
||||
}
|
||||
packets.append(OngoingGroupCallBroadcastPacket(numSamples: Int32(numSamples), data: frame))
|
||||
} else {
|
||||
break
|
||||
}
|
||||
/*if let frame = source.readFrame() {
|
||||
packets.append(frame)
|
||||
} else {
|
||||
break
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
context.add(packets);*/
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.broadcastPacketsDisposable?.dispose()
|
||||
self.broadcastPartsDisposable?.dispose()
|
||||
}
|
||||
|
||||
func setJoinResponse(payload: String, participants: [(UInt32, String?)]) {
|
||||
@ -480,10 +474,10 @@ public final class OngoingGroupCallContext {
|
||||
}
|
||||
}
|
||||
|
||||
public init(inputDeviceId: String = "", outputDeviceId: String = "", video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set<UInt32>) -> Void, demoAudioStream: Bool) {
|
||||
public init(inputDeviceId: String = "", outputDeviceId: String = "", video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set<UInt32>) -> Void, audioStreamData: AudioStreamData?) {
|
||||
let queue = self.queue
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return Impl(queue: queue, inputDeviceId: inputDeviceId, outputDeviceId: outputDeviceId, video: video, participantDescriptionsRequired: participantDescriptionsRequired, demoAudioStream: demoAudioStream)
|
||||
return Impl(queue: queue, inputDeviceId: inputDeviceId, outputDeviceId: outputDeviceId, video: video, participantDescriptionsRequired: participantDescriptionsRequired, audioStreamData: audioStreamData)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,8 @@ objc_library(
|
||||
"//submodules/MtProtoKit:MtProtoKit",
|
||||
"//third-party/boringssl:crypto",
|
||||
"//third-party/boringssl:ssl",
|
||||
"//third-party/ogg:ogg",
|
||||
"//third-party/opusfile:opusfile",
|
||||
],
|
||||
sdk_frameworks = [
|
||||
"Foundation",
|
||||
|
@ -165,19 +165,18 @@ typedef NS_ENUM(int32_t, GroupCallNetworkState) {
|
||||
|
||||
@end
|
||||
|
||||
@interface OngoingGroupCallBroadcastPacket : NSObject
|
||||
@interface OngoingGroupCallBroadcastPart : NSObject
|
||||
|
||||
@property (nonatomic, readonly) int numSamples;
|
||||
@property (nonatomic, strong, readonly) NSData * _Nonnull data;
|
||||
@property (nonatomic, strong, readonly) NSData * _Nonnull decodedData;
|
||||
@property (nonatomic, readonly) int32_t timestamp;
|
||||
@property (nonatomic, strong, readonly) NSData * _Nonnull oggData;
|
||||
|
||||
- (instancetype _Nonnull)initWithNumSamples:(int)numSamples data:(NSData * _Nonnull)data decodedData:(NSData * _Nonnull)decodedData;
|
||||
- (instancetype _Nonnull)initWithTimestamp:(int32_t)timestamp oggData:(NSData * _Nonnull)oggData;
|
||||
|
||||
@end
|
||||
|
||||
@interface GroupCallThreadLocalContext : NSObject
|
||||
|
||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))participantDescriptionsRequired;
|
||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))participantDescriptionsRequired externalDecodeOgg:(NSData * _Nullable (^ _Nullable)(NSData * _Nonnull))externalDecodeOgg;
|
||||
|
||||
- (void)stop;
|
||||
|
||||
@ -196,7 +195,7 @@ typedef NS_ENUM(int32_t, GroupCallNetworkState) {
|
||||
- (void)switchAudioInput:(NSString * _Nonnull)deviceId;
|
||||
- (void)makeIncomingVideoViewWithSsrc:(uint32_t)ssrc completion:(void (^_Nonnull)(UIView<OngoingCallThreadLocalContextWebrtcVideoView> * _Nullable))completion;
|
||||
|
||||
- (void)addBroadcastPackets:(NSArray<OngoingGroupCallBroadcastPacket *> * _Nonnull)packets;
|
||||
- (void)addBroadcastParts:(NSArray<OngoingGroupCallBroadcastPart *> * _Nonnull)parts;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -833,7 +833,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
|
||||
@implementation GroupCallThreadLocalContext
|
||||
|
||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))participantDescriptionsRequired {
|
||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))participantDescriptionsRequired externalDecodeOgg:(NSData * _Nullable (^ _Nullable)(NSData * _Nonnull))externalDecodeOgg {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_queue = queue;
|
||||
@ -841,6 +841,19 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
_networkStateUpdated = [networkStateUpdated copy];
|
||||
_videoCapturer = videoCapturer;
|
||||
|
||||
std::function<void(std::vector<uint8_t> &, std::vector<uint8_t> const &)> externalDecodeOggFunction;
|
||||
if (externalDecodeOgg) {
|
||||
externalDecodeOggFunction = [externalDecodeOgg](std::vector<uint8_t> &outPcm, std::vector<uint8_t> sourceData) {
|
||||
@autoreleasepool {
|
||||
NSData *result = externalDecodeOgg([NSData dataWithBytes:sourceData.data() length:sourceData.size()]);
|
||||
if (result) {
|
||||
outPcm.resize(result.length);
|
||||
[result getBytes:outPcm.data() length:result.length];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
__weak GroupCallThreadLocalContext *weakSelf = self;
|
||||
_instance.reset(new tgcalls::GroupInstanceCustomImpl((tgcalls::GroupInstanceDescriptor){
|
||||
.networkStateUpdated = [weakSelf, queue, networkStateUpdated](bool isConnected) {
|
||||
@ -877,7 +890,8 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
[mappedSources addObject:@(it)];
|
||||
}
|
||||
participantDescriptionsRequired(mappedSources);
|
||||
}
|
||||
},
|
||||
.externalDecodeOgg = externalDecodeOggFunction
|
||||
}));
|
||||
}
|
||||
return self;
|
||||
@ -1398,25 +1412,21 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addBroadcastPackets:(NSArray<OngoingGroupCallBroadcastPacket *> * _Nonnull)packets {
|
||||
- (void)addBroadcastParts:(NSArray<OngoingGroupCallBroadcastPart *> * _Nonnull)parts {
|
||||
if (!_instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<tgcalls::BroadcastPacket> parsedPackets;
|
||||
for (OngoingGroupCallBroadcastPacket *packet in packets) {
|
||||
tgcalls::BroadcastPacket parsedPacket;
|
||||
parsedPacket.numSamples = packet.numSamples;
|
||||
std::vector<tgcalls::BroadcastPart> parsedParts;
|
||||
for (OngoingGroupCallBroadcastPart *part in parts) {
|
||||
tgcalls::BroadcastPart parsedPart;
|
||||
parsedPart.timestamp = part.timestamp;
|
||||
parsedPart.oggData.resize(part.oggData.length);
|
||||
[part.oggData getBytes:parsedPart.oggData.data() length:part.oggData.length];
|
||||
|
||||
parsedPacket.data.resize(packet.data.length);
|
||||
[packet.data getBytes:parsedPacket.data.data() length:packet.data.length];
|
||||
|
||||
parsedPacket.decodedData.resize(packet.decodedData.length);
|
||||
[packet.decodedData getBytes:parsedPacket.decodedData.data() length:packet.decodedData.length];
|
||||
|
||||
parsedPackets.push_back(std::move(parsedPacket));
|
||||
parsedParts.push_back(std::move(parsedPart));
|
||||
}
|
||||
((tgcalls::GroupInstanceCustomImpl *)(_instance.get()))->addBroadcastPackets(std::move(parsedPackets));
|
||||
((tgcalls::GroupInstanceCustomImpl *)(_instance.get()))->addBroadcastParts(std::move(parsedParts));
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1434,14 +1444,13 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
|
||||
|
||||
@end
|
||||
|
||||
@implementation OngoingGroupCallBroadcastPacket
|
||||
@implementation OngoingGroupCallBroadcastPart
|
||||
|
||||
- (instancetype _Nonnull)initWithNumSamples:(int)numSamples data:(NSData * _Nonnull)data decodedData:(NSData * _Nonnull)decodedData {
|
||||
- (instancetype _Nonnull)initWithTimestamp:(int32_t)timestamp oggData:(NSData * _Nonnull)oggData {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_numSamples = numSamples;
|
||||
_data = data;
|
||||
_decodedData = decodedData;
|
||||
_timestamp = timestamp;
|
||||
_oggData = oggData;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 35a4725bd37e4e0a07eb2d3ba626b80f9dc73fce
|
||||
Subproject commit adbf89527e97bf082115324dfdceed45a75a5e71
|
20
third-party/ogg/BUILD
vendored
Normal file
20
third-party/ogg/BUILD
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
objc_library(
|
||||
name = "ogg",
|
||||
enable_modules = True,
|
||||
module_name = "ogg",
|
||||
srcs = glob([
|
||||
"Sources/*.c",
|
||||
]),
|
||||
hdrs = glob([
|
||||
"include/ogg/*.h",
|
||||
]),
|
||||
includes = [
|
||||
"include",
|
||||
],
|
||||
copts = [
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
1087
third-party/ogg/Sources/bitwise.c
vendored
Normal file
1087
third-party/ogg/Sources/bitwise.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
278
third-party/ogg/Sources/crctable.h
vendored
Normal file
278
third-party/ogg/Sources/crctable.h
vendored
Normal file
@ -0,0 +1,278 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2018 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
|
||||
#include <ogg/os_types.h>
|
||||
|
||||
static const ogg_uint32_t crc_lookup[8][256]={
|
||||
{0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
|
||||
0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
|
||||
0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
|
||||
0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
|
||||
0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
|
||||
0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
|
||||
0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
|
||||
0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
|
||||
0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
|
||||
0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
|
||||
0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
|
||||
0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
|
||||
0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
|
||||
0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
|
||||
0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
|
||||
0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
|
||||
0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
|
||||
0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
|
||||
0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
|
||||
0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
|
||||
0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
|
||||
0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
|
||||
0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
|
||||
0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
|
||||
0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
|
||||
0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
|
||||
0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
|
||||
0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
|
||||
0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
|
||||
0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
|
||||
0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
|
||||
0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4},
|
||||
|
||||
{0x00000000,0xd219c1dc,0xa0f29e0f,0x72eb5fd3,0x452421a9,0x973de075,0xe5d6bfa6,0x37cf7e7a,
|
||||
0x8a484352,0x5851828e,0x2abadd5d,0xf8a31c81,0xcf6c62fb,0x1d75a327,0x6f9efcf4,0xbd873d28,
|
||||
0x10519b13,0xc2485acf,0xb0a3051c,0x62bac4c0,0x5575baba,0x876c7b66,0xf58724b5,0x279ee569,
|
||||
0x9a19d841,0x4800199d,0x3aeb464e,0xe8f28792,0xdf3df9e8,0x0d243834,0x7fcf67e7,0xadd6a63b,
|
||||
0x20a33626,0xf2baf7fa,0x8051a829,0x524869f5,0x6587178f,0xb79ed653,0xc5758980,0x176c485c,
|
||||
0xaaeb7574,0x78f2b4a8,0x0a19eb7b,0xd8002aa7,0xefcf54dd,0x3dd69501,0x4f3dcad2,0x9d240b0e,
|
||||
0x30f2ad35,0xe2eb6ce9,0x9000333a,0x4219f2e6,0x75d68c9c,0xa7cf4d40,0xd5241293,0x073dd34f,
|
||||
0xbabaee67,0x68a32fbb,0x1a487068,0xc851b1b4,0xff9ecfce,0x2d870e12,0x5f6c51c1,0x8d75901d,
|
||||
0x41466c4c,0x935fad90,0xe1b4f243,0x33ad339f,0x04624de5,0xd67b8c39,0xa490d3ea,0x76891236,
|
||||
0xcb0e2f1e,0x1917eec2,0x6bfcb111,0xb9e570cd,0x8e2a0eb7,0x5c33cf6b,0x2ed890b8,0xfcc15164,
|
||||
0x5117f75f,0x830e3683,0xf1e56950,0x23fca88c,0x1433d6f6,0xc62a172a,0xb4c148f9,0x66d88925,
|
||||
0xdb5fb40d,0x094675d1,0x7bad2a02,0xa9b4ebde,0x9e7b95a4,0x4c625478,0x3e890bab,0xec90ca77,
|
||||
0x61e55a6a,0xb3fc9bb6,0xc117c465,0x130e05b9,0x24c17bc3,0xf6d8ba1f,0x8433e5cc,0x562a2410,
|
||||
0xebad1938,0x39b4d8e4,0x4b5f8737,0x994646eb,0xae893891,0x7c90f94d,0x0e7ba69e,0xdc626742,
|
||||
0x71b4c179,0xa3ad00a5,0xd1465f76,0x035f9eaa,0x3490e0d0,0xe689210c,0x94627edf,0x467bbf03,
|
||||
0xfbfc822b,0x29e543f7,0x5b0e1c24,0x8917ddf8,0xbed8a382,0x6cc1625e,0x1e2a3d8d,0xcc33fc51,
|
||||
0x828cd898,0x50951944,0x227e4697,0xf067874b,0xc7a8f931,0x15b138ed,0x675a673e,0xb543a6e2,
|
||||
0x08c49bca,0xdadd5a16,0xa83605c5,0x7a2fc419,0x4de0ba63,0x9ff97bbf,0xed12246c,0x3f0be5b0,
|
||||
0x92dd438b,0x40c48257,0x322fdd84,0xe0361c58,0xd7f96222,0x05e0a3fe,0x770bfc2d,0xa5123df1,
|
||||
0x189500d9,0xca8cc105,0xb8679ed6,0x6a7e5f0a,0x5db12170,0x8fa8e0ac,0xfd43bf7f,0x2f5a7ea3,
|
||||
0xa22feebe,0x70362f62,0x02dd70b1,0xd0c4b16d,0xe70bcf17,0x35120ecb,0x47f95118,0x95e090c4,
|
||||
0x2867adec,0xfa7e6c30,0x889533e3,0x5a8cf23f,0x6d438c45,0xbf5a4d99,0xcdb1124a,0x1fa8d396,
|
||||
0xb27e75ad,0x6067b471,0x128ceba2,0xc0952a7e,0xf75a5404,0x254395d8,0x57a8ca0b,0x85b10bd7,
|
||||
0x383636ff,0xea2ff723,0x98c4a8f0,0x4add692c,0x7d121756,0xaf0bd68a,0xdde08959,0x0ff94885,
|
||||
0xc3cab4d4,0x11d37508,0x63382adb,0xb121eb07,0x86ee957d,0x54f754a1,0x261c0b72,0xf405caae,
|
||||
0x4982f786,0x9b9b365a,0xe9706989,0x3b69a855,0x0ca6d62f,0xdebf17f3,0xac544820,0x7e4d89fc,
|
||||
0xd39b2fc7,0x0182ee1b,0x7369b1c8,0xa1707014,0x96bf0e6e,0x44a6cfb2,0x364d9061,0xe45451bd,
|
||||
0x59d36c95,0x8bcaad49,0xf921f29a,0x2b383346,0x1cf74d3c,0xceee8ce0,0xbc05d333,0x6e1c12ef,
|
||||
0xe36982f2,0x3170432e,0x439b1cfd,0x9182dd21,0xa64da35b,0x74546287,0x06bf3d54,0xd4a6fc88,
|
||||
0x6921c1a0,0xbb38007c,0xc9d35faf,0x1bca9e73,0x2c05e009,0xfe1c21d5,0x8cf77e06,0x5eeebfda,
|
||||
0xf33819e1,0x2121d83d,0x53ca87ee,0x81d34632,0xb61c3848,0x6405f994,0x16eea647,0xc4f7679b,
|
||||
0x79705ab3,0xab699b6f,0xd982c4bc,0x0b9b0560,0x3c547b1a,0xee4dbac6,0x9ca6e515,0x4ebf24c9},
|
||||
|
||||
{0x00000000,0x01d8ac87,0x03b1590e,0x0269f589,0x0762b21c,0x06ba1e9b,0x04d3eb12,0x050b4795,
|
||||
0x0ec56438,0x0f1dc8bf,0x0d743d36,0x0cac91b1,0x09a7d624,0x087f7aa3,0x0a168f2a,0x0bce23ad,
|
||||
0x1d8ac870,0x1c5264f7,0x1e3b917e,0x1fe33df9,0x1ae87a6c,0x1b30d6eb,0x19592362,0x18818fe5,
|
||||
0x134fac48,0x129700cf,0x10fef546,0x112659c1,0x142d1e54,0x15f5b2d3,0x179c475a,0x1644ebdd,
|
||||
0x3b1590e0,0x3acd3c67,0x38a4c9ee,0x397c6569,0x3c7722fc,0x3daf8e7b,0x3fc67bf2,0x3e1ed775,
|
||||
0x35d0f4d8,0x3408585f,0x3661add6,0x37b90151,0x32b246c4,0x336aea43,0x31031fca,0x30dbb34d,
|
||||
0x269f5890,0x2747f417,0x252e019e,0x24f6ad19,0x21fdea8c,0x2025460b,0x224cb382,0x23941f05,
|
||||
0x285a3ca8,0x2982902f,0x2beb65a6,0x2a33c921,0x2f388eb4,0x2ee02233,0x2c89d7ba,0x2d517b3d,
|
||||
0x762b21c0,0x77f38d47,0x759a78ce,0x7442d449,0x714993dc,0x70913f5b,0x72f8cad2,0x73206655,
|
||||
0x78ee45f8,0x7936e97f,0x7b5f1cf6,0x7a87b071,0x7f8cf7e4,0x7e545b63,0x7c3daeea,0x7de5026d,
|
||||
0x6ba1e9b0,0x6a794537,0x6810b0be,0x69c81c39,0x6cc35bac,0x6d1bf72b,0x6f7202a2,0x6eaaae25,
|
||||
0x65648d88,0x64bc210f,0x66d5d486,0x670d7801,0x62063f94,0x63de9313,0x61b7669a,0x606fca1d,
|
||||
0x4d3eb120,0x4ce61da7,0x4e8fe82e,0x4f5744a9,0x4a5c033c,0x4b84afbb,0x49ed5a32,0x4835f6b5,
|
||||
0x43fbd518,0x4223799f,0x404a8c16,0x41922091,0x44996704,0x4541cb83,0x47283e0a,0x46f0928d,
|
||||
0x50b47950,0x516cd5d7,0x5305205e,0x52dd8cd9,0x57d6cb4c,0x560e67cb,0x54679242,0x55bf3ec5,
|
||||
0x5e711d68,0x5fa9b1ef,0x5dc04466,0x5c18e8e1,0x5913af74,0x58cb03f3,0x5aa2f67a,0x5b7a5afd,
|
||||
0xec564380,0xed8eef07,0xefe71a8e,0xee3fb609,0xeb34f19c,0xeaec5d1b,0xe885a892,0xe95d0415,
|
||||
0xe29327b8,0xe34b8b3f,0xe1227eb6,0xe0fad231,0xe5f195a4,0xe4293923,0xe640ccaa,0xe798602d,
|
||||
0xf1dc8bf0,0xf0042777,0xf26dd2fe,0xf3b57e79,0xf6be39ec,0xf766956b,0xf50f60e2,0xf4d7cc65,
|
||||
0xff19efc8,0xfec1434f,0xfca8b6c6,0xfd701a41,0xf87b5dd4,0xf9a3f153,0xfbca04da,0xfa12a85d,
|
||||
0xd743d360,0xd69b7fe7,0xd4f28a6e,0xd52a26e9,0xd021617c,0xd1f9cdfb,0xd3903872,0xd24894f5,
|
||||
0xd986b758,0xd85e1bdf,0xda37ee56,0xdbef42d1,0xdee40544,0xdf3ca9c3,0xdd555c4a,0xdc8df0cd,
|
||||
0xcac91b10,0xcb11b797,0xc978421e,0xc8a0ee99,0xcdaba90c,0xcc73058b,0xce1af002,0xcfc25c85,
|
||||
0xc40c7f28,0xc5d4d3af,0xc7bd2626,0xc6658aa1,0xc36ecd34,0xc2b661b3,0xc0df943a,0xc10738bd,
|
||||
0x9a7d6240,0x9ba5cec7,0x99cc3b4e,0x981497c9,0x9d1fd05c,0x9cc77cdb,0x9eae8952,0x9f7625d5,
|
||||
0x94b80678,0x9560aaff,0x97095f76,0x96d1f3f1,0x93dab464,0x920218e3,0x906bed6a,0x91b341ed,
|
||||
0x87f7aa30,0x862f06b7,0x8446f33e,0x859e5fb9,0x8095182c,0x814db4ab,0x83244122,0x82fceda5,
|
||||
0x8932ce08,0x88ea628f,0x8a839706,0x8b5b3b81,0x8e507c14,0x8f88d093,0x8de1251a,0x8c39899d,
|
||||
0xa168f2a0,0xa0b05e27,0xa2d9abae,0xa3010729,0xa60a40bc,0xa7d2ec3b,0xa5bb19b2,0xa463b535,
|
||||
0xafad9698,0xae753a1f,0xac1ccf96,0xadc46311,0xa8cf2484,0xa9178803,0xab7e7d8a,0xaaa6d10d,
|
||||
0xbce23ad0,0xbd3a9657,0xbf5363de,0xbe8bcf59,0xbb8088cc,0xba58244b,0xb831d1c2,0xb9e97d45,
|
||||
0xb2275ee8,0xb3fff26f,0xb19607e6,0xb04eab61,0xb545ecf4,0xb49d4073,0xb6f4b5fa,0xb72c197d},
|
||||
|
||||
{0x00000000,0xdc6d9ab7,0xbc1a28d9,0x6077b26e,0x7cf54c05,0xa098d6b2,0xc0ef64dc,0x1c82fe6b,
|
||||
0xf9ea980a,0x258702bd,0x45f0b0d3,0x999d2a64,0x851fd40f,0x59724eb8,0x3905fcd6,0xe5686661,
|
||||
0xf7142da3,0x2b79b714,0x4b0e057a,0x97639fcd,0x8be161a6,0x578cfb11,0x37fb497f,0xeb96d3c8,
|
||||
0x0efeb5a9,0xd2932f1e,0xb2e49d70,0x6e8907c7,0x720bf9ac,0xae66631b,0xce11d175,0x127c4bc2,
|
||||
0xeae946f1,0x3684dc46,0x56f36e28,0x8a9ef49f,0x961c0af4,0x4a719043,0x2a06222d,0xf66bb89a,
|
||||
0x1303defb,0xcf6e444c,0xaf19f622,0x73746c95,0x6ff692fe,0xb39b0849,0xd3ecba27,0x0f812090,
|
||||
0x1dfd6b52,0xc190f1e5,0xa1e7438b,0x7d8ad93c,0x61082757,0xbd65bde0,0xdd120f8e,0x017f9539,
|
||||
0xe417f358,0x387a69ef,0x580ddb81,0x84604136,0x98e2bf5d,0x448f25ea,0x24f89784,0xf8950d33,
|
||||
0xd1139055,0x0d7e0ae2,0x6d09b88c,0xb164223b,0xade6dc50,0x718b46e7,0x11fcf489,0xcd916e3e,
|
||||
0x28f9085f,0xf49492e8,0x94e32086,0x488eba31,0x540c445a,0x8861deed,0xe8166c83,0x347bf634,
|
||||
0x2607bdf6,0xfa6a2741,0x9a1d952f,0x46700f98,0x5af2f1f3,0x869f6b44,0xe6e8d92a,0x3a85439d,
|
||||
0xdfed25fc,0x0380bf4b,0x63f70d25,0xbf9a9792,0xa31869f9,0x7f75f34e,0x1f024120,0xc36fdb97,
|
||||
0x3bfad6a4,0xe7974c13,0x87e0fe7d,0x5b8d64ca,0x470f9aa1,0x9b620016,0xfb15b278,0x277828cf,
|
||||
0xc2104eae,0x1e7dd419,0x7e0a6677,0xa267fcc0,0xbee502ab,0x6288981c,0x02ff2a72,0xde92b0c5,
|
||||
0xcceefb07,0x108361b0,0x70f4d3de,0xac994969,0xb01bb702,0x6c762db5,0x0c019fdb,0xd06c056c,
|
||||
0x3504630d,0xe969f9ba,0x891e4bd4,0x5573d163,0x49f12f08,0x959cb5bf,0xf5eb07d1,0x29869d66,
|
||||
0xa6e63d1d,0x7a8ba7aa,0x1afc15c4,0xc6918f73,0xda137118,0x067eebaf,0x660959c1,0xba64c376,
|
||||
0x5f0ca517,0x83613fa0,0xe3168dce,0x3f7b1779,0x23f9e912,0xff9473a5,0x9fe3c1cb,0x438e5b7c,
|
||||
0x51f210be,0x8d9f8a09,0xede83867,0x3185a2d0,0x2d075cbb,0xf16ac60c,0x911d7462,0x4d70eed5,
|
||||
0xa81888b4,0x74751203,0x1402a06d,0xc86f3ada,0xd4edc4b1,0x08805e06,0x68f7ec68,0xb49a76df,
|
||||
0x4c0f7bec,0x9062e15b,0xf0155335,0x2c78c982,0x30fa37e9,0xec97ad5e,0x8ce01f30,0x508d8587,
|
||||
0xb5e5e3e6,0x69887951,0x09ffcb3f,0xd5925188,0xc910afe3,0x157d3554,0x750a873a,0xa9671d8d,
|
||||
0xbb1b564f,0x6776ccf8,0x07017e96,0xdb6ce421,0xc7ee1a4a,0x1b8380fd,0x7bf43293,0xa799a824,
|
||||
0x42f1ce45,0x9e9c54f2,0xfeebe69c,0x22867c2b,0x3e048240,0xe26918f7,0x821eaa99,0x5e73302e,
|
||||
0x77f5ad48,0xab9837ff,0xcbef8591,0x17821f26,0x0b00e14d,0xd76d7bfa,0xb71ac994,0x6b775323,
|
||||
0x8e1f3542,0x5272aff5,0x32051d9b,0xee68872c,0xf2ea7947,0x2e87e3f0,0x4ef0519e,0x929dcb29,
|
||||
0x80e180eb,0x5c8c1a5c,0x3cfba832,0xe0963285,0xfc14ccee,0x20795659,0x400ee437,0x9c637e80,
|
||||
0x790b18e1,0xa5668256,0xc5113038,0x197caa8f,0x05fe54e4,0xd993ce53,0xb9e47c3d,0x6589e68a,
|
||||
0x9d1cebb9,0x4171710e,0x2106c360,0xfd6b59d7,0xe1e9a7bc,0x3d843d0b,0x5df38f65,0x819e15d2,
|
||||
0x64f673b3,0xb89be904,0xd8ec5b6a,0x0481c1dd,0x18033fb6,0xc46ea501,0xa419176f,0x78748dd8,
|
||||
0x6a08c61a,0xb6655cad,0xd612eec3,0x0a7f7474,0x16fd8a1f,0xca9010a8,0xaae7a2c6,0x768a3871,
|
||||
0x93e25e10,0x4f8fc4a7,0x2ff876c9,0xf395ec7e,0xef171215,0x337a88a2,0x530d3acc,0x8f60a07b},
|
||||
|
||||
{0x00000000,0x490d678d,0x921acf1a,0xdb17a897,0x20f48383,0x69f9e40e,0xb2ee4c99,0xfbe32b14,
|
||||
0x41e90706,0x08e4608b,0xd3f3c81c,0x9afeaf91,0x611d8485,0x2810e308,0xf3074b9f,0xba0a2c12,
|
||||
0x83d20e0c,0xcadf6981,0x11c8c116,0x58c5a69b,0xa3268d8f,0xea2bea02,0x313c4295,0x78312518,
|
||||
0xc23b090a,0x8b366e87,0x5021c610,0x192ca19d,0xe2cf8a89,0xabc2ed04,0x70d54593,0x39d8221e,
|
||||
0x036501af,0x4a686622,0x917fceb5,0xd872a938,0x2391822c,0x6a9ce5a1,0xb18b4d36,0xf8862abb,
|
||||
0x428c06a9,0x0b816124,0xd096c9b3,0x999bae3e,0x6278852a,0x2b75e2a7,0xf0624a30,0xb96f2dbd,
|
||||
0x80b70fa3,0xc9ba682e,0x12adc0b9,0x5ba0a734,0xa0438c20,0xe94eebad,0x3259433a,0x7b5424b7,
|
||||
0xc15e08a5,0x88536f28,0x5344c7bf,0x1a49a032,0xe1aa8b26,0xa8a7ecab,0x73b0443c,0x3abd23b1,
|
||||
0x06ca035e,0x4fc764d3,0x94d0cc44,0xddddabc9,0x263e80dd,0x6f33e750,0xb4244fc7,0xfd29284a,
|
||||
0x47230458,0x0e2e63d5,0xd539cb42,0x9c34accf,0x67d787db,0x2edae056,0xf5cd48c1,0xbcc02f4c,
|
||||
0x85180d52,0xcc156adf,0x1702c248,0x5e0fa5c5,0xa5ec8ed1,0xece1e95c,0x37f641cb,0x7efb2646,
|
||||
0xc4f10a54,0x8dfc6dd9,0x56ebc54e,0x1fe6a2c3,0xe40589d7,0xad08ee5a,0x761f46cd,0x3f122140,
|
||||
0x05af02f1,0x4ca2657c,0x97b5cdeb,0xdeb8aa66,0x255b8172,0x6c56e6ff,0xb7414e68,0xfe4c29e5,
|
||||
0x444605f7,0x0d4b627a,0xd65ccaed,0x9f51ad60,0x64b28674,0x2dbfe1f9,0xf6a8496e,0xbfa52ee3,
|
||||
0x867d0cfd,0xcf706b70,0x1467c3e7,0x5d6aa46a,0xa6898f7e,0xef84e8f3,0x34934064,0x7d9e27e9,
|
||||
0xc7940bfb,0x8e996c76,0x558ec4e1,0x1c83a36c,0xe7608878,0xae6deff5,0x757a4762,0x3c7720ef,
|
||||
0x0d9406bc,0x44996131,0x9f8ec9a6,0xd683ae2b,0x2d60853f,0x646de2b2,0xbf7a4a25,0xf6772da8,
|
||||
0x4c7d01ba,0x05706637,0xde67cea0,0x976aa92d,0x6c898239,0x2584e5b4,0xfe934d23,0xb79e2aae,
|
||||
0x8e4608b0,0xc74b6f3d,0x1c5cc7aa,0x5551a027,0xaeb28b33,0xe7bfecbe,0x3ca84429,0x75a523a4,
|
||||
0xcfaf0fb6,0x86a2683b,0x5db5c0ac,0x14b8a721,0xef5b8c35,0xa656ebb8,0x7d41432f,0x344c24a2,
|
||||
0x0ef10713,0x47fc609e,0x9cebc809,0xd5e6af84,0x2e058490,0x6708e31d,0xbc1f4b8a,0xf5122c07,
|
||||
0x4f180015,0x06156798,0xdd02cf0f,0x940fa882,0x6fec8396,0x26e1e41b,0xfdf64c8c,0xb4fb2b01,
|
||||
0x8d23091f,0xc42e6e92,0x1f39c605,0x5634a188,0xadd78a9c,0xe4daed11,0x3fcd4586,0x76c0220b,
|
||||
0xccca0e19,0x85c76994,0x5ed0c103,0x17dda68e,0xec3e8d9a,0xa533ea17,0x7e244280,0x3729250d,
|
||||
0x0b5e05e2,0x4253626f,0x9944caf8,0xd049ad75,0x2baa8661,0x62a7e1ec,0xb9b0497b,0xf0bd2ef6,
|
||||
0x4ab702e4,0x03ba6569,0xd8adcdfe,0x91a0aa73,0x6a438167,0x234ee6ea,0xf8594e7d,0xb15429f0,
|
||||
0x888c0bee,0xc1816c63,0x1a96c4f4,0x539ba379,0xa878886d,0xe175efe0,0x3a624777,0x736f20fa,
|
||||
0xc9650ce8,0x80686b65,0x5b7fc3f2,0x1272a47f,0xe9918f6b,0xa09ce8e6,0x7b8b4071,0x328627fc,
|
||||
0x083b044d,0x413663c0,0x9a21cb57,0xd32cacda,0x28cf87ce,0x61c2e043,0xbad548d4,0xf3d82f59,
|
||||
0x49d2034b,0x00df64c6,0xdbc8cc51,0x92c5abdc,0x692680c8,0x202be745,0xfb3c4fd2,0xb231285f,
|
||||
0x8be90a41,0xc2e46dcc,0x19f3c55b,0x50fea2d6,0xab1d89c2,0xe210ee4f,0x390746d8,0x700a2155,
|
||||
0xca000d47,0x830d6aca,0x581ac25d,0x1117a5d0,0xeaf48ec4,0xa3f9e949,0x78ee41de,0x31e32653},
|
||||
|
||||
{0x00000000,0x1b280d78,0x36501af0,0x2d781788,0x6ca035e0,0x77883898,0x5af02f10,0x41d82268,
|
||||
0xd9406bc0,0xc26866b8,0xef107130,0xf4387c48,0xb5e05e20,0xaec85358,0x83b044d0,0x989849a8,
|
||||
0xb641ca37,0xad69c74f,0x8011d0c7,0x9b39ddbf,0xdae1ffd7,0xc1c9f2af,0xecb1e527,0xf799e85f,
|
||||
0x6f01a1f7,0x7429ac8f,0x5951bb07,0x4279b67f,0x03a19417,0x1889996f,0x35f18ee7,0x2ed9839f,
|
||||
0x684289d9,0x736a84a1,0x5e129329,0x453a9e51,0x04e2bc39,0x1fcab141,0x32b2a6c9,0x299aabb1,
|
||||
0xb102e219,0xaa2aef61,0x8752f8e9,0x9c7af591,0xdda2d7f9,0xc68ada81,0xebf2cd09,0xf0dac071,
|
||||
0xde0343ee,0xc52b4e96,0xe853591e,0xf37b5466,0xb2a3760e,0xa98b7b76,0x84f36cfe,0x9fdb6186,
|
||||
0x0743282e,0x1c6b2556,0x311332de,0x2a3b3fa6,0x6be31dce,0x70cb10b6,0x5db3073e,0x469b0a46,
|
||||
0xd08513b2,0xcbad1eca,0xe6d50942,0xfdfd043a,0xbc252652,0xa70d2b2a,0x8a753ca2,0x915d31da,
|
||||
0x09c57872,0x12ed750a,0x3f956282,0x24bd6ffa,0x65654d92,0x7e4d40ea,0x53355762,0x481d5a1a,
|
||||
0x66c4d985,0x7decd4fd,0x5094c375,0x4bbcce0d,0x0a64ec65,0x114ce11d,0x3c34f695,0x271cfbed,
|
||||
0xbf84b245,0xa4acbf3d,0x89d4a8b5,0x92fca5cd,0xd32487a5,0xc80c8add,0xe5749d55,0xfe5c902d,
|
||||
0xb8c79a6b,0xa3ef9713,0x8e97809b,0x95bf8de3,0xd467af8b,0xcf4fa2f3,0xe237b57b,0xf91fb803,
|
||||
0x6187f1ab,0x7aaffcd3,0x57d7eb5b,0x4cffe623,0x0d27c44b,0x160fc933,0x3b77debb,0x205fd3c3,
|
||||
0x0e86505c,0x15ae5d24,0x38d64aac,0x23fe47d4,0x622665bc,0x790e68c4,0x54767f4c,0x4f5e7234,
|
||||
0xd7c63b9c,0xccee36e4,0xe196216c,0xfabe2c14,0xbb660e7c,0xa04e0304,0x8d36148c,0x961e19f4,
|
||||
0xa5cb3ad3,0xbee337ab,0x939b2023,0x88b32d5b,0xc96b0f33,0xd243024b,0xff3b15c3,0xe41318bb,
|
||||
0x7c8b5113,0x67a35c6b,0x4adb4be3,0x51f3469b,0x102b64f3,0x0b03698b,0x267b7e03,0x3d53737b,
|
||||
0x138af0e4,0x08a2fd9c,0x25daea14,0x3ef2e76c,0x7f2ac504,0x6402c87c,0x497adff4,0x5252d28c,
|
||||
0xcaca9b24,0xd1e2965c,0xfc9a81d4,0xe7b28cac,0xa66aaec4,0xbd42a3bc,0x903ab434,0x8b12b94c,
|
||||
0xcd89b30a,0xd6a1be72,0xfbd9a9fa,0xe0f1a482,0xa12986ea,0xba018b92,0x97799c1a,0x8c519162,
|
||||
0x14c9d8ca,0x0fe1d5b2,0x2299c23a,0x39b1cf42,0x7869ed2a,0x6341e052,0x4e39f7da,0x5511faa2,
|
||||
0x7bc8793d,0x60e07445,0x4d9863cd,0x56b06eb5,0x17684cdd,0x0c4041a5,0x2138562d,0x3a105b55,
|
||||
0xa28812fd,0xb9a01f85,0x94d8080d,0x8ff00575,0xce28271d,0xd5002a65,0xf8783ded,0xe3503095,
|
||||
0x754e2961,0x6e662419,0x431e3391,0x58363ee9,0x19ee1c81,0x02c611f9,0x2fbe0671,0x34960b09,
|
||||
0xac0e42a1,0xb7264fd9,0x9a5e5851,0x81765529,0xc0ae7741,0xdb867a39,0xf6fe6db1,0xedd660c9,
|
||||
0xc30fe356,0xd827ee2e,0xf55ff9a6,0xee77f4de,0xafafd6b6,0xb487dbce,0x99ffcc46,0x82d7c13e,
|
||||
0x1a4f8896,0x016785ee,0x2c1f9266,0x37379f1e,0x76efbd76,0x6dc7b00e,0x40bfa786,0x5b97aafe,
|
||||
0x1d0ca0b8,0x0624adc0,0x2b5cba48,0x3074b730,0x71ac9558,0x6a849820,0x47fc8fa8,0x5cd482d0,
|
||||
0xc44ccb78,0xdf64c600,0xf21cd188,0xe934dcf0,0xa8ecfe98,0xb3c4f3e0,0x9ebce468,0x8594e910,
|
||||
0xab4d6a8f,0xb06567f7,0x9d1d707f,0x86357d07,0xc7ed5f6f,0xdcc55217,0xf1bd459f,0xea9548e7,
|
||||
0x720d014f,0x69250c37,0x445d1bbf,0x5f7516c7,0x1ead34af,0x058539d7,0x28fd2e5f,0x33d52327},
|
||||
|
||||
{0x00000000,0x4f576811,0x9eaed022,0xd1f9b833,0x399cbdf3,0x76cbd5e2,0xa7326dd1,0xe86505c0,
|
||||
0x73397be6,0x3c6e13f7,0xed97abc4,0xa2c0c3d5,0x4aa5c615,0x05f2ae04,0xd40b1637,0x9b5c7e26,
|
||||
0xe672f7cc,0xa9259fdd,0x78dc27ee,0x378b4fff,0xdfee4a3f,0x90b9222e,0x41409a1d,0x0e17f20c,
|
||||
0x954b8c2a,0xda1ce43b,0x0be55c08,0x44b23419,0xacd731d9,0xe38059c8,0x3279e1fb,0x7d2e89ea,
|
||||
0xc824f22f,0x87739a3e,0x568a220d,0x19dd4a1c,0xf1b84fdc,0xbeef27cd,0x6f169ffe,0x2041f7ef,
|
||||
0xbb1d89c9,0xf44ae1d8,0x25b359eb,0x6ae431fa,0x8281343a,0xcdd65c2b,0x1c2fe418,0x53788c09,
|
||||
0x2e5605e3,0x61016df2,0xb0f8d5c1,0xffafbdd0,0x17cab810,0x589dd001,0x89646832,0xc6330023,
|
||||
0x5d6f7e05,0x12381614,0xc3c1ae27,0x8c96c636,0x64f3c3f6,0x2ba4abe7,0xfa5d13d4,0xb50a7bc5,
|
||||
0x9488f9e9,0xdbdf91f8,0x0a2629cb,0x457141da,0xad14441a,0xe2432c0b,0x33ba9438,0x7cedfc29,
|
||||
0xe7b1820f,0xa8e6ea1e,0x791f522d,0x36483a3c,0xde2d3ffc,0x917a57ed,0x4083efde,0x0fd487cf,
|
||||
0x72fa0e25,0x3dad6634,0xec54de07,0xa303b616,0x4b66b3d6,0x0431dbc7,0xd5c863f4,0x9a9f0be5,
|
||||
0x01c375c3,0x4e941dd2,0x9f6da5e1,0xd03acdf0,0x385fc830,0x7708a021,0xa6f11812,0xe9a67003,
|
||||
0x5cac0bc6,0x13fb63d7,0xc202dbe4,0x8d55b3f5,0x6530b635,0x2a67de24,0xfb9e6617,0xb4c90e06,
|
||||
0x2f957020,0x60c21831,0xb13ba002,0xfe6cc813,0x1609cdd3,0x595ea5c2,0x88a71df1,0xc7f075e0,
|
||||
0xbadefc0a,0xf589941b,0x24702c28,0x6b274439,0x834241f9,0xcc1529e8,0x1dec91db,0x52bbf9ca,
|
||||
0xc9e787ec,0x86b0effd,0x574957ce,0x181e3fdf,0xf07b3a1f,0xbf2c520e,0x6ed5ea3d,0x2182822c,
|
||||
0x2dd0ee65,0x62878674,0xb37e3e47,0xfc295656,0x144c5396,0x5b1b3b87,0x8ae283b4,0xc5b5eba5,
|
||||
0x5ee99583,0x11befd92,0xc04745a1,0x8f102db0,0x67752870,0x28224061,0xf9dbf852,0xb68c9043,
|
||||
0xcba219a9,0x84f571b8,0x550cc98b,0x1a5ba19a,0xf23ea45a,0xbd69cc4b,0x6c907478,0x23c71c69,
|
||||
0xb89b624f,0xf7cc0a5e,0x2635b26d,0x6962da7c,0x8107dfbc,0xce50b7ad,0x1fa90f9e,0x50fe678f,
|
||||
0xe5f41c4a,0xaaa3745b,0x7b5acc68,0x340da479,0xdc68a1b9,0x933fc9a8,0x42c6719b,0x0d91198a,
|
||||
0x96cd67ac,0xd99a0fbd,0x0863b78e,0x4734df9f,0xaf51da5f,0xe006b24e,0x31ff0a7d,0x7ea8626c,
|
||||
0x0386eb86,0x4cd18397,0x9d283ba4,0xd27f53b5,0x3a1a5675,0x754d3e64,0xa4b48657,0xebe3ee46,
|
||||
0x70bf9060,0x3fe8f871,0xee114042,0xa1462853,0x49232d93,0x06744582,0xd78dfdb1,0x98da95a0,
|
||||
0xb958178c,0xf60f7f9d,0x27f6c7ae,0x68a1afbf,0x80c4aa7f,0xcf93c26e,0x1e6a7a5d,0x513d124c,
|
||||
0xca616c6a,0x8536047b,0x54cfbc48,0x1b98d459,0xf3fdd199,0xbcaab988,0x6d5301bb,0x220469aa,
|
||||
0x5f2ae040,0x107d8851,0xc1843062,0x8ed35873,0x66b65db3,0x29e135a2,0xf8188d91,0xb74fe580,
|
||||
0x2c139ba6,0x6344f3b7,0xb2bd4b84,0xfdea2395,0x158f2655,0x5ad84e44,0x8b21f677,0xc4769e66,
|
||||
0x717ce5a3,0x3e2b8db2,0xefd23581,0xa0855d90,0x48e05850,0x07b73041,0xd64e8872,0x9919e063,
|
||||
0x02459e45,0x4d12f654,0x9ceb4e67,0xd3bc2676,0x3bd923b6,0x748e4ba7,0xa577f394,0xea209b85,
|
||||
0x970e126f,0xd8597a7e,0x09a0c24d,0x46f7aa5c,0xae92af9c,0xe1c5c78d,0x303c7fbe,0x7f6b17af,
|
||||
0xe4376989,0xab600198,0x7a99b9ab,0x35ced1ba,0xddabd47a,0x92fcbc6b,0x43050458,0x0c526c49},
|
||||
|
||||
{0x00000000,0x5ba1dcca,0xb743b994,0xece2655e,0x6a466e9f,0x31e7b255,0xdd05d70b,0x86a40bc1,
|
||||
0xd48cdd3e,0x8f2d01f4,0x63cf64aa,0x386eb860,0xbecab3a1,0xe56b6f6b,0x09890a35,0x5228d6ff,
|
||||
0xadd8a7cb,0xf6797b01,0x1a9b1e5f,0x413ac295,0xc79ec954,0x9c3f159e,0x70dd70c0,0x2b7cac0a,
|
||||
0x79547af5,0x22f5a63f,0xce17c361,0x95b61fab,0x1312146a,0x48b3c8a0,0xa451adfe,0xfff07134,
|
||||
0x5f705221,0x04d18eeb,0xe833ebb5,0xb392377f,0x35363cbe,0x6e97e074,0x8275852a,0xd9d459e0,
|
||||
0x8bfc8f1f,0xd05d53d5,0x3cbf368b,0x671eea41,0xe1bae180,0xba1b3d4a,0x56f95814,0x0d5884de,
|
||||
0xf2a8f5ea,0xa9092920,0x45eb4c7e,0x1e4a90b4,0x98ee9b75,0xc34f47bf,0x2fad22e1,0x740cfe2b,
|
||||
0x262428d4,0x7d85f41e,0x91679140,0xcac64d8a,0x4c62464b,0x17c39a81,0xfb21ffdf,0xa0802315,
|
||||
0xbee0a442,0xe5417888,0x09a31dd6,0x5202c11c,0xd4a6cadd,0x8f071617,0x63e57349,0x3844af83,
|
||||
0x6a6c797c,0x31cda5b6,0xdd2fc0e8,0x868e1c22,0x002a17e3,0x5b8bcb29,0xb769ae77,0xecc872bd,
|
||||
0x13380389,0x4899df43,0xa47bba1d,0xffda66d7,0x797e6d16,0x22dfb1dc,0xce3dd482,0x959c0848,
|
||||
0xc7b4deb7,0x9c15027d,0x70f76723,0x2b56bbe9,0xadf2b028,0xf6536ce2,0x1ab109bc,0x4110d576,
|
||||
0xe190f663,0xba312aa9,0x56d34ff7,0x0d72933d,0x8bd698fc,0xd0774436,0x3c952168,0x6734fda2,
|
||||
0x351c2b5d,0x6ebdf797,0x825f92c9,0xd9fe4e03,0x5f5a45c2,0x04fb9908,0xe819fc56,0xb3b8209c,
|
||||
0x4c4851a8,0x17e98d62,0xfb0be83c,0xa0aa34f6,0x260e3f37,0x7dafe3fd,0x914d86a3,0xcaec5a69,
|
||||
0x98c48c96,0xc365505c,0x2f873502,0x7426e9c8,0xf282e209,0xa9233ec3,0x45c15b9d,0x1e608757,
|
||||
0x79005533,0x22a189f9,0xce43eca7,0x95e2306d,0x13463bac,0x48e7e766,0xa4058238,0xffa45ef2,
|
||||
0xad8c880d,0xf62d54c7,0x1acf3199,0x416eed53,0xc7cae692,0x9c6b3a58,0x70895f06,0x2b2883cc,
|
||||
0xd4d8f2f8,0x8f792e32,0x639b4b6c,0x383a97a6,0xbe9e9c67,0xe53f40ad,0x09dd25f3,0x527cf939,
|
||||
0x00542fc6,0x5bf5f30c,0xb7179652,0xecb64a98,0x6a124159,0x31b39d93,0xdd51f8cd,0x86f02407,
|
||||
0x26700712,0x7dd1dbd8,0x9133be86,0xca92624c,0x4c36698d,0x1797b547,0xfb75d019,0xa0d40cd3,
|
||||
0xf2fcda2c,0xa95d06e6,0x45bf63b8,0x1e1ebf72,0x98bab4b3,0xc31b6879,0x2ff90d27,0x7458d1ed,
|
||||
0x8ba8a0d9,0xd0097c13,0x3ceb194d,0x674ac587,0xe1eece46,0xba4f128c,0x56ad77d2,0x0d0cab18,
|
||||
0x5f247de7,0x0485a12d,0xe867c473,0xb3c618b9,0x35621378,0x6ec3cfb2,0x8221aaec,0xd9807626,
|
||||
0xc7e0f171,0x9c412dbb,0x70a348e5,0x2b02942f,0xada69fee,0xf6074324,0x1ae5267a,0x4144fab0,
|
||||
0x136c2c4f,0x48cdf085,0xa42f95db,0xff8e4911,0x792a42d0,0x228b9e1a,0xce69fb44,0x95c8278e,
|
||||
0x6a3856ba,0x31998a70,0xdd7bef2e,0x86da33e4,0x007e3825,0x5bdfe4ef,0xb73d81b1,0xec9c5d7b,
|
||||
0xbeb48b84,0xe515574e,0x09f73210,0x5256eeda,0xd4f2e51b,0x8f5339d1,0x63b15c8f,0x38108045,
|
||||
0x9890a350,0xc3317f9a,0x2fd31ac4,0x7472c60e,0xf2d6cdcf,0xa9771105,0x4595745b,0x1e34a891,
|
||||
0x4c1c7e6e,0x17bda2a4,0xfb5fc7fa,0xa0fe1b30,0x265a10f1,0x7dfbcc3b,0x9119a965,0xcab875af,
|
||||
0x3548049b,0x6ee9d851,0x820bbd0f,0xd9aa61c5,0x5f0e6a04,0x04afb6ce,0xe84dd390,0xb3ec0f5a,
|
||||
0xe1c4d9a5,0xba65056f,0x56876031,0x0d26bcfb,0x8b82b73a,0xd0236bf0,0x3cc10eae,0x6760d264}};
|
2109
third-party/ogg/Sources/framing.c
vendored
Normal file
2109
third-party/ogg/Sources/framing.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
209
third-party/ogg/include/ogg/ogg.h
vendored
Normal file
209
third-party/ogg/include/ogg/ogg.h
vendored
Normal file
@ -0,0 +1,209 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: toplevel libogg include
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OGG_H
|
||||
#define _OGG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <ogg/os_types.h>
|
||||
|
||||
typedef struct {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
} ogg_iovec_t;
|
||||
|
||||
typedef struct {
|
||||
long endbyte;
|
||||
int endbit;
|
||||
|
||||
unsigned char *buffer;
|
||||
unsigned char *ptr;
|
||||
long storage;
|
||||
} oggpack_buffer;
|
||||
|
||||
/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *header;
|
||||
long header_len;
|
||||
unsigned char *body;
|
||||
long body_len;
|
||||
} ogg_page;
|
||||
|
||||
/* ogg_stream_state contains the current encode/decode state of a logical
|
||||
Ogg bitstream **********************************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *body_data; /* bytes from packet bodies */
|
||||
long body_storage; /* storage elements allocated */
|
||||
long body_fill; /* elements stored; fill mark */
|
||||
long body_returned; /* elements of fill returned */
|
||||
|
||||
|
||||
int *lacing_vals; /* The values that will go to the segment table */
|
||||
ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
|
||||
this way, but it is simple coupled to the
|
||||
lacing fifo */
|
||||
long lacing_storage;
|
||||
long lacing_fill;
|
||||
long lacing_packet;
|
||||
long lacing_returned;
|
||||
|
||||
unsigned char header[282]; /* working space for header encode */
|
||||
int header_fill;
|
||||
|
||||
int e_o_s; /* set when we have buffered the last packet in the
|
||||
logical bitstream */
|
||||
int b_o_s; /* set after we've written the initial page
|
||||
of a logical bitstream */
|
||||
long serialno;
|
||||
long pageno;
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a separate abstraction
|
||||
layer) also knows about the gap */
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
} ogg_stream_state;
|
||||
|
||||
/* ogg_packet is used to encapsulate the data and metadata belonging
|
||||
to a single raw Ogg/Vorbis packet *************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *packet;
|
||||
long bytes;
|
||||
long b_o_s;
|
||||
long e_o_s;
|
||||
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a separate abstraction
|
||||
layer) also knows about the gap */
|
||||
} ogg_packet;
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int storage;
|
||||
int fill;
|
||||
int returned;
|
||||
|
||||
int unsynced;
|
||||
int headerbytes;
|
||||
int bodybytes;
|
||||
} ogg_sync_state;
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
|
||||
|
||||
extern void oggpack_writeinit(oggpack_buffer *b);
|
||||
extern int oggpack_writecheck(oggpack_buffer *b);
|
||||
extern void oggpack_writetrunc(oggpack_buffer *b,long bits);
|
||||
extern void oggpack_writealign(oggpack_buffer *b);
|
||||
extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpack_reset(oggpack_buffer *b);
|
||||
extern void oggpack_writeclear(oggpack_buffer *b);
|
||||
extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||
extern long oggpack_look(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_look1(oggpack_buffer *b);
|
||||
extern void oggpack_adv(oggpack_buffer *b,int bits);
|
||||
extern void oggpack_adv1(oggpack_buffer *b);
|
||||
extern long oggpack_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_read1(oggpack_buffer *b);
|
||||
extern long oggpack_bytes(oggpack_buffer *b);
|
||||
extern long oggpack_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
|
||||
|
||||
extern void oggpackB_writeinit(oggpack_buffer *b);
|
||||
extern int oggpackB_writecheck(oggpack_buffer *b);
|
||||
extern void oggpackB_writetrunc(oggpack_buffer *b,long bits);
|
||||
extern void oggpackB_writealign(oggpack_buffer *b);
|
||||
extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpackB_reset(oggpack_buffer *b);
|
||||
extern void oggpackB_writeclear(oggpack_buffer *b);
|
||||
extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||
extern long oggpackB_look(oggpack_buffer *b,int bits);
|
||||
extern long oggpackB_look1(oggpack_buffer *b);
|
||||
extern void oggpackB_adv(oggpack_buffer *b,int bits);
|
||||
extern void oggpackB_adv1(oggpack_buffer *b);
|
||||
extern long oggpackB_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpackB_read1(oggpack_buffer *b);
|
||||
extern long oggpackB_bytes(oggpack_buffer *b);
|
||||
extern long oggpackB_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
|
||||
|
||||
extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
|
||||
extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
|
||||
int count, long e_o_s, ogg_int64_t granulepos);
|
||||
extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
|
||||
extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/
|
||||
|
||||
extern int ogg_sync_init(ogg_sync_state *oy);
|
||||
extern int ogg_sync_clear(ogg_sync_state *oy);
|
||||
extern int ogg_sync_reset(ogg_sync_state *oy);
|
||||
extern int ogg_sync_destroy(ogg_sync_state *oy);
|
||||
extern int ogg_sync_check(ogg_sync_state *oy);
|
||||
|
||||
extern char *ogg_sync_buffer(ogg_sync_state *oy, long size);
|
||||
extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
|
||||
extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
|
||||
extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
|
||||
extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
|
||||
extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: general ***************************/
|
||||
|
||||
extern int ogg_stream_init(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_clear(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_destroy(ogg_stream_state *os);
|
||||
extern int ogg_stream_check(ogg_stream_state *os);
|
||||
extern int ogg_stream_eos(ogg_stream_state *os);
|
||||
|
||||
extern void ogg_page_checksum_set(ogg_page *og);
|
||||
|
||||
extern int ogg_page_version(const ogg_page *og);
|
||||
extern int ogg_page_continued(const ogg_page *og);
|
||||
extern int ogg_page_bos(const ogg_page *og);
|
||||
extern int ogg_page_eos(const ogg_page *og);
|
||||
extern ogg_int64_t ogg_page_granulepos(const ogg_page *og);
|
||||
extern int ogg_page_serialno(const ogg_page *og);
|
||||
extern long ogg_page_pageno(const ogg_page *og);
|
||||
extern int ogg_page_packets(const ogg_page *og);
|
||||
|
||||
extern void ogg_packet_clear(ogg_packet *op);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OGG_H */
|
158
third-party/ogg/include/ogg/os_types.h
vendored
Normal file
158
third-party/ogg/include/ogg/os_types.h
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: Define a consistent set of types on each platform.
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OS_TYPES_H
|
||||
#define _OS_TYPES_H
|
||||
|
||||
/* make it easy on the folks that want to compile the libs with a
|
||||
different malloc than stdlib */
|
||||
#define _ogg_malloc malloc
|
||||
#define _ogg_calloc calloc
|
||||
#define _ogg_realloc realloc
|
||||
#define _ogg_free free
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
# if defined(__CYGWIN__)
|
||||
# include <stdint.h>
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef uint16_t ogg_uint16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
typedef uint64_t ogg_uint64_t;
|
||||
# elif defined(__MINGW32__)
|
||||
# include <sys/types.h>
|
||||
typedef short ogg_int16_t;
|
||||
typedef unsigned short ogg_uint16_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long ogg_int64_t;
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
# elif defined(__MWERKS__)
|
||||
typedef long long ogg_int64_t;
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef short ogg_int16_t;
|
||||
typedef unsigned short ogg_uint16_t;
|
||||
# else
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1800) /* MSVC 2013 and newer */
|
||||
# include <stdint.h>
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef uint16_t ogg_uint16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
typedef uint64_t ogg_uint64_t;
|
||||
# else
|
||||
/* MSVC/Borland */
|
||||
typedef __int64 ogg_int64_t;
|
||||
typedef __int32 ogg_int32_t;
|
||||
typedef unsigned __int32 ogg_uint32_t;
|
||||
typedef unsigned __int64 ogg_uint64_t;
|
||||
typedef __int16 ogg_int16_t;
|
||||
typedef unsigned __int16 ogg_uint16_t;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef uint16_t ogg_uint16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
typedef uint64_t ogg_uint64_t;
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
|
||||
/* Haiku */
|
||||
# include <sys/types.h>
|
||||
typedef short ogg_int16_t;
|
||||
typedef unsigned short ogg_uint16_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long ogg_int64_t;
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
|
||||
/* Be */
|
||||
# include <inttypes.h>
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef uint16_t ogg_uint16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
typedef uint64_t ogg_uint64_t;
|
||||
|
||||
#elif defined (__EMX__)
|
||||
|
||||
/* OS/2 GCC */
|
||||
typedef short ogg_int16_t;
|
||||
typedef unsigned short ogg_uint16_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long ogg_int64_t;
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
|
||||
|
||||
#elif defined (DJGPP)
|
||||
|
||||
/* DJGPP */
|
||||
typedef short ogg_int16_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long ogg_int64_t;
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
|
||||
#elif defined(R5900)
|
||||
|
||||
/* PS2 EE */
|
||||
typedef long ogg_int64_t;
|
||||
typedef unsigned long ogg_uint64_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned ogg_uint32_t;
|
||||
typedef short ogg_int16_t;
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
|
||||
/* Symbian GCC */
|
||||
typedef signed short ogg_int16_t;
|
||||
typedef unsigned short ogg_uint16_t;
|
||||
typedef signed int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long int ogg_int64_t;
|
||||
typedef unsigned long long int ogg_uint64_t;
|
||||
|
||||
#elif defined(__TMS320C6X__)
|
||||
|
||||
/* TI C64x compiler */
|
||||
typedef signed short ogg_int16_t;
|
||||
typedef unsigned short ogg_uint16_t;
|
||||
typedef signed int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long int ogg_int64_t;
|
||||
typedef unsigned long long int ogg_uint64_t;
|
||||
|
||||
#else
|
||||
|
||||
# include <ogg/config_types.h>
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _OS_TYPES_H */
|
25
third-party/opusfile/BUILD
vendored
Normal file
25
third-party/opusfile/BUILD
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
objc_library(
|
||||
name = "opusfile",
|
||||
enable_modules = True,
|
||||
module_name = "opusfile",
|
||||
srcs = glob([
|
||||
"Sources/*.c",
|
||||
]),
|
||||
hdrs = glob([
|
||||
"include/opusfile/*.h",
|
||||
]),
|
||||
includes = [
|
||||
"include",
|
||||
],
|
||||
copts = [
|
||||
"-Ithird-party/opusfile/include/opusfile",
|
||||
],
|
||||
deps = [
|
||||
"//third-party/ogg:ogg",
|
||||
"//third-party/opus:opus",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
3592
third-party/opusfile/Sources/http.c
vendored
Normal file
3592
third-party/opusfile/Sources/http.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
775
third-party/opusfile/Sources/info.c
vendored
Normal file
775
third-party/opusfile/Sources/info.c
vendored
Normal file
@ -0,0 +1,775 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012-2020 *
|
||||
* by the Xiph.Org Foundation and contributors https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
static unsigned op_parse_uint16le(const unsigned char *_data){
|
||||
return _data[0]|_data[1]<<8;
|
||||
}
|
||||
|
||||
static int op_parse_int16le(const unsigned char *_data){
|
||||
int ret;
|
||||
ret=_data[0]|_data[1]<<8;
|
||||
return (ret^0x8000)-0x8000;
|
||||
}
|
||||
|
||||
static opus_uint32 op_parse_uint32le(const unsigned char *_data){
|
||||
return _data[0]|(opus_uint32)_data[1]<<8|
|
||||
(opus_uint32)_data[2]<<16|(opus_uint32)_data[3]<<24;
|
||||
}
|
||||
|
||||
static opus_uint32 op_parse_uint32be(const unsigned char *_data){
|
||||
return _data[3]|(opus_uint32)_data[2]<<8|
|
||||
(opus_uint32)_data[1]<<16|(opus_uint32)_data[0]<<24;
|
||||
}
|
||||
|
||||
int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){
|
||||
OpusHead head;
|
||||
if(_len<8)return OP_ENOTFORMAT;
|
||||
if(memcmp(_data,"OpusHead",8)!=0)return OP_ENOTFORMAT;
|
||||
if(_len<9)return OP_EBADHEADER;
|
||||
head.version=_data[8];
|
||||
if(head.version>15)return OP_EVERSION;
|
||||
if(_len<19)return OP_EBADHEADER;
|
||||
head.channel_count=_data[9];
|
||||
head.pre_skip=op_parse_uint16le(_data+10);
|
||||
head.input_sample_rate=op_parse_uint32le(_data+12);
|
||||
head.output_gain=op_parse_int16le(_data+16);
|
||||
head.mapping_family=_data[18];
|
||||
if(head.mapping_family==0){
|
||||
if(head.channel_count<1||head.channel_count>2)return OP_EBADHEADER;
|
||||
if(head.version<=1&&_len>19)return OP_EBADHEADER;
|
||||
head.stream_count=1;
|
||||
head.coupled_count=head.channel_count-1;
|
||||
if(_head!=NULL){
|
||||
_head->mapping[0]=0;
|
||||
_head->mapping[1]=1;
|
||||
}
|
||||
}
|
||||
else if(head.mapping_family==1){
|
||||
size_t size;
|
||||
int ci;
|
||||
if(head.channel_count<1||head.channel_count>8)return OP_EBADHEADER;
|
||||
size=21+head.channel_count;
|
||||
if(_len<size||head.version<=1&&_len>size)return OP_EBADHEADER;
|
||||
head.stream_count=_data[19];
|
||||
if(head.stream_count<1)return OP_EBADHEADER;
|
||||
head.coupled_count=_data[20];
|
||||
if(head.coupled_count>head.stream_count)return OP_EBADHEADER;
|
||||
for(ci=0;ci<head.channel_count;ci++){
|
||||
if(_data[21+ci]>=head.stream_count+head.coupled_count
|
||||
&&_data[21+ci]!=255){
|
||||
return OP_EBADHEADER;
|
||||
}
|
||||
}
|
||||
if(_head!=NULL)memcpy(_head->mapping,_data+21,head.channel_count);
|
||||
}
|
||||
/*General purpose players should not attempt to play back content with
|
||||
channel mapping family 255.*/
|
||||
else if(head.mapping_family==255)return OP_EIMPL;
|
||||
/*No other channel mapping families are currently defined.*/
|
||||
else return OP_EBADHEADER;
|
||||
if(_head!=NULL)memcpy(_head,&head,head.mapping-(unsigned char *)&head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void opus_tags_init(OpusTags *_tags){
|
||||
memset(_tags,0,sizeof(*_tags));
|
||||
}
|
||||
|
||||
void opus_tags_clear(OpusTags *_tags){
|
||||
int ncomments;
|
||||
int ci;
|
||||
ncomments=_tags->comments;
|
||||
if(_tags->user_comments!=NULL)ncomments++;
|
||||
else{
|
||||
OP_ASSERT(ncomments==0);
|
||||
}
|
||||
for(ci=ncomments;ci-->0;)_ogg_free(_tags->user_comments[ci]);
|
||||
_ogg_free(_tags->user_comments);
|
||||
_ogg_free(_tags->comment_lengths);
|
||||
_ogg_free(_tags->vendor);
|
||||
}
|
||||
|
||||
/*Ensure there's room for up to _ncomments comments.*/
|
||||
static int op_tags_ensure_capacity(OpusTags *_tags,size_t _ncomments){
|
||||
char **user_comments;
|
||||
int *comment_lengths;
|
||||
int cur_ncomments;
|
||||
size_t size;
|
||||
if(OP_UNLIKELY(_ncomments>=(size_t)INT_MAX))return OP_EFAULT;
|
||||
size=sizeof(*_tags->comment_lengths)*(_ncomments+1);
|
||||
if(size/sizeof(*_tags->comment_lengths)!=_ncomments+1)return OP_EFAULT;
|
||||
cur_ncomments=_tags->comments;
|
||||
/*We only support growing.
|
||||
Trimming requires cleaning up the allocated strings in the old space, and
|
||||
is best handled separately if it's ever needed.*/
|
||||
OP_ASSERT(_ncomments>=(size_t)cur_ncomments);
|
||||
comment_lengths=(int *)_ogg_realloc(_tags->comment_lengths,size);
|
||||
if(OP_UNLIKELY(comment_lengths==NULL))return OP_EFAULT;
|
||||
if(_tags->comment_lengths==NULL){
|
||||
OP_ASSERT(cur_ncomments==0);
|
||||
comment_lengths[cur_ncomments]=0;
|
||||
}
|
||||
comment_lengths[_ncomments]=comment_lengths[cur_ncomments];
|
||||
_tags->comment_lengths=comment_lengths;
|
||||
size=sizeof(*_tags->user_comments)*(_ncomments+1);
|
||||
if(size/sizeof(*_tags->user_comments)!=_ncomments+1)return OP_EFAULT;
|
||||
user_comments=(char **)_ogg_realloc(_tags->user_comments,size);
|
||||
if(OP_UNLIKELY(user_comments==NULL))return OP_EFAULT;
|
||||
if(_tags->user_comments==NULL){
|
||||
OP_ASSERT(cur_ncomments==0);
|
||||
user_comments[cur_ncomments]=NULL;
|
||||
}
|
||||
user_comments[_ncomments]=user_comments[cur_ncomments];
|
||||
_tags->user_comments=user_comments;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Duplicate a (possibly non-NUL terminated) string with a known length.*/
|
||||
static char *op_strdup_with_len(const char *_s,size_t _len){
|
||||
size_t size;
|
||||
char *ret;
|
||||
size=sizeof(*ret)*(_len+1);
|
||||
if(OP_UNLIKELY(size<_len))return NULL;
|
||||
ret=(char *)_ogg_malloc(size);
|
||||
if(OP_LIKELY(ret!=NULL)){
|
||||
ret=(char *)memcpy(ret,_s,sizeof(*ret)*_len);
|
||||
ret[_len]='\0';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*The actual implementation of opus_tags_parse().
|
||||
Unlike the public API, this function requires _tags to already be
|
||||
initialized, modifies its contents before success is guaranteed, and assumes
|
||||
the caller will clear it on error.*/
|
||||
static int opus_tags_parse_impl(OpusTags *_tags,
|
||||
const unsigned char *_data,size_t _len){
|
||||
opus_uint32 count;
|
||||
size_t len;
|
||||
int ncomments;
|
||||
int ci;
|
||||
len=_len;
|
||||
if(len<8)return OP_ENOTFORMAT;
|
||||
if(memcmp(_data,"OpusTags",8)!=0)return OP_ENOTFORMAT;
|
||||
if(len<16)return OP_EBADHEADER;
|
||||
_data+=8;
|
||||
len-=8;
|
||||
count=op_parse_uint32le(_data);
|
||||
_data+=4;
|
||||
len-=4;
|
||||
if(count>len)return OP_EBADHEADER;
|
||||
if(_tags!=NULL){
|
||||
_tags->vendor=op_strdup_with_len((char *)_data,count);
|
||||
if(_tags->vendor==NULL)return OP_EFAULT;
|
||||
}
|
||||
_data+=count;
|
||||
len-=count;
|
||||
if(len<4)return OP_EBADHEADER;
|
||||
count=op_parse_uint32le(_data);
|
||||
_data+=4;
|
||||
len-=4;
|
||||
/*Check to make sure there's minimally sufficient data left in the packet.*/
|
||||
if(count>len>>2)return OP_EBADHEADER;
|
||||
/*Check for overflow (the API limits this to an int).*/
|
||||
if(count>(opus_uint32)INT_MAX-1)return OP_EFAULT;
|
||||
if(_tags!=NULL){
|
||||
int ret;
|
||||
ret=op_tags_ensure_capacity(_tags,count);
|
||||
if(ret<0)return ret;
|
||||
}
|
||||
ncomments=(int)count;
|
||||
for(ci=0;ci<ncomments;ci++){
|
||||
/*Check to make sure there's minimally sufficient data left in the packet.*/
|
||||
if((size_t)(ncomments-ci)>len>>2)return OP_EBADHEADER;
|
||||
count=op_parse_uint32le(_data);
|
||||
_data+=4;
|
||||
len-=4;
|
||||
if(count>len)return OP_EBADHEADER;
|
||||
/*Check for overflow (the API limits this to an int).*/
|
||||
if(count>(opus_uint32)INT_MAX)return OP_EFAULT;
|
||||
if(_tags!=NULL){
|
||||
_tags->user_comments[ci]=op_strdup_with_len((char *)_data,count);
|
||||
if(_tags->user_comments[ci]==NULL)return OP_EFAULT;
|
||||
_tags->comment_lengths[ci]=(int)count;
|
||||
_tags->comments=ci+1;
|
||||
/*Needed by opus_tags_clear() if we fail before parsing the (optional)
|
||||
binary metadata.*/
|
||||
_tags->user_comments[ci+1]=NULL;
|
||||
}
|
||||
_data+=count;
|
||||
len-=count;
|
||||
}
|
||||
if(len>0&&(_data[0]&1)){
|
||||
if(len>(opus_uint32)INT_MAX)return OP_EFAULT;
|
||||
if(_tags!=NULL){
|
||||
_tags->user_comments[ncomments]=(char *)_ogg_malloc(len);
|
||||
if(OP_UNLIKELY(_tags->user_comments[ncomments]==NULL))return OP_EFAULT;
|
||||
memcpy(_tags->user_comments[ncomments],_data,len);
|
||||
_tags->comment_lengths[ncomments]=(int)len;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opus_tags_parse(OpusTags *_tags,const unsigned char *_data,size_t _len){
|
||||
if(_tags!=NULL){
|
||||
OpusTags tags;
|
||||
int ret;
|
||||
opus_tags_init(&tags);
|
||||
ret=opus_tags_parse_impl(&tags,_data,_len);
|
||||
if(ret<0)opus_tags_clear(&tags);
|
||||
else *_tags=*&tags;
|
||||
return ret;
|
||||
}
|
||||
else return opus_tags_parse_impl(NULL,_data,_len);
|
||||
}
|
||||
|
||||
/*The actual implementation of opus_tags_copy().
|
||||
Unlike the public API, this function requires _dst to already be
|
||||
initialized, modifies its contents before success is guaranteed, and assumes
|
||||
the caller will clear it on error.*/
|
||||
static int opus_tags_copy_impl(OpusTags *_dst,const OpusTags *_src){
|
||||
char *vendor;
|
||||
int ncomments;
|
||||
int ret;
|
||||
int ci;
|
||||
vendor=_src->vendor;
|
||||
_dst->vendor=op_strdup_with_len(vendor,strlen(vendor));
|
||||
if(OP_UNLIKELY(_dst->vendor==NULL))return OP_EFAULT;
|
||||
ncomments=_src->comments;
|
||||
ret=op_tags_ensure_capacity(_dst,ncomments);
|
||||
if(OP_UNLIKELY(ret<0))return ret;
|
||||
for(ci=0;ci<ncomments;ci++){
|
||||
int len;
|
||||
len=_src->comment_lengths[ci];
|
||||
OP_ASSERT(len>=0);
|
||||
_dst->user_comments[ci]=op_strdup_with_len(_src->user_comments[ci],len);
|
||||
if(OP_UNLIKELY(_dst->user_comments[ci]==NULL))return OP_EFAULT;
|
||||
_dst->comment_lengths[ci]=len;
|
||||
_dst->comments=ci+1;
|
||||
}
|
||||
if(_src->comment_lengths!=NULL){
|
||||
int len;
|
||||
len=_src->comment_lengths[ncomments];
|
||||
if(len>0){
|
||||
_dst->user_comments[ncomments]=(char *)_ogg_malloc(len);
|
||||
if(OP_UNLIKELY(_dst->user_comments[ncomments]==NULL))return OP_EFAULT;
|
||||
memcpy(_dst->user_comments[ncomments],_src->user_comments[ncomments],len);
|
||||
_dst->comment_lengths[ncomments]=len;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opus_tags_copy(OpusTags *_dst,const OpusTags *_src){
|
||||
OpusTags dst;
|
||||
int ret;
|
||||
opus_tags_init(&dst);
|
||||
ret=opus_tags_copy_impl(&dst,_src);
|
||||
if(OP_UNLIKELY(ret<0))opus_tags_clear(&dst);
|
||||
else *_dst=*&dst;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value){
|
||||
char *comment;
|
||||
size_t tag_len;
|
||||
size_t value_len;
|
||||
int ncomments;
|
||||
int ret;
|
||||
ncomments=_tags->comments;
|
||||
ret=op_tags_ensure_capacity(_tags,ncomments+1);
|
||||
if(OP_UNLIKELY(ret<0))return ret;
|
||||
tag_len=strlen(_tag);
|
||||
value_len=strlen(_value);
|
||||
/*+2 for '=' and '\0'.*/
|
||||
if(tag_len+value_len<tag_len)return OP_EFAULT;
|
||||
if(tag_len+value_len>(size_t)INT_MAX-2)return OP_EFAULT;
|
||||
comment=(char *)_ogg_malloc(sizeof(*comment)*(tag_len+value_len+2));
|
||||
if(OP_UNLIKELY(comment==NULL))return OP_EFAULT;
|
||||
memcpy(comment,_tag,sizeof(*comment)*tag_len);
|
||||
comment[tag_len]='=';
|
||||
memcpy(comment+tag_len+1,_value,sizeof(*comment)*(value_len+1));
|
||||
_tags->user_comments[ncomments]=comment;
|
||||
_tags->comment_lengths[ncomments]=(int)(tag_len+value_len+1);
|
||||
_tags->comments=ncomments+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opus_tags_add_comment(OpusTags *_tags,const char *_comment){
|
||||
char *comment;
|
||||
int comment_len;
|
||||
int ncomments;
|
||||
int ret;
|
||||
ncomments=_tags->comments;
|
||||
ret=op_tags_ensure_capacity(_tags,ncomments+1);
|
||||
if(OP_UNLIKELY(ret<0))return ret;
|
||||
comment_len=(int)strlen(_comment);
|
||||
comment=op_strdup_with_len(_comment,comment_len);
|
||||
if(OP_UNLIKELY(comment==NULL))return OP_EFAULT;
|
||||
_tags->user_comments[ncomments]=comment;
|
||||
_tags->comment_lengths[ncomments]=comment_len;
|
||||
_tags->comments=ncomments+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opus_tags_set_binary_suffix(OpusTags *_tags,
|
||||
const unsigned char *_data,int _len){
|
||||
unsigned char *binary_suffix_data;
|
||||
int ncomments;
|
||||
int ret;
|
||||
if(_len<0||_len>0&&(_data==NULL||!(_data[0]&1)))return OP_EINVAL;
|
||||
ncomments=_tags->comments;
|
||||
ret=op_tags_ensure_capacity(_tags,ncomments);
|
||||
if(OP_UNLIKELY(ret<0))return ret;
|
||||
binary_suffix_data=
|
||||
(unsigned char *)_ogg_realloc(_tags->user_comments[ncomments],_len);
|
||||
if(OP_UNLIKELY(binary_suffix_data==NULL))return OP_EFAULT;
|
||||
memcpy(binary_suffix_data,_data,_len);
|
||||
_tags->user_comments[ncomments]=(char *)binary_suffix_data;
|
||||
_tags->comment_lengths[ncomments]=_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opus_tagcompare(const char *_tag_name,const char *_comment){
|
||||
size_t tag_len;
|
||||
tag_len=strlen(_tag_name);
|
||||
if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return -1;
|
||||
return opus_tagncompare(_tag_name,(int)tag_len,_comment);
|
||||
}
|
||||
|
||||
int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){
|
||||
int ret;
|
||||
OP_ASSERT(_tag_len>=0);
|
||||
ret=op_strncasecmp(_tag_name,_comment,_tag_len);
|
||||
return ret?ret:'='-_comment[_tag_len];
|
||||
}
|
||||
|
||||
const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){
|
||||
char **user_comments;
|
||||
size_t tag_len;
|
||||
int found;
|
||||
int ncomments;
|
||||
int ci;
|
||||
tag_len=strlen(_tag);
|
||||
if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return NULL;
|
||||
ncomments=_tags->comments;
|
||||
user_comments=_tags->user_comments;
|
||||
found=0;
|
||||
for(ci=0;ci<ncomments;ci++){
|
||||
if(!opus_tagncompare(_tag,(int)tag_len,user_comments[ci])){
|
||||
/*We return a pointer to the data, not a copy.*/
|
||||
if(_count==found++)return user_comments[ci]+tag_len+1;
|
||||
}
|
||||
}
|
||||
/*Didn't find anything.*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int opus_tags_query_count(const OpusTags *_tags,const char *_tag){
|
||||
char **user_comments;
|
||||
size_t tag_len;
|
||||
int found;
|
||||
int ncomments;
|
||||
int ci;
|
||||
tag_len=strlen(_tag);
|
||||
if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return 0;
|
||||
ncomments=_tags->comments;
|
||||
user_comments=_tags->user_comments;
|
||||
found=0;
|
||||
for(ci=0;ci<ncomments;ci++){
|
||||
if(!opus_tagncompare(_tag,(int)tag_len,user_comments[ci]))found++;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
const unsigned char *opus_tags_get_binary_suffix(const OpusTags *_tags,
|
||||
int *_len){
|
||||
int ncomments;
|
||||
int len;
|
||||
ncomments=_tags->comments;
|
||||
len=_tags->comment_lengths==NULL?0:_tags->comment_lengths[ncomments];
|
||||
*_len=len;
|
||||
OP_ASSERT(len==0||_tags->user_comments!=NULL);
|
||||
return len>0?(const unsigned char *)_tags->user_comments[ncomments]:NULL;
|
||||
}
|
||||
|
||||
static int opus_tags_get_gain(const OpusTags *_tags,int *_gain_q8,
|
||||
const char *_tag_name,size_t _tag_len){
|
||||
char **comments;
|
||||
int ncomments;
|
||||
int ci;
|
||||
comments=_tags->user_comments;
|
||||
ncomments=_tags->comments;
|
||||
/*Look for the first valid tag with the name _tag_name and use that.*/
|
||||
for(ci=0;ci<ncomments;ci++){
|
||||
OP_ASSERT(_tag_len<=(size_t)INT_MAX);
|
||||
if(opus_tagncompare(_tag_name,(int)_tag_len,comments[ci])==0){
|
||||
char *p;
|
||||
opus_int32 gain_q8;
|
||||
int negative;
|
||||
p=comments[ci]+_tag_len+1;
|
||||
negative=0;
|
||||
if(*p=='-'){
|
||||
negative=-1;
|
||||
p++;
|
||||
}
|
||||
else if(*p=='+')p++;
|
||||
gain_q8=0;
|
||||
while(*p>='0'&&*p<='9'){
|
||||
gain_q8=10*gain_q8+*p-'0';
|
||||
if(gain_q8>32767-negative)break;
|
||||
p++;
|
||||
}
|
||||
/*This didn't look like a signed 16-bit decimal integer.
|
||||
Not a valid gain tag.*/
|
||||
if(*p!='\0')continue;
|
||||
*_gain_q8=(int)(gain_q8+negative^negative);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return OP_FALSE;
|
||||
}
|
||||
|
||||
int opus_tags_get_album_gain(const OpusTags *_tags,int *_gain_q8){
|
||||
return opus_tags_get_gain(_tags,_gain_q8,"R128_ALBUM_GAIN",15);
|
||||
}
|
||||
|
||||
int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
|
||||
return opus_tags_get_gain(_tags,_gain_q8,"R128_TRACK_GAIN",15);
|
||||
}
|
||||
|
||||
static int op_is_jpeg(const unsigned char *_buf,size_t _buf_sz){
|
||||
return _buf_sz>=3&&memcmp(_buf,"\xFF\xD8\xFF",3)==0;
|
||||
}
|
||||
|
||||
/*Tries to extract the width, height, bits per pixel, and palette size of a
|
||||
JPEG.
|
||||
On failure, simply leaves its outputs unmodified.*/
|
||||
static void op_extract_jpeg_params(const unsigned char *_buf,size_t _buf_sz,
|
||||
opus_uint32 *_width,opus_uint32 *_height,
|
||||
opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){
|
||||
if(op_is_jpeg(_buf,_buf_sz)){
|
||||
size_t offs;
|
||||
offs=2;
|
||||
for(;;){
|
||||
size_t segment_len;
|
||||
int marker;
|
||||
while(offs<_buf_sz&&_buf[offs]!=0xFF)offs++;
|
||||
while(offs<_buf_sz&&_buf[offs]==0xFF)offs++;
|
||||
marker=_buf[offs];
|
||||
offs++;
|
||||
/*If we hit EOI* (end of image), or another SOI* (start of image),
|
||||
or SOS (start of scan), then stop now.*/
|
||||
if(offs>=_buf_sz||(marker>=0xD8&&marker<=0xDA))break;
|
||||
/*RST* (restart markers): skip (no segment length).*/
|
||||
else if(marker>=0xD0&&marker<=0xD7)continue;
|
||||
/*Read the length of the marker segment.*/
|
||||
if(_buf_sz-offs<2)break;
|
||||
segment_len=_buf[offs]<<8|_buf[offs+1];
|
||||
if(segment_len<2||_buf_sz-offs<segment_len)break;
|
||||
if(marker==0xC0||(marker>0xC0&&marker<0xD0&&(marker&3)!=0)){
|
||||
/*Found a SOFn (start of frame) marker segment:*/
|
||||
if(segment_len>=8){
|
||||
*_height=_buf[offs+3]<<8|_buf[offs+4];
|
||||
*_width=_buf[offs+5]<<8|_buf[offs+6];
|
||||
*_depth=_buf[offs+2]*_buf[offs+7];
|
||||
*_colors=0;
|
||||
*_has_palette=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*Other markers: skip the whole marker segment.*/
|
||||
offs+=segment_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int op_is_png(const unsigned char *_buf,size_t _buf_sz){
|
||||
return _buf_sz>=8&&memcmp(_buf,"\x89PNG\x0D\x0A\x1A\x0A",8)==0;
|
||||
}
|
||||
|
||||
/*Tries to extract the width, height, bits per pixel, and palette size of a
|
||||
PNG.
|
||||
On failure, simply leaves its outputs unmodified.*/
|
||||
static void op_extract_png_params(const unsigned char *_buf,size_t _buf_sz,
|
||||
opus_uint32 *_width,opus_uint32 *_height,
|
||||
opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){
|
||||
if(op_is_png(_buf,_buf_sz)){
|
||||
size_t offs;
|
||||
offs=8;
|
||||
while(_buf_sz-offs>=12){
|
||||
ogg_uint32_t chunk_len;
|
||||
chunk_len=op_parse_uint32be(_buf+offs);
|
||||
if(chunk_len>_buf_sz-(offs+12))break;
|
||||
else if(chunk_len==13&&memcmp(_buf+offs+4,"IHDR",4)==0){
|
||||
int color_type;
|
||||
*_width=op_parse_uint32be(_buf+offs+8);
|
||||
*_height=op_parse_uint32be(_buf+offs+12);
|
||||
color_type=_buf[offs+17];
|
||||
if(color_type==3){
|
||||
*_depth=24;
|
||||
*_has_palette=1;
|
||||
}
|
||||
else{
|
||||
int sample_depth;
|
||||
sample_depth=_buf[offs+16];
|
||||
if(color_type==0)*_depth=sample_depth;
|
||||
else if(color_type==2)*_depth=sample_depth*3;
|
||||
else if(color_type==4)*_depth=sample_depth*2;
|
||||
else if(color_type==6)*_depth=sample_depth*4;
|
||||
*_colors=0;
|
||||
*_has_palette=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(*_has_palette>0&&memcmp(_buf+offs+4,"PLTE",4)==0){
|
||||
*_colors=chunk_len/3;
|
||||
break;
|
||||
}
|
||||
offs+=12+chunk_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int op_is_gif(const unsigned char *_buf,size_t _buf_sz){
|
||||
return _buf_sz>=6&&(memcmp(_buf,"GIF87a",6)==0||memcmp(_buf,"GIF89a",6)==0);
|
||||
}
|
||||
|
||||
/*Tries to extract the width, height, bits per pixel, and palette size of a
|
||||
GIF.
|
||||
On failure, simply leaves its outputs unmodified.*/
|
||||
static void op_extract_gif_params(const unsigned char *_buf,size_t _buf_sz,
|
||||
opus_uint32 *_width,opus_uint32 *_height,
|
||||
opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){
|
||||
if(op_is_gif(_buf,_buf_sz)&&_buf_sz>=14){
|
||||
*_width=_buf[6]|_buf[7]<<8;
|
||||
*_height=_buf[8]|_buf[9]<<8;
|
||||
/*libFLAC hard-codes the depth to 24.*/
|
||||
*_depth=24;
|
||||
*_colors=1<<((_buf[10]&7)+1);
|
||||
*_has_palette=1;
|
||||
}
|
||||
}
|
||||
|
||||
/*The actual implementation of opus_picture_tag_parse().
|
||||
Unlike the public API, this function requires _pic to already be
|
||||
initialized, modifies its contents before success is guaranteed, and assumes
|
||||
the caller will clear it on error.*/
|
||||
static int opus_picture_tag_parse_impl(OpusPictureTag *_pic,const char *_tag,
|
||||
unsigned char *_buf,size_t _buf_sz,size_t _base64_sz){
|
||||
opus_int32 picture_type;
|
||||
opus_uint32 mime_type_length;
|
||||
char *mime_type;
|
||||
opus_uint32 description_length;
|
||||
char *description;
|
||||
opus_uint32 width;
|
||||
opus_uint32 height;
|
||||
opus_uint32 depth;
|
||||
opus_uint32 colors;
|
||||
opus_uint32 data_length;
|
||||
opus_uint32 file_width;
|
||||
opus_uint32 file_height;
|
||||
opus_uint32 file_depth;
|
||||
opus_uint32 file_colors;
|
||||
int format;
|
||||
int has_palette;
|
||||
int colors_set;
|
||||
size_t i;
|
||||
/*Decode the BASE64 data.*/
|
||||
OP_ASSERT(_base64_sz>=11);
|
||||
for(i=0;i<_base64_sz;i++){
|
||||
opus_uint32 value;
|
||||
int j;
|
||||
value=0;
|
||||
for(j=0;j<4;j++){
|
||||
unsigned c;
|
||||
unsigned d;
|
||||
c=(unsigned char)_tag[4*i+j];
|
||||
if(c=='+')d=62;
|
||||
else if(c=='/')d=63;
|
||||
else if(c>='0'&&c<='9')d=52+c-'0';
|
||||
else if(c>='a'&&c<='z')d=26+c-'a';
|
||||
else if(c>='A'&&c<='Z')d=c-'A';
|
||||
else if(c=='='&&3*i+j>_buf_sz)d=0;
|
||||
else return OP_ENOTFORMAT;
|
||||
value=value<<6|d;
|
||||
}
|
||||
_buf[3*i]=(unsigned char)(value>>16);
|
||||
if(3*i+1<_buf_sz){
|
||||
_buf[3*i+1]=(unsigned char)(value>>8);
|
||||
if(3*i+2<_buf_sz)_buf[3*i+2]=(unsigned char)value;
|
||||
}
|
||||
}
|
||||
i=0;
|
||||
picture_type=op_parse_uint32be(_buf+i);
|
||||
i+=4;
|
||||
/*Extract the MIME type.*/
|
||||
mime_type_length=op_parse_uint32be(_buf+i);
|
||||
i+=4;
|
||||
if(mime_type_length>_buf_sz-32)return OP_ENOTFORMAT;
|
||||
mime_type=(char *)_ogg_malloc(sizeof(*_pic->mime_type)*(mime_type_length+1));
|
||||
if(mime_type==NULL)return OP_EFAULT;
|
||||
memcpy(mime_type,_buf+i,sizeof(*mime_type)*mime_type_length);
|
||||
mime_type[mime_type_length]='\0';
|
||||
_pic->mime_type=mime_type;
|
||||
i+=mime_type_length;
|
||||
/*Extract the description string.*/
|
||||
description_length=op_parse_uint32be(_buf+i);
|
||||
i+=4;
|
||||
if(description_length>_buf_sz-mime_type_length-32)return OP_ENOTFORMAT;
|
||||
description=
|
||||
(char *)_ogg_malloc(sizeof(*_pic->mime_type)*(description_length+1));
|
||||
if(description==NULL)return OP_EFAULT;
|
||||
memcpy(description,_buf+i,sizeof(*description)*description_length);
|
||||
description[description_length]='\0';
|
||||
_pic->description=description;
|
||||
i+=description_length;
|
||||
/*Extract the remaining fields.*/
|
||||
width=op_parse_uint32be(_buf+i);
|
||||
i+=4;
|
||||
height=op_parse_uint32be(_buf+i);
|
||||
i+=4;
|
||||
depth=op_parse_uint32be(_buf+i);
|
||||
i+=4;
|
||||
colors=op_parse_uint32be(_buf+i);
|
||||
i+=4;
|
||||
/*If one of these is set, they all must be, but colors==0 is a valid value.*/
|
||||
colors_set=width!=0||height!=0||depth!=0||colors!=0;
|
||||
if((width==0||height==0||depth==0)&&colors_set)return OP_ENOTFORMAT;
|
||||
data_length=op_parse_uint32be(_buf+i);
|
||||
i+=4;
|
||||
if(data_length>_buf_sz-i)return OP_ENOTFORMAT;
|
||||
/*Trim extraneous data so we don't copy it below.*/
|
||||
_buf_sz=i+data_length;
|
||||
/*Attempt to determine the image format.*/
|
||||
format=OP_PIC_FORMAT_UNKNOWN;
|
||||
if(mime_type_length==3&&strcmp(mime_type,"-->")==0){
|
||||
format=OP_PIC_FORMAT_URL;
|
||||
/*Picture type 1 must be a 32x32 PNG.*/
|
||||
if(picture_type==1&&(width!=0||height!=0)&&(width!=32||height!=32)){
|
||||
return OP_ENOTFORMAT;
|
||||
}
|
||||
/*Append a terminating NUL for the convenience of our callers.*/
|
||||
_buf[_buf_sz++]='\0';
|
||||
}
|
||||
else{
|
||||
if(mime_type_length==10
|
||||
&&op_strncasecmp(mime_type,"image/jpeg",mime_type_length)==0){
|
||||
if(op_is_jpeg(_buf+i,data_length))format=OP_PIC_FORMAT_JPEG;
|
||||
}
|
||||
else if(mime_type_length==9
|
||||
&&op_strncasecmp(mime_type,"image/png",mime_type_length)==0){
|
||||
if(op_is_png(_buf+i,data_length))format=OP_PIC_FORMAT_PNG;
|
||||
}
|
||||
else if(mime_type_length==9
|
||||
&&op_strncasecmp(mime_type,"image/gif",mime_type_length)==0){
|
||||
if(op_is_gif(_buf+i,data_length))format=OP_PIC_FORMAT_GIF;
|
||||
}
|
||||
else if(mime_type_length==0||(mime_type_length==6
|
||||
&&op_strncasecmp(mime_type,"image/",mime_type_length)==0)){
|
||||
if(op_is_jpeg(_buf+i,data_length))format=OP_PIC_FORMAT_JPEG;
|
||||
else if(op_is_png(_buf+i,data_length))format=OP_PIC_FORMAT_PNG;
|
||||
else if(op_is_gif(_buf+i,data_length))format=OP_PIC_FORMAT_GIF;
|
||||
}
|
||||
file_width=file_height=file_depth=file_colors=0;
|
||||
has_palette=-1;
|
||||
switch(format){
|
||||
case OP_PIC_FORMAT_JPEG:{
|
||||
op_extract_jpeg_params(_buf+i,data_length,
|
||||
&file_width,&file_height,&file_depth,&file_colors,&has_palette);
|
||||
}break;
|
||||
case OP_PIC_FORMAT_PNG:{
|
||||
op_extract_png_params(_buf+i,data_length,
|
||||
&file_width,&file_height,&file_depth,&file_colors,&has_palette);
|
||||
}break;
|
||||
case OP_PIC_FORMAT_GIF:{
|
||||
op_extract_gif_params(_buf+i,data_length,
|
||||
&file_width,&file_height,&file_depth,&file_colors,&has_palette);
|
||||
}break;
|
||||
}
|
||||
if(has_palette>=0){
|
||||
/*If we successfully extracted these parameters from the image, override
|
||||
any declared values.*/
|
||||
width=file_width;
|
||||
height=file_height;
|
||||
depth=file_depth;
|
||||
colors=file_colors;
|
||||
}
|
||||
/*Picture type 1 must be a 32x32 PNG.*/
|
||||
if(picture_type==1&&(format!=OP_PIC_FORMAT_PNG||width!=32||height!=32)){
|
||||
return OP_ENOTFORMAT;
|
||||
}
|
||||
}
|
||||
/*Adjust _buf_sz instead of using data_length to capture the terminating NUL
|
||||
for URLs.*/
|
||||
_buf_sz-=i;
|
||||
memmove(_buf,_buf+i,sizeof(*_buf)*_buf_sz);
|
||||
_buf=(unsigned char *)_ogg_realloc(_buf,_buf_sz);
|
||||
if(_buf_sz>0&&_buf==NULL)return OP_EFAULT;
|
||||
_pic->type=picture_type;
|
||||
_pic->width=width;
|
||||
_pic->height=height;
|
||||
_pic->depth=depth;
|
||||
_pic->colors=colors;
|
||||
_pic->data_length=data_length;
|
||||
_pic->data=_buf;
|
||||
_pic->format=format;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opus_picture_tag_parse(OpusPictureTag *_pic,const char *_tag){
|
||||
OpusPictureTag pic;
|
||||
unsigned char *buf;
|
||||
size_t base64_sz;
|
||||
size_t buf_sz;
|
||||
size_t tag_length;
|
||||
int ret;
|
||||
if(opus_tagncompare("METADATA_BLOCK_PICTURE",22,_tag)==0)_tag+=23;
|
||||
/*Figure out how much BASE64-encoded data we have.*/
|
||||
tag_length=strlen(_tag);
|
||||
if(tag_length&3)return OP_ENOTFORMAT;
|
||||
base64_sz=tag_length>>2;
|
||||
buf_sz=3*base64_sz;
|
||||
if(buf_sz<32)return OP_ENOTFORMAT;
|
||||
if(_tag[tag_length-1]=='=')buf_sz--;
|
||||
if(_tag[tag_length-2]=='=')buf_sz--;
|
||||
if(buf_sz<32)return OP_ENOTFORMAT;
|
||||
/*Allocate an extra byte to allow appending a terminating NUL to URL data.*/
|
||||
buf=(unsigned char *)_ogg_malloc(sizeof(*buf)*(buf_sz+1));
|
||||
if(buf==NULL)return OP_EFAULT;
|
||||
opus_picture_tag_init(&pic);
|
||||
ret=opus_picture_tag_parse_impl(&pic,_tag,buf,buf_sz,base64_sz);
|
||||
if(ret<0){
|
||||
opus_picture_tag_clear(&pic);
|
||||
_ogg_free(buf);
|
||||
}
|
||||
else *_pic=*&pic;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void opus_picture_tag_init(OpusPictureTag *_pic){
|
||||
memset(_pic,0,sizeof(*_pic));
|
||||
}
|
||||
|
||||
void opus_picture_tag_clear(OpusPictureTag *_pic){
|
||||
_ogg_free(_pic->description);
|
||||
_ogg_free(_pic->mime_type);
|
||||
_ogg_free(_pic->data);
|
||||
}
|
42
third-party/opusfile/Sources/internal.c
vendored
Normal file
42
third-party/opusfile/Sources/internal.c
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012-2020 *
|
||||
* by the Xiph.Org Foundation and contributors https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(OP_ENABLE_ASSERTIONS)
|
||||
void op_fatal_impl(const char *_str,const char *_file,int _line){
|
||||
fprintf(stderr,"Fatal (internal) error in %s, line %i: %s\n",
|
||||
_file,_line,_str);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*A version of strncasecmp() that is guaranteed to only ignore the case of
|
||||
ASCII characters.*/
|
||||
int op_strncasecmp(const char *_a,const char *_b,int _n){
|
||||
int i;
|
||||
for(i=0;i<_n;i++){
|
||||
int a;
|
||||
int b;
|
||||
int d;
|
||||
a=_a[i];
|
||||
b=_b[i];
|
||||
if(a>='a'&&a<='z')a-='a'-'A';
|
||||
if(b>='a'&&b<='z')b-='a'-'A';
|
||||
d=a-b;
|
||||
if(d)return d;
|
||||
}
|
||||
return 0;
|
||||
}
|
259
third-party/opusfile/Sources/internal.h
vendored
Normal file
259
third-party/opusfile/Sources/internal.h
vendored
Normal file
@ -0,0 +1,259 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012-2020 *
|
||||
* by the Xiph.Org Foundation and contributors https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
#if !defined(_opusfile_internal_h)
|
||||
# define _opusfile_internal_h (1)
|
||||
|
||||
# if !defined(_REENTRANT)
|
||||
# define _REENTRANT
|
||||
# endif
|
||||
# if !defined(_GNU_SOURCE)
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
# if !defined(_LARGEFILE_SOURCE)
|
||||
# define _LARGEFILE_SOURCE
|
||||
# endif
|
||||
# if !defined(_LARGEFILE64_SOURCE)
|
||||
# define _LARGEFILE64_SOURCE
|
||||
# endif
|
||||
# if !defined(_FILE_OFFSET_BITS)
|
||||
# define _FILE_OFFSET_BITS 64
|
||||
# endif
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <opusfile.h>
|
||||
|
||||
typedef struct OggOpusLink OggOpusLink;
|
||||
|
||||
# if defined(OP_FIXED_POINT)
|
||||
|
||||
typedef opus_int16 op_sample;
|
||||
|
||||
# else
|
||||
|
||||
typedef float op_sample;
|
||||
|
||||
/*We're using this define to test for libopus 1.1 or later until libopus
|
||||
provides a better mechanism.*/
|
||||
# if defined(OPUS_GET_EXPERT_FRAME_DURATION_REQUEST)
|
||||
/*Enable soft clipping prevention in 16-bit decodes.*/
|
||||
# define OP_SOFT_CLIP (1)
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
# if OP_GNUC_PREREQ(4,2)
|
||||
/*Disable excessive warnings about the order of operations.*/
|
||||
# pragma GCC diagnostic ignored "-Wparentheses"
|
||||
# elif defined(_MSC_VER)
|
||||
/*Disable excessive warnings about the order of operations.*/
|
||||
# pragma warning(disable:4554)
|
||||
/*Disable warnings about "deprecated" POSIX functions.*/
|
||||
# pragma warning(disable:4996)
|
||||
# endif
|
||||
|
||||
# if OP_GNUC_PREREQ(3,0)
|
||||
/*Another alternative is
|
||||
(__builtin_constant_p(_x)?!!(_x):__builtin_expect(!!(_x),1))
|
||||
but that evaluates _x multiple times, which may be bad.*/
|
||||
# define OP_LIKELY(_x) (__builtin_expect(!!(_x),1))
|
||||
# define OP_UNLIKELY(_x) (__builtin_expect(!!(_x),0))
|
||||
# else
|
||||
# define OP_LIKELY(_x) (!!(_x))
|
||||
# define OP_UNLIKELY(_x) (!!(_x))
|
||||
# endif
|
||||
|
||||
# if defined(OP_ENABLE_ASSERTIONS)
|
||||
# if OP_GNUC_PREREQ(2,5)||__SUNPRO_C>=0x590
|
||||
__attribute__((noreturn))
|
||||
# endif
|
||||
void op_fatal_impl(const char *_str,const char *_file,int _line);
|
||||
|
||||
# define OP_FATAL(_str) (op_fatal_impl(_str,__FILE__,__LINE__))
|
||||
|
||||
# define OP_ASSERT(_cond) \
|
||||
do{ \
|
||||
if(OP_UNLIKELY(!(_cond)))OP_FATAL("assertion failed: " #_cond); \
|
||||
} \
|
||||
while(0)
|
||||
# define OP_ALWAYS_TRUE(_cond) OP_ASSERT(_cond)
|
||||
|
||||
# else
|
||||
# define OP_FATAL(_str) abort()
|
||||
# define OP_ASSERT(_cond)
|
||||
# define OP_ALWAYS_TRUE(_cond) ((void)(_cond))
|
||||
# endif
|
||||
|
||||
# define OP_INT64_MAX (2*(((ogg_int64_t)1<<62)-1)|1)
|
||||
# define OP_INT64_MIN (-OP_INT64_MAX-1)
|
||||
# define OP_INT32_MAX (2*(((ogg_int32_t)1<<30)-1)|1)
|
||||
# define OP_INT32_MIN (-OP_INT32_MAX-1)
|
||||
|
||||
# define OP_MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
|
||||
# define OP_MAX(_a,_b) ((_a)>(_b)?(_a):(_b))
|
||||
# define OP_CLAMP(_lo,_x,_hi) (OP_MAX(_lo,OP_MIN(_x,_hi)))
|
||||
|
||||
/*Advance a file offset by the given amount, clamping against OP_INT64_MAX.
|
||||
This is used to advance a known offset by things like OP_CHUNK_SIZE or
|
||||
OP_PAGE_SIZE_MAX, while making sure to avoid signed overflow.
|
||||
It assumes that both _offset and _amount are non-negative.*/
|
||||
#define OP_ADV_OFFSET(_offset,_amount) \
|
||||
(OP_MIN(_offset,OP_INT64_MAX-(_amount))+(_amount))
|
||||
|
||||
/*The maximum channel count for any mapping we'll actually decode.*/
|
||||
# define OP_NCHANNELS_MAX (8)
|
||||
|
||||
/*Initial state.*/
|
||||
# define OP_NOTOPEN (0)
|
||||
/*We've found the first Opus stream in the first link.*/
|
||||
# define OP_PARTOPEN (1)
|
||||
# define OP_OPENED (2)
|
||||
/*We've found the first Opus stream in the current link.*/
|
||||
# define OP_STREAMSET (3)
|
||||
/*We've initialized the decoder for the chosen Opus stream in the current
|
||||
link.*/
|
||||
# define OP_INITSET (4)
|
||||
|
||||
/*Information cached for a single link in a chained Ogg Opus file.
|
||||
We choose the first Opus stream encountered in each link to play back (and
|
||||
require at least one).*/
|
||||
struct OggOpusLink{
|
||||
/*The byte offset of the first header page in this link.*/
|
||||
opus_int64 offset;
|
||||
/*The byte offset of the first data page from the chosen Opus stream in this
|
||||
link (after the headers).*/
|
||||
opus_int64 data_offset;
|
||||
/*The byte offset of the last page from the chosen Opus stream in this link.
|
||||
This is used when seeking to ensure we find a page before the last one, so
|
||||
that end-trimming calculations work properly.
|
||||
This is only valid for seekable sources.*/
|
||||
opus_int64 end_offset;
|
||||
/*The total duration of all prior links.
|
||||
This is always zero for non-seekable sources.*/
|
||||
ogg_int64_t pcm_file_offset;
|
||||
/*The granule position of the last sample.
|
||||
This is only valid for seekable sources.*/
|
||||
ogg_int64_t pcm_end;
|
||||
/*The granule position before the first sample.*/
|
||||
ogg_int64_t pcm_start;
|
||||
/*The serial number.*/
|
||||
ogg_uint32_t serialno;
|
||||
/*The contents of the info header.*/
|
||||
OpusHead head;
|
||||
/*The contents of the comment header.*/
|
||||
OpusTags tags;
|
||||
};
|
||||
|
||||
struct OggOpusFile{
|
||||
/*The callbacks used to access the stream.*/
|
||||
OpusFileCallbacks callbacks;
|
||||
/*A FILE *, memory buffer, etc.*/
|
||||
void *stream;
|
||||
/*Whether or not we can seek with this stream.*/
|
||||
int seekable;
|
||||
/*The number of links in this chained Ogg Opus file.*/
|
||||
int nlinks;
|
||||
/*The cached information from each link in a chained Ogg Opus file.
|
||||
If stream isn't seekable (e.g., it's a pipe), only the current link
|
||||
appears.*/
|
||||
OggOpusLink *links;
|
||||
/*The number of serial numbers from a single link.*/
|
||||
int nserialnos;
|
||||
/*The capacity of the list of serial numbers from a single link.*/
|
||||
int cserialnos;
|
||||
/*Storage for the list of serial numbers from a single link.
|
||||
This is a scratch buffer used when scanning the BOS pages at the start of
|
||||
each link.*/
|
||||
ogg_uint32_t *serialnos;
|
||||
/*This is the current offset of the data processed by the ogg_sync_state.
|
||||
After a seek, this should be set to the target offset so that we can track
|
||||
the byte offsets of subsequent pages.
|
||||
After a call to op_get_next_page(), this will point to the first byte after
|
||||
that page.*/
|
||||
opus_int64 offset;
|
||||
/*The total size of this stream, or -1 if it's unseekable.*/
|
||||
opus_int64 end;
|
||||
/*Used to locate pages in the stream.*/
|
||||
ogg_sync_state oy;
|
||||
/*One of OP_NOTOPEN, OP_PARTOPEN, OP_OPENED, OP_STREAMSET, OP_INITSET.*/
|
||||
int ready_state;
|
||||
/*The current link being played back.*/
|
||||
int cur_link;
|
||||
/*The number of decoded samples to discard from the start of decoding.*/
|
||||
opus_int32 cur_discard_count;
|
||||
/*The granule position of the previous packet (current packet start time).*/
|
||||
ogg_int64_t prev_packet_gp;
|
||||
/*The stream offset of the most recent page with completed packets, or -1.
|
||||
This is only needed to recover continued packet data in the seeking logic,
|
||||
when we use the current position as one of our bounds, only to later
|
||||
discover it was the correct starting point.*/
|
||||
opus_int64 prev_page_offset;
|
||||
/*The number of bytes read since the last bitrate query, including framing.*/
|
||||
opus_int64 bytes_tracked;
|
||||
/*The number of samples decoded since the last bitrate query.*/
|
||||
ogg_int64_t samples_tracked;
|
||||
/*Takes physical pages and welds them into a logical stream of packets.*/
|
||||
ogg_stream_state os;
|
||||
/*Re-timestamped packets from a single page.
|
||||
Buffering these relies on the undocumented libogg behavior that ogg_packet
|
||||
pointers remain valid until the next page is submitted to the
|
||||
ogg_stream_state they came from.*/
|
||||
ogg_packet op[255];
|
||||
/*The index of the next packet to return.*/
|
||||
int op_pos;
|
||||
/*The total number of packets available.*/
|
||||
int op_count;
|
||||
/*Central working state for the packet-to-PCM decoder.*/
|
||||
OpusMSDecoder *od;
|
||||
/*The application-provided packet decode callback.*/
|
||||
op_decode_cb_func decode_cb;
|
||||
/*The application-provided packet decode callback context.*/
|
||||
void *decode_cb_ctx;
|
||||
/*The stream count used to initialize the decoder.*/
|
||||
int od_stream_count;
|
||||
/*The coupled stream count used to initialize the decoder.*/
|
||||
int od_coupled_count;
|
||||
/*The channel count used to initialize the decoder.*/
|
||||
int od_channel_count;
|
||||
/*The channel mapping used to initialize the decoder.*/
|
||||
unsigned char od_mapping[OP_NCHANNELS_MAX];
|
||||
/*The buffered data for one decoded packet.*/
|
||||
op_sample *od_buffer;
|
||||
/*The current position in the decoded buffer.*/
|
||||
int od_buffer_pos;
|
||||
/*The number of valid samples in the decoded buffer.*/
|
||||
int od_buffer_size;
|
||||
/*The type of gain offset to apply.
|
||||
One of OP_HEADER_GAIN, OP_ALBUM_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/
|
||||
int gain_type;
|
||||
/*The offset to apply to the gain.*/
|
||||
opus_int32 gain_offset_q8;
|
||||
/*Internal state for soft clipping and dithering float->short output.*/
|
||||
#if !defined(OP_FIXED_POINT)
|
||||
# if defined(OP_SOFT_CLIP)
|
||||
float clip_state[OP_NCHANNELS_MAX];
|
||||
# endif
|
||||
float dither_a[OP_NCHANNELS_MAX*4];
|
||||
float dither_b[OP_NCHANNELS_MAX*4];
|
||||
opus_uint32 dither_seed;
|
||||
int dither_mute;
|
||||
int dither_disabled;
|
||||
/*The number of channels represented by the internal state.
|
||||
This gets set to 0 whenever anything that would prevent state propagation
|
||||
occurs (switching between the float/short APIs, or between the
|
||||
stereo/multistream APIs).*/
|
||||
int state_channel_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
int op_strncasecmp(const char *_a,const char *_b,int _n);
|
||||
|
||||
#endif
|
3340
third-party/opusfile/Sources/opusfile.c
vendored
Normal file
3340
third-party/opusfile/Sources/opusfile.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
415
third-party/opusfile/Sources/stream.c
vendored
Normal file
415
third-party/opusfile/Sources/stream.c
vendored
Normal file
@ -0,0 +1,415 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2018 *
|
||||
* by the Xiph.Org Foundation and contributors https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: stdio-based convenience library for opening/seeking/decoding
|
||||
last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#if defined(_WIN32)
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
typedef struct OpusMemStream OpusMemStream;
|
||||
|
||||
#define OP_MEM_SIZE_MAX (~(size_t)0>>1)
|
||||
#define OP_MEM_DIFF_MAX ((ptrdiff_t)OP_MEM_SIZE_MAX)
|
||||
|
||||
/*The context information needed to read from a block of memory as if it were a
|
||||
file.*/
|
||||
struct OpusMemStream{
|
||||
/*The block of memory to read from.*/
|
||||
const unsigned char *data;
|
||||
/*The total size of the block.
|
||||
This must be at most OP_MEM_SIZE_MAX to prevent signed overflow while
|
||||
seeking.*/
|
||||
ptrdiff_t size;
|
||||
/*The current file position.
|
||||
This is allowed to be set arbitrarily greater than size (i.e., past the end
|
||||
of the block, though we will not read data past the end of the block), but
|
||||
is not allowed to be negative (i.e., before the beginning of the block).*/
|
||||
ptrdiff_t pos;
|
||||
};
|
||||
|
||||
static int op_fread(void *_stream,unsigned char *_ptr,int _buf_size){
|
||||
FILE *stream;
|
||||
size_t ret;
|
||||
/*Check for empty read.*/
|
||||
if(_buf_size<=0)return 0;
|
||||
stream=(FILE *)_stream;
|
||||
ret=fread(_ptr,1,_buf_size,stream);
|
||||
OP_ASSERT(ret<=(size_t)_buf_size);
|
||||
/*If ret==0 and !feof(stream), there was a read error.*/
|
||||
return ret>0||feof(stream)?(int)ret:OP_EREAD;
|
||||
}
|
||||
|
||||
static int op_fseek(void *_stream,opus_int64 _offset,int _whence){
|
||||
#if defined(_WIN32)
|
||||
/*_fseeki64() is not exposed until MSVCRT80.
|
||||
This is the default starting with MSVC 2005 (_MSC_VER>=1400), but we want
|
||||
to allow linking against older MSVCRT versions for compatibility back to
|
||||
XP without installing extra runtime libraries.
|
||||
i686-pc-mingw32 does not have fseeko() and requires
|
||||
__MSVCRT_VERSION__>=0x800 for _fseeki64(), which screws up linking with
|
||||
other libraries (that don't use MSVCRT80 from MSVC 2005 by default).
|
||||
i686-w64-mingw32 does have fseeko() and respects _FILE_OFFSET_BITS, but I
|
||||
don't know how to detect that at compile time.
|
||||
We could just use fseeko64() (which is available in both), but it's
|
||||
implemented using fgetpos()/fsetpos() just like this code, except without
|
||||
the overflow checking, so we prefer our version.*/
|
||||
opus_int64 pos;
|
||||
/*We don't use fpos_t directly because it might be a struct if __STDC__ is
|
||||
non-zero or _INTEGRAL_MAX_BITS < 64.
|
||||
I'm not certain when the latter is true, but someone could in theory set
|
||||
the former.
|
||||
Either way, it should be binary compatible with a normal 64-bit int (this
|
||||
assumption is not portable, but I believe it is true for MSVCRT).*/
|
||||
OP_ASSERT(sizeof(pos)==sizeof(fpos_t));
|
||||
/*Translate the seek to an absolute one.*/
|
||||
if(_whence==SEEK_CUR){
|
||||
int ret;
|
||||
ret=fgetpos((FILE *)_stream,(fpos_t *)&pos);
|
||||
if(ret)return ret;
|
||||
}
|
||||
else if(_whence==SEEK_END)pos=_filelengthi64(_fileno((FILE *)_stream));
|
||||
else if(_whence==SEEK_SET)pos=0;
|
||||
else return -1;
|
||||
/*Check for errors or overflow.*/
|
||||
if(pos<0||_offset<-pos||_offset>OP_INT64_MAX-pos)return -1;
|
||||
pos+=_offset;
|
||||
return fsetpos((FILE *)_stream,(fpos_t *)&pos);
|
||||
#else
|
||||
/*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer
|
||||
it except on Windows.*/
|
||||
return fseeko((FILE *)_stream,(off_t)_offset,_whence);
|
||||
#endif
|
||||
}
|
||||
|
||||
static opus_int64 op_ftell(void *_stream){
|
||||
#if defined(_WIN32)
|
||||
/*_ftelli64() is not exposed until MSVCRT80, and ftello()/ftello64() have
|
||||
the same problems as fseeko()/fseeko64() in MingW.
|
||||
See above for a more detailed explanation.*/
|
||||
opus_int64 pos;
|
||||
OP_ASSERT(sizeof(pos)==sizeof(fpos_t));
|
||||
return fgetpos((FILE *)_stream,(fpos_t *)&pos)?-1:pos;
|
||||
#else
|
||||
/*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer
|
||||
it except on Windows.*/
|
||||
return ftello((FILE *)_stream);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const OpusFileCallbacks OP_FILE_CALLBACKS={
|
||||
op_fread,
|
||||
op_fseek,
|
||||
op_ftell,
|
||||
(op_close_func)fclose
|
||||
};
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <stddef.h>
|
||||
# include <errno.h>
|
||||
|
||||
/*Windows doesn't accept UTF-8 by default, and we don't have a wchar_t API,
|
||||
so if we just pass the path to fopen(), then there'd be no way for a user
|
||||
of our API to open a Unicode filename.
|
||||
Instead, we translate from UTF-8 to UTF-16 and use Windows' wchar_t API.
|
||||
This makes this API more consistent with platforms where the character set
|
||||
used by fopen is the same as used on disk, which is generally UTF-8, and
|
||||
with our metadata API, which always uses UTF-8.*/
|
||||
static wchar_t *op_utf8_to_utf16(const char *_src){
|
||||
wchar_t *dst;
|
||||
size_t len;
|
||||
len=strlen(_src);
|
||||
/*Worst-case output is 1 wide character per 1 input character.*/
|
||||
dst=(wchar_t *)_ogg_malloc(sizeof(*dst)*(len+1));
|
||||
if(dst!=NULL){
|
||||
size_t si;
|
||||
size_t di;
|
||||
for(di=si=0;si<len;si++){
|
||||
int c0;
|
||||
c0=(unsigned char)_src[si];
|
||||
if(!(c0&0x80)){
|
||||
/*Start byte says this is a 1-byte sequence.*/
|
||||
dst[di++]=(wchar_t)c0;
|
||||
continue;
|
||||
}
|
||||
else{
|
||||
int c1;
|
||||
/*This is safe, because c0 was not 0 and _src is NUL-terminated.*/
|
||||
c1=(unsigned char)_src[si+1];
|
||||
if((c1&0xC0)==0x80){
|
||||
/*Found at least one continuation byte.*/
|
||||
if((c0&0xE0)==0xC0){
|
||||
wchar_t w;
|
||||
/*Start byte says this is a 2-byte sequence.*/
|
||||
w=(c0&0x1F)<<6|c1&0x3F;
|
||||
if(w>=0x80U){
|
||||
/*This is a 2-byte sequence that is not overlong.*/
|
||||
dst[di++]=w;
|
||||
si++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else{
|
||||
int c2;
|
||||
/*This is safe, because c1 was not 0 and _src is NUL-terminated.*/
|
||||
c2=(unsigned char)_src[si+2];
|
||||
if((c2&0xC0)==0x80){
|
||||
/*Found at least two continuation bytes.*/
|
||||
if((c0&0xF0)==0xE0){
|
||||
wchar_t w;
|
||||
/*Start byte says this is a 3-byte sequence.*/
|
||||
w=(c0&0xF)<<12|(c1&0x3F)<<6|c2&0x3F;
|
||||
if(w>=0x800U&&(w<0xD800||w>=0xE000)&&w<0xFFFE){
|
||||
/*This is a 3-byte sequence that is not overlong, not a
|
||||
UTF-16 surrogate pair value, and not a 'not a character'
|
||||
value.*/
|
||||
dst[di++]=w;
|
||||
si+=2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else{
|
||||
int c3;
|
||||
/*This is safe, because c2 was not 0 and _src is
|
||||
NUL-terminated.*/
|
||||
c3=(unsigned char)_src[si+3];
|
||||
if((c3&0xC0)==0x80){
|
||||
/*Found at least three continuation bytes.*/
|
||||
if((c0&0xF8)==0xF0){
|
||||
opus_uint32 w;
|
||||
/*Start byte says this is a 4-byte sequence.*/
|
||||
w=(c0&7)<<18|(c1&0x3F)<<12|(c2&0x3F)<<6&(c3&0x3F);
|
||||
if(w>=0x10000U&&w<0x110000U){
|
||||
/*This is a 4-byte sequence that is not overlong and not
|
||||
greater than the largest valid Unicode code point.
|
||||
Convert it to a surrogate pair.*/
|
||||
w-=0x10000;
|
||||
dst[di++]=(wchar_t)(0xD800+(w>>10));
|
||||
dst[di++]=(wchar_t)(0xDC00+(w&0x3FF));
|
||||
si+=3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*If we got here, we encountered an illegal UTF-8 sequence.*/
|
||||
_ogg_free(dst);
|
||||
return NULL;
|
||||
}
|
||||
OP_ASSERT(di<=len);
|
||||
dst[di]='\0';
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*fsetpos() internally dispatches to the win32 API call SetFilePointer().
|
||||
According to SetFilePointer()'s documentation [0], the behavior is
|
||||
undefined if you do not call it on "a file stored on a seeking device".
|
||||
However, none of the MSVCRT seeking functions verify what kind of file is
|
||||
being used before calling it (which I believe is a bug, since they are
|
||||
supposed to fail and return an error, but it is a bug that has been there
|
||||
for multiple decades now).
|
||||
In practice, SetFilePointer() appears to succeed for things like stdin,
|
||||
even when you are not just piping in a regular file, which prevents the use
|
||||
of this API to determine whether it is possible to seek in a file at all.
|
||||
Therefore, we take the approach recommended by the SetFilePointer()
|
||||
documentation and confirm the type of file using GetFileType() first.
|
||||
We do this once, when the file is opened, and return the corresponding
|
||||
callback in order to avoid an extra win32 API call on every seek in the
|
||||
common case.
|
||||
Hopefully the return value of GetFileType() cannot actually change for the
|
||||
lifetime of a file handle.
|
||||
[0] https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-setfilepointer
|
||||
*/
|
||||
static int op_fseek_fail(void *_stream,opus_int64 _offset,int _whence){
|
||||
(void)_stream;
|
||||
(void)_offset;
|
||||
(void)_whence;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const OpusFileCallbacks OP_UNSEEKABLE_FILE_CALLBACKS={
|
||||
op_fread,
|
||||
op_fseek_fail,
|
||||
op_ftell,
|
||||
(op_close_func)fclose
|
||||
};
|
||||
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_EXTRA_LEAN
|
||||
# include <windows.h>
|
||||
|
||||
static const OpusFileCallbacks *op_get_file_callbacks(FILE *_fp){
|
||||
intptr_t h_file;
|
||||
h_file=_get_osfhandle(_fileno(_fp));
|
||||
if(h_file!=-1
|
||||
&&(GetFileType((HANDLE)h_file)&~FILE_TYPE_REMOTE)==FILE_TYPE_DISK){
|
||||
return &OP_FILE_CALLBACKS;
|
||||
}
|
||||
return &OP_UNSEEKABLE_FILE_CALLBACKS;
|
||||
}
|
||||
#else
|
||||
static const OpusFileCallbacks *op_get_file_callbacks(FILE *_fp){
|
||||
(void)_fp;
|
||||
return &OP_FILE_CALLBACKS;
|
||||
}
|
||||
#endif
|
||||
|
||||
void *op_fopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode){
|
||||
FILE *fp;
|
||||
#if !defined(_WIN32)
|
||||
fp=fopen(_path,_mode);
|
||||
#else
|
||||
fp=NULL;
|
||||
{
|
||||
wchar_t *wpath;
|
||||
wchar_t *wmode;
|
||||
wpath=op_utf8_to_utf16(_path);
|
||||
wmode=op_utf8_to_utf16(_mode);
|
||||
if(wmode==NULL)errno=EINVAL;
|
||||
else if(wpath==NULL)errno=ENOENT;
|
||||
else fp=_wfopen(wpath,wmode);
|
||||
_ogg_free(wmode);
|
||||
_ogg_free(wpath);
|
||||
}
|
||||
#endif
|
||||
if(fp!=NULL)*_cb=*op_get_file_callbacks(fp);
|
||||
return fp;
|
||||
}
|
||||
|
||||
void *op_fdopen(OpusFileCallbacks *_cb,int _fd,const char *_mode){
|
||||
FILE *fp;
|
||||
fp=fdopen(_fd,_mode);
|
||||
if(fp!=NULL)*_cb=*op_get_file_callbacks(fp);
|
||||
return fp;
|
||||
}
|
||||
|
||||
void *op_freopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode,
|
||||
void *_stream){
|
||||
FILE *fp;
|
||||
#if !defined(_WIN32)
|
||||
fp=freopen(_path,_mode,(FILE *)_stream);
|
||||
#else
|
||||
fp=NULL;
|
||||
{
|
||||
wchar_t *wpath;
|
||||
wchar_t *wmode;
|
||||
wpath=op_utf8_to_utf16(_path);
|
||||
wmode=op_utf8_to_utf16(_mode);
|
||||
if(wmode==NULL)errno=EINVAL;
|
||||
else if(wpath==NULL)errno=ENOENT;
|
||||
else fp=_wfreopen(wpath,wmode,(FILE *)_stream);
|
||||
_ogg_free(wmode);
|
||||
_ogg_free(wpath);
|
||||
}
|
||||
#endif
|
||||
if(fp!=NULL)*_cb=*op_get_file_callbacks(fp);
|
||||
return fp;
|
||||
}
|
||||
|
||||
static int op_mem_read(void *_stream,unsigned char *_ptr,int _buf_size){
|
||||
OpusMemStream *stream;
|
||||
ptrdiff_t size;
|
||||
ptrdiff_t pos;
|
||||
stream=(OpusMemStream *)_stream;
|
||||
/*Check for empty read.*/
|
||||
if(_buf_size<=0)return 0;
|
||||
size=stream->size;
|
||||
pos=stream->pos;
|
||||
/*Check for EOF.*/
|
||||
if(pos>=size)return 0;
|
||||
/*Check for a short read.*/
|
||||
_buf_size=(int)OP_MIN(size-pos,_buf_size);
|
||||
memcpy(_ptr,stream->data+pos,_buf_size);
|
||||
pos+=_buf_size;
|
||||
stream->pos=pos;
|
||||
return _buf_size;
|
||||
}
|
||||
|
||||
static int op_mem_seek(void *_stream,opus_int64 _offset,int _whence){
|
||||
OpusMemStream *stream;
|
||||
ptrdiff_t pos;
|
||||
stream=(OpusMemStream *)_stream;
|
||||
pos=stream->pos;
|
||||
OP_ASSERT(pos>=0);
|
||||
switch(_whence){
|
||||
case SEEK_SET:{
|
||||
/*Check for overflow:*/
|
||||
if(_offset<0||_offset>OP_MEM_DIFF_MAX)return -1;
|
||||
pos=(ptrdiff_t)_offset;
|
||||
}break;
|
||||
case SEEK_CUR:{
|
||||
/*Check for overflow:*/
|
||||
if(_offset<-pos||_offset>OP_MEM_DIFF_MAX-pos)return -1;
|
||||
pos=(ptrdiff_t)(pos+_offset);
|
||||
}break;
|
||||
case SEEK_END:{
|
||||
ptrdiff_t size;
|
||||
size=stream->size;
|
||||
OP_ASSERT(size>=0);
|
||||
/*Check for overflow:*/
|
||||
if(_offset<-size||_offset>OP_MEM_DIFF_MAX-size)return -1;
|
||||
pos=(ptrdiff_t)(size+_offset);
|
||||
}break;
|
||||
default:return -1;
|
||||
}
|
||||
stream->pos=pos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static opus_int64 op_mem_tell(void *_stream){
|
||||
OpusMemStream *stream;
|
||||
stream=(OpusMemStream *)_stream;
|
||||
return (ogg_int64_t)stream->pos;
|
||||
}
|
||||
|
||||
static int op_mem_close(void *_stream){
|
||||
_ogg_free(_stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const OpusFileCallbacks OP_MEM_CALLBACKS={
|
||||
op_mem_read,
|
||||
op_mem_seek,
|
||||
op_mem_tell,
|
||||
op_mem_close
|
||||
};
|
||||
|
||||
void *op_mem_stream_create(OpusFileCallbacks *_cb,
|
||||
const unsigned char *_data,size_t _size){
|
||||
OpusMemStream *stream;
|
||||
if(_size>OP_MEM_SIZE_MAX)return NULL;
|
||||
stream=(OpusMemStream *)_ogg_malloc(sizeof(*stream));
|
||||
if(stream!=NULL){
|
||||
*_cb=*&OP_MEM_CALLBACKS;
|
||||
stream->data=_data;
|
||||
stream->size=_size;
|
||||
stream->pos=0;
|
||||
}
|
||||
return stream;
|
||||
}
|
173
third-party/opusfile/Sources/wincerts.c
vendored
Normal file
173
third-party/opusfile/Sources/wincerts.c
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2013-2016 *
|
||||
* by the Xiph.Org Foundation and contributors https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
|
||||
/*This should really be part of OpenSSL, but there's been a patch [1] sitting
|
||||
in their bugtracker for over two years that implements this, without any
|
||||
action, so I'm giving up and re-implementing it locally.
|
||||
|
||||
[1] <https://rt.openssl.org/Ticket/Display.html?id=2158>*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
#if defined(OP_ENABLE_HTTP)&&defined(_WIN32)
|
||||
/*You must include windows.h before wincrypt.h and x509.h.*/
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_EXTRA_LEAN
|
||||
# include <windows.h>
|
||||
/*You must include wincrypt.h before x509.h, too, or X509_NAME doesn't get
|
||||
defined properly.*/
|
||||
# include <wincrypt.h>
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/err.h>
|
||||
# include <openssl/x509.h>
|
||||
|
||||
static int op_capi_new(X509_LOOKUP *_lu){
|
||||
HCERTSTORE h_store;
|
||||
h_store=CertOpenStore(CERT_STORE_PROV_SYSTEM_A,0,0,
|
||||
CERT_STORE_OPEN_EXISTING_FLAG|CERT_STORE_READONLY_FLAG|
|
||||
CERT_SYSTEM_STORE_CURRENT_USER|CERT_STORE_SHARE_CONTEXT_FLAG,"ROOT");
|
||||
if(h_store!=NULL){
|
||||
_lu->method_data=(char *)h_store;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void op_capi_free(X509_LOOKUP *_lu){
|
||||
HCERTSTORE h_store;
|
||||
h_store=(HCERTSTORE)_lu->method_data;
|
||||
# if defined(OP_ENABLE_ASSERTIONS)
|
||||
OP_ALWAYS_TRUE(CertCloseStore(h_store,CERT_CLOSE_STORE_CHECK_FLAG));
|
||||
# else
|
||||
CertCloseStore(h_store,0);
|
||||
# endif
|
||||
}
|
||||
|
||||
static int op_capi_retrieve_by_subject(X509_LOOKUP *_lu,int _type,
|
||||
X509_NAME *_name,X509_OBJECT *_ret){
|
||||
X509_OBJECT *obj;
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
|
||||
obj=X509_OBJECT_retrieve_by_subject(_lu->store_ctx->objs,_type,_name);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
|
||||
if(obj!=NULL){
|
||||
_ret->type=obj->type;
|
||||
memcpy(&_ret->data,&obj->data,sizeof(_ret->data));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int op_capi_get_by_subject(X509_LOOKUP *_lu,int _type,X509_NAME *_name,
|
||||
X509_OBJECT *_ret){
|
||||
HCERTSTORE h_store;
|
||||
if(_name==NULL)return 0;
|
||||
if(_name->bytes==NULL||_name->bytes->length<=0||_name->modified){
|
||||
if(i2d_X509_NAME(_name,NULL)<0)return 0;
|
||||
OP_ASSERT(_name->bytes->length>0);
|
||||
}
|
||||
h_store=(HCERTSTORE)_lu->method_data;
|
||||
switch(_type){
|
||||
case X509_LU_X509:{
|
||||
CERT_NAME_BLOB find_para;
|
||||
PCCERT_CONTEXT cert;
|
||||
X509 *x;
|
||||
int ret;
|
||||
/*Although X509_NAME contains a canon_enc field, that "canonical" [1]
|
||||
encoding was just made up by OpenSSL.
|
||||
It doesn't correspond to any actual standard, and since it drops the
|
||||
initial sequence header, won't be recognized by the Crypto API.
|
||||
The assumption here is that CertFindCertificateInStore() will allow any
|
||||
appropriate variations in the encoding when it does its comparison.
|
||||
This is, however, emphatically not true under Wine, which just compares
|
||||
the encodings with memcmp().
|
||||
Most of the time things work anyway, though, and there isn't really
|
||||
anything we can do to make the situation better.
|
||||
|
||||
[1] A "canonical form" is defined as the one where, if you locked 10
|
||||
mathematicians in a room and asked them to come up with a
|
||||
representation for something, it's the answer that 9 of them would
|
||||
give you back.
|
||||
I don't think OpenSSL's encoding qualifies.*/
|
||||
if(OP_UNLIKELY(_name->bytes->length>MAXDWORD))return 0;
|
||||
find_para.cbData=(DWORD)_name->bytes->length;
|
||||
find_para.pbData=(unsigned char *)_name->bytes->data;
|
||||
cert=CertFindCertificateInStore(h_store,X509_ASN_ENCODING,0,
|
||||
CERT_FIND_SUBJECT_NAME,&find_para,NULL);
|
||||
if(cert==NULL)return 0;
|
||||
x=d2i_X509(NULL,(const unsigned char **)&cert->pbCertEncoded,
|
||||
cert->cbCertEncoded);
|
||||
CertFreeCertificateContext(cert);
|
||||
if(x==NULL)return 0;
|
||||
ret=X509_STORE_add_cert(_lu->store_ctx,x);
|
||||
X509_free(x);
|
||||
if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret);
|
||||
}break;
|
||||
case X509_LU_CRL:{
|
||||
CERT_INFO cert_info;
|
||||
CERT_CONTEXT find_para;
|
||||
PCCRL_CONTEXT crl;
|
||||
X509_CRL *x;
|
||||
int ret;
|
||||
ret=op_capi_retrieve_by_subject(_lu,_type,_name,_ret);
|
||||
if(ret>0)return ret;
|
||||
memset(&cert_info,0,sizeof(cert_info));
|
||||
if(OP_UNLIKELY(_name->bytes->length>MAXDWORD))return 0;
|
||||
cert_info.Issuer.cbData=(DWORD)_name->bytes->length;
|
||||
cert_info.Issuer.pbData=(unsigned char *)_name->bytes->data;
|
||||
memset(&find_para,0,sizeof(find_para));
|
||||
find_para.pCertInfo=&cert_info;
|
||||
crl=CertFindCRLInStore(h_store,0,0,CRL_FIND_ISSUED_BY,&find_para,NULL);
|
||||
if(crl==NULL)return 0;
|
||||
x=d2i_X509_CRL(NULL,(const unsigned char **)&crl->pbCrlEncoded,
|
||||
crl->cbCrlEncoded);
|
||||
CertFreeCRLContext(crl);
|
||||
if(x==NULL)return 0;
|
||||
ret=X509_STORE_add_crl(_lu->store_ctx,x);
|
||||
X509_CRL_free(x);
|
||||
if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret);
|
||||
}break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*This is not const because OpenSSL doesn't allow it, even though it won't
|
||||
write to it.*/
|
||||
static X509_LOOKUP_METHOD X509_LOOKUP_CAPI={
|
||||
"Load Crypto API store into cache",
|
||||
op_capi_new,
|
||||
op_capi_free,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
op_capi_get_by_subject,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
int SSL_CTX_set_default_verify_paths_win32(SSL_CTX *_ssl_ctx){
|
||||
X509_STORE *store;
|
||||
X509_LOOKUP *lu;
|
||||
/*We intentionally do not add the normal default paths, as they are usually
|
||||
wrong, and are just asking to be used as an exploit vector.*/
|
||||
store=SSL_CTX_get_cert_store(_ssl_ctx);
|
||||
OP_ASSERT(store!=NULL);
|
||||
lu=X509_STORE_add_lookup(store,&X509_LOOKUP_CAPI);
|
||||
if(lu==NULL)return 0;
|
||||
ERR_clear_error();
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
90
third-party/opusfile/Sources/winerrno.h
vendored
Normal file
90
third-party/opusfile/Sources/winerrno.h
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012-2013 *
|
||||
* by the Xiph.Org Foundation and contributors https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
#if !defined(_opusfile_winerrno_h)
|
||||
# define _opusfile_winerrno_h (1)
|
||||
|
||||
# include <errno.h>
|
||||
# include <winerror.h>
|
||||
|
||||
/*These conflict with the MSVC errno.h definitions, but we don't need to use
|
||||
the original ones in any file that deals with sockets.
|
||||
We could map the WSA errors to the errno.h ones (most of which are only
|
||||
available on sufficiently new versions of MSVC), but they aren't ordered the
|
||||
same, and given how rarely we actually look at the values, I don't think
|
||||
it's worth a lookup table.*/
|
||||
# undef EWOULDBLOCK
|
||||
# undef EINPROGRESS
|
||||
# undef EALREADY
|
||||
# undef ENOTSOCK
|
||||
# undef EDESTADDRREQ
|
||||
# undef EMSGSIZE
|
||||
# undef EPROTOTYPE
|
||||
# undef ENOPROTOOPT
|
||||
# undef EPROTONOSUPPORT
|
||||
# undef EOPNOTSUPP
|
||||
# undef EAFNOSUPPORT
|
||||
# undef EADDRINUSE
|
||||
# undef EADDRNOTAVAIL
|
||||
# undef ENETDOWN
|
||||
# undef ENETUNREACH
|
||||
# undef ENETRESET
|
||||
# undef ECONNABORTED
|
||||
# undef ECONNRESET
|
||||
# undef ENOBUFS
|
||||
# undef EISCONN
|
||||
# undef ENOTCONN
|
||||
# undef ETIMEDOUT
|
||||
# undef ECONNREFUSED
|
||||
# undef ELOOP
|
||||
# undef ENAMETOOLONG
|
||||
# undef EHOSTUNREACH
|
||||
# undef ENOTEMPTY
|
||||
|
||||
# define EWOULDBLOCK (WSAEWOULDBLOCK-WSABASEERR)
|
||||
# define EINPROGRESS (WSAEINPROGRESS-WSABASEERR)
|
||||
# define EALREADY (WSAEALREADY-WSABASEERR)
|
||||
# define ENOTSOCK (WSAENOTSOCK-WSABASEERR)
|
||||
# define EDESTADDRREQ (WSAEDESTADDRREQ-WSABASEERR)
|
||||
# define EMSGSIZE (WSAEMSGSIZE-WSABASEERR)
|
||||
# define EPROTOTYPE (WSAEPROTOTYPE-WSABASEERR)
|
||||
# define ENOPROTOOPT (WSAENOPROTOOPT-WSABASEERR)
|
||||
# define EPROTONOSUPPORT (WSAEPROTONOSUPPORT-WSABASEERR)
|
||||
# define ESOCKTNOSUPPORT (WSAESOCKTNOSUPPORT-WSABASEERR)
|
||||
# define EOPNOTSUPP (WSAEOPNOTSUPP-WSABASEERR)
|
||||
# define EPFNOSUPPORT (WSAEPFNOSUPPORT-WSABASEERR)
|
||||
# define EAFNOSUPPORT (WSAEAFNOSUPPORT-WSABASEERR)
|
||||
# define EADDRINUSE (WSAEADDRINUSE-WSABASEERR)
|
||||
# define EADDRNOTAVAIL (WSAEADDRNOTAVAIL-WSABASEERR)
|
||||
# define ENETDOWN (WSAENETDOWN-WSABASEERR)
|
||||
# define ENETUNREACH (WSAENETUNREACH-WSABASEERR)
|
||||
# define ENETRESET (WSAENETRESET-WSABASEERR)
|
||||
# define ECONNABORTED (WSAECONNABORTED-WSABASEERR)
|
||||
# define ECONNRESET (WSAECONNRESET-WSABASEERR)
|
||||
# define ENOBUFS (WSAENOBUFS-WSABASEERR)
|
||||
# define EISCONN (WSAEISCONN-WSABASEERR)
|
||||
# define ENOTCONN (WSAENOTCONN-WSABASEERR)
|
||||
# define ESHUTDOWN (WSAESHUTDOWN-WSABASEERR)
|
||||
# define ETOOMANYREFS (WSAETOOMANYREFS-WSABASEERR)
|
||||
# define ETIMEDOUT (WSAETIMEDOUT-WSABASEERR)
|
||||
# define ECONNREFUSED (WSAECONNREFUSED-WSABASEERR)
|
||||
# define ELOOP (WSAELOOP-WSABASEERR)
|
||||
# define ENAMETOOLONG (WSAENAMETOOLONG-WSABASEERR)
|
||||
# define EHOSTDOWN (WSAEHOSTDOWN-WSABASEERR)
|
||||
# define EHOSTUNREACH (WSAEHOSTUNREACH-WSABASEERR)
|
||||
# define ENOTEMPTY (WSAENOTEMPTY-WSABASEERR)
|
||||
# define EPROCLIM (WSAEPROCLIM-WSABASEERR)
|
||||
# define EUSERS (WSAEUSERS-WSABASEERR)
|
||||
# define EDQUOT (WSAEDQUOT-WSABASEERR)
|
||||
# define ESTALE (WSAESTALE-WSABASEERR)
|
||||
# define EREMOTE (WSAEREMOTE-WSABASEERR)
|
||||
|
||||
#endif
|
2164
third-party/opusfile/include/opusfile/opusfile.h
vendored
Normal file
2164
third-party/opusfile/include/opusfile/opusfile.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user