/// <summary> /// The encode service_ encode completed. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { if (EncodeCompleted != null) { this.EncodeCompleted(sender, e); } }
/// <summary> /// The encode service_ encode completed. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { if (userSettingService.GetUserSetting <bool>(UserSettingConstants.GrowlEncode)) { // GrowlCommunicator.Notify("Encode Completed", "Put down that cocktail...\nyour Handbrake encode is done."); } }
/// <summary> /// The encode service_ encode completed. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void EncodeService_EncodeCompleted(object sender, EncodeCompletedEventArgs e) { if (!this.queueProcessor.IsProcessing) { this.JobStatus = Resources.QueueViewModel_LastJobFinished; } }
/// <summary> /// Encode Completed Event Handler. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void encodeService_EncodeCompleted(object sender, EncodeCompletedEventArgs e) { if (this.SelectedMode == 0) { this.Log = this.encodeService.ActivityLog; } }
/// <summary> /// After an encode is complete, move onto the next job. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.LastProcessedJob.Status = QueueItemStatus.Completed; // Clear the completed item of the queue if the setting is set. if (this.userSettingService.GetUserSetting <bool>(ASUserSettingConstants.ClearCompletedFromQueue)) { this.ClearCompleted(); } if (!e.Successful) { this.LastProcessedJob.Status = QueueItemStatus.Error; this.Pause(); } // Handling Log Data this.EncodeService.ProcessLogs(this.LastProcessedJob.Task.Destination); // Move onto the next job. if (this.IsProcessing) { this.ProcessNextJob(); } else { this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; this.OnQueueCompleted(new QueueCompletedEventArgs(true)); this.BackupQueue(string.Empty); } }
/// <summary> /// After an encode is complete, move onto the next job. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.LastProcessedJob.Status = QueueItemStatus.Completed; // Clear the completed item of the queue if the setting is set. if (clearCompleted) { this.ClearCompleted(); } if (!e.Successful) { this.LastProcessedJob.Status = QueueItemStatus.Error; } // Move onto the next job. if (this.IsProcessing) { this.ProcessNextJob(); } else { this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; this.OnQueueCompleted(new QueueCompletedEventArgs(true)); this.BackupQueue(string.Empty); } }
/// <summary> /// The encode service_ encode completed. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void EncodeService_EncodeCompleted(object sender, EncodeCompletedEventArgs e) { if (!this.queueProcessor.IsProcessing) { this.JobStatus = "Last Queued Job Finished"; } }
/// <summary> /// Invoke the Encode Completed Event /// </summary> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> public void Invoke_encodeCompleted(EncodeCompletedEventArgs e) { EncodeCompletedStatus handler = this.EncodeCompleted; if (handler != null) { handler(this, e); } }
/// <summary> /// The encode completed callback. /// </summary> /// <param name="eventArgs"> /// The event args. /// </param> public override void EncodeCompletedCallback(EncodeCompletedEventArgs eventArgs) { if (this.EncodeCompleted != null) { ThreadPool.QueueUserWorkItem(delegate { this.EncodeCompleted(this, eventArgs); }); } base.EncodeCompletedCallback(eventArgs); }
private void EncodeCompleted(object sender, EncodeCompletedEventArgs args) { _finishedSteps++; _currentEncoder.EncodeCompleted -= EncodeCompleted; _currentEncoder.EncodeStarted -= EncodeStarted; _currentEncoder.EncodeStatusChanged -= EncoderProgressStatus; _currentEncoder = null; DeleteTempFiles(); if (_currentJob != null && _currentJob.ExitCode == 0) { InvokeQueueStatusChanged(new QueueProgressEventArgs { JobName = string.Empty, AverageFrameRate = 0f, CurrentFrameRate = 0f, CurrentFrame = 0, TotalFrames = 0, ElapsedTime = new TimeSpan(), EstimatedTimeLeft = new TimeSpan(), PercentComplete = 0, TotalPercentComplete = (_finishedSteps * _fullTaskPercent), Pass = 0, }); GetNextStep(); if (_currentJob.NextStep == EncodingStep.Done && _queueList.IndexOf(_currentJob) < _queueList.Count - 1) { _currentJob = GetNextJob(); GetNextStep(); } else if (_currentJob.NextStep == EncodingStep.Done && _queueList.IndexOf(_currentJob) == _queueList.Count - 1) { InvokeQueueCompleted(new QueueCompletedEventArgs(true, null, string.Empty)); return; } ExecuteNextStep(); } else { var currentJob = _currentJob; var exitCode = -1; if (currentJob != null) { exitCode = currentJob.ExitCode; } InvokeQueueCompleted(new QueueCompletedEventArgs(false, new ApplicationException("Encoder exited with code " + exitCode), "Encoder exited with code " + exitCode)); } }
/// <summary> /// Invoke the Encode Completed Event /// </summary> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> public void InvokeEncodeCompleted(EncodeCompletedEventArgs e) { EncodeCompletedStatus handler = this.EncodeCompleted; if (handler != null) { handler(this, e); } this.LogIndex = 0; // Reset }
/// <summary> /// Handle the Encode Completed Event /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> private void encodeService_EncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.Percentage = "0.00%"; this.PercentageValue = 0; this.IsEncoding = false; this.encodeService.EncodeCompleted -= this.encodeService_EncodeCompleted; this.encodeService.EncodeStatusChanged -= this.encodeService_EncodeStatusChanged; this.PlayFile(); }
private void HandbrakeInstance_EncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.completedState = new JsonState() { WorkDone = new WorkDone() { Error = e.Error } }; this.completedState.State = "WORKDONE"; this.logHandler.ShutdownFileWriter(); this.handbrakeInstance.Dispose(); HandBrakeUtils.DisposeGlobal(); }
/// <summary> /// Encode Completed Event Handler /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void InstanceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.IsEncoding = false; this.ServiceLogMessage("Encode Completed ..."); // Handling Log Data this.ProcessLogs(this.currentTask.Destination, this.isPreviewInstance, this.currentConfiguration); // Raise the Encode Completed EVent. this.InvokeEncodeCompleted( e.Error ? new EventArgs.EncodeCompletedEventArgs(false, null, string.Empty, this.currentTask.Destination) : new EventArgs.EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Destination)); }
private void InstanceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.IsEncoding = false; if (this.isEncodeComplete) { return; // Prevent phantom events bubbling up the stack. } this.isEncodeComplete = true; string completeMessage = "Job Completed!"; switch (e.Error) { case 0: break; case 1: completeMessage = "Job Cancelled!"; break; case 2: completeMessage = string.Format("Job Failed. Check log and input settings ({0})", e.Error); break; case 3: completeMessage = string.Format("Job Failed to Initialise. Check log and input settings ({0})", e.Error); break; default: completeMessage = string.Format("Job Failed ({0})", e.Error); break; } this.ServiceLogMessage(completeMessage); // Handling Log Data string hbLog = this.ProcessLogs(this.currentTask.Destination); long filesize = this.GetFilesize(this.currentTask.Destination); // Raise the Encode Completed Event. this.InvokeEncodeCompleted( e.Error != 0 ? new EventArgs.EncodeCompletedEventArgs(false, null, e.Error.ToString(), this.currentTask.Source, this.currentTask.Destination, hbLog, filesize, e.Error) : new EventArgs.EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Source, this.currentTask.Destination, hbLog, filesize, e.Error)); this.logInstanceManager.Deregister(Path.GetFileName(hbLog)); }
private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.IsEncoding = false; this.IsPaused = false; this.job.Status = !e.Successful ? QueueItemStatus.Error : QueueItemStatus.Completed; this.job.Statistics.EndTime = DateTime.Now; this.job.Statistics.CompletedActivityLogPath = e.ActivityLogPath; this.job.Statistics.FinalFileSize = e.FinalFilesizeInBytes; this.job.JobProgress.ClearStatusDisplay(); this.encodeService.EncodeStatusChanged -= this.EncodeStatusChanged; this.encodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; this.OnJobFinished(e); }
/// <summary> /// The encode service_ encode completed. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> private void EncodeService_EncodeCompleted(object sender, EncodeCompletedEventArgs e) { // Send the file to the users requested applicaiton if (e.Successful) { this.SendToApplication(e.FileName); } // Allow the system to sleep again. Execute.OnUIThread(() => { if (this.userSettingService.GetUserSetting <bool>(UserSettingConstants.PreventSleep)) { Win32.AllowSleep(); } }); }
private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.IsEncoding = false; this.IsPaused = false; this.job.Status = !e.Successful ? QueueItemStatus.Error : QueueItemStatus.Completed; this.job?.JobProgress.Update(e); this.job.Statistics.UpdateStats(e, this.job); this.job.JobProgress.ClearStatusDisplay(); this.encodeService.EncodeStatusChanged -= this.EncodeStatusChanged; this.encodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; this.OnJobFinished(e); }
/// <summary> /// After an encode is complete, move onto the next job. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.QueueManager.LastProcessedJob.Status = QueueItemStatus.Completed; // Clear the completed item of the queue if the setting is set. if (userSettingService.GetUserSetting <bool>(ASUserSettingConstants.ClearCompletedFromQueue)) { this.QueueManager.ClearCompleted(); } // Growl if (userSettingService.GetUserSetting <bool>(ASUserSettingConstants.GrowlEncode)) { GrowlCommunicator.Notify("Encode Completed", "Put down that cocktail...\nyour Handbrake encode is done."); } if (!e.Successful) { this.QueueManager.LastProcessedJob.Status = QueueItemStatus.Error; this.Pause(); } // Handling Log Data this.EncodeService.ProcessLogs(this.QueueManager.LastProcessedJob.Task.Destination); // Post-Processing if (e.Successful) { SendToApplication(this.QueueManager.LastProcessedJob.Task.Destination); } // Move onto the next job. if (this.IsProcessing) { this.ProcessNextJob(); } else { this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; this.InvokeQueueCompleted(EventArgs.Empty); this.QueueManager.BackupQueue(string.Empty); } }
/// <summary> /// The encode service_ encode completed. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { encodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; encodeService.EncodeStarted -= this.encodeService_EncodeStarted; encodeService.EncodeStatusChanged -= this.encodeService_EncodeStatusChanged; Subscribers.ForEach( delegate(IHbServiceCallback callback) { if (((ICommunicationObject)callback).State == CommunicationState.Opened) { Console.WriteLine("Encode Completed Callback"); callback.EncodeCompletedCallback(e); } else { Subscribers.Remove(callback); } }); }
/// <summary> /// Encode Completed Event Handler /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void InstanceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.IsEncoding = false; this.ServiceLogMessage("Encode Completed ..."); // Stop Logging. HandBrakeUtils.MessageLogged -= this.HandBrakeInstanceMessageLogged; HandBrakeUtils.ErrorLogged -= this.HandBrakeInstanceErrorLogged; // Handling Log Data this.ProcessLogs(this.currentTask.Destination, this.isPreviewInstance, this.currentConfiguration); // Cleanup this.ShutdownFileWriter(); // Raise the Encode Completed EVent. this.InvokeEncodeCompleted( e.Error ? new HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs(false, null, string.Empty, this.currentTask.Destination) : new HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Destination)); }
/// <summary> /// After an encode is complete, move onto the next job. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { // Growl if (Init.GrowlEncode) { GrowlCommunicator.Notify("Encode Completed", "Put down that cocktail...\nyour Handbrake encode is done."); } if (!e.Successful) { this.Pause(); MessageBox.Show(e.Exception + e.ErrorInformation); } // Handling Log Data this.EncodeService.ProcessLogs(this.QueueManager.LastProcessedJob.Destination); // Move onto the next job. this.ProcessNextJob(); }
private void InstanceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.IsEncoding = false; string completeMessage = "Job Completed!"; switch (e.Error) { case 0: break; case 1: completeMessage = "Job Cancelled!"; break; case 2: completeMessage = string.Format("Job Failed. Check log and input settings ({0})", e.Error); break; case 3: completeMessage = string.Format("Job Failed to Initialise. Check log and input settings ({0})", e.Error); break; default: completeMessage = string.Format("Job Failed ({0})", e.Error); break; } this.ServiceLogMessage(completeMessage); // Handling Log Data string hbLog = this.ProcessLogs(this.currentTask.Destination, this.isPreviewInstance, this.currentConfiguration); long filesize = this.GetFilesize(this.currentTask.Destination); // Raise the Encode Completed Event. this.InvokeEncodeCompleted( e.Error != 0 ? new EventArgs.EncodeCompletedEventArgs(false, null, e.Error.ToString(), this.currentTask.Source, this.currentTask.Destination, hbLog, filesize) : new EventArgs.EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Source, this.currentTask.Destination, hbLog, filesize)); }
void OnEncodeEnded(object sender, EncodeCompletedEventArgs e) { Dispatcher.BeginInvoke(() => { // TODO: How do I detect errors? this.encodeIndex++; if (this.encodeIndex < this.jobQueue.Count) { this.encodingQueue.Start(this.jobQueue[this.encodeIndex], true); TotalPercentComplete = Math.Round( ((double)this.encodeIndex / (double)this.jobQueue.Count) * 100.0); } else { IsEncoding = this.encodingQueue.IsEncoding; ETA = "Complete"; PercentComplete = 100; TotalPercentComplete = 100; } }); }
public void UpdateStats(EncodeCompletedEventArgs e, QueueTask job) { EndTime = DateTime.Now; CompletedActivityLogPath = e.ActivityLogPath; FinalFileSizeBytes = e.FinalFilesizeInBytes; if (File.Exists(job.Task.Source)) { FileInfo file = new FileInfo(job.Task.Source); SourceFileSizeInBytes = file.Length; } EncodingSpeed = job.JobProgress.AverageFrameRate; ContentLength = this.DurationCalculation(job); SourceLength = GetSourceDuration(job); this.NotifyOfPropertyChange(() => this.EndTime); this.NotifyOfPropertyChange(() => this.CompletedActivityLogPath); this.NotifyOfPropertyChange(() => this.FileSizeDisplay); this.NotifyOfPropertyChange(() => this.EncodingSpeedDisplay); this.NotifyOfPropertyChange(() => this.ContentLength); this.NotifyOfPropertyChange(() => this.SourceLength); }
/// <summary> /// encode finished. /// </summary> /// <param name="sender">Encode job</param> /// <param name="e">encode complete event arguments</param> private void Job_EncodeCompleted (object sender, EncodeCompletedEventArgs e) { if (this.JobLog != null) { this.JobLog.Write ("Progress:100.00% - Complete\r\n"); } this.timeLastLogProgressWrite = DateTime.Now; }
private void OnEncodeCompleted(object sender, EncodeCompletedEventArgs e) { DispatchService.BeginInvoke(() => { ILogger encodeLogger = this.CurrentJob.Logger; string outputPath = this.CurrentJob.Job.OutputPath; if (this.encodeStopped) { // If the encode was stopped manually this.StopEncodingAndReport(); this.CurrentJob.ReportEncodeEnd(); if (this.totalTasks == 1) { this.EncodeQueue.Clear(); } encodeLogger.Log("Encoding stopped"); } else { // If the encode completed successfully this.completedQueueWork += this.CurrentJob.Cost; var outputFileInfo = new FileInfo(this.CurrentJob.Job.OutputPath); EncodeResultStatus status = EncodeResultStatus.Succeeded; if (e.Error) { status = EncodeResultStatus.Failed; encodeLogger.LogError("Encode failed."); } else if (!outputFileInfo.Exists) { status = EncodeResultStatus.Failed; encodeLogger.LogError("Encode failed. HandBrake reported no error but the expected output file was not found."); } else if (outputFileInfo.Length == 0) { status = EncodeResultStatus.Failed; encodeLogger.LogError("Encode failed. HandBrake reported no error but the output file was empty."); } EncodeJobViewModel finishedJob = this.CurrentJob; if (Config.PreserveModifyTimeFiles) { try { if (status != EncodeResultStatus.Failed && !Utilities.IsDirectory(finishedJob.Job.SourcePath)) { FileInfo info = new FileInfo(finishedJob.Job.SourcePath); File.SetCreationTimeUtc(finishedJob.Job.OutputPath, info.CreationTimeUtc); File.SetLastWriteTimeUtc(finishedJob.Job.OutputPath, info.LastWriteTimeUtc); } } catch (IOException exception) { encodeLogger.LogError("Could not set create/modify dates on file: " + exception); } catch (UnauthorizedAccessException exception) { encodeLogger.LogError("Could not set create/modify dates on file: " + exception); } } this.CompletedJobs.Add(new EncodeResultViewModel( new EncodeResult { Destination = this.CurrentJob.Job.OutputPath, Status = status, EncodeTime = this.CurrentJob.EncodeTime, LogPath = encodeLogger.LogPath }, finishedJob)); this.RaisePropertyChanged(() => this.CompletedItemsCount); this.RaisePropertyChanged(() => this.CompletedTabHeader); this.EncodeQueue.RemoveAt(0); this.RaisePropertyChanged(() => this.QueuedTabHeader); // Wait until after it's removed from the queue before running cleanup: otherwise it will find // the instance "in use" in the queue and not do removal. if (!Config.KeepScansAfterCompletion) { this.CleanupHandBrakeInstanceIfUnused(finishedJob.HandBrakeInstance); finishedJob.HandBrakeInstance = null; } encodeLogger.Log("Job completed (Elapsed Time: " + Utilities.FormatTimeSpan(finishedJob.EncodeTime) + ")"); if (this.EncodeQueue.Count == 0) { this.SelectedTabIndex = CompletedTabIndex; this.StopEncodingAndReport(); this.logger.Log("Queue completed"); this.logger.ShowStatus(MainRes.EncodeCompleted); this.logger.Log(""); Ioc.Container.GetInstance<TrayService>().ShowBalloonMessage(MainRes.EncodeCompleteBalloonTitle, MainRes.EncodeCompleteBalloonMessage); EncodeCompleteActionType actionType = this.EncodeCompleteAction.ActionType; if (Config.PlaySoundOnCompletion && actionType != EncodeCompleteActionType.Sleep && actionType != EncodeCompleteActionType.LogOff && actionType != EncodeCompleteActionType.Shutdown) { string soundPath = null; if (Config.UseCustomCompletionSound) { if (File.Exists(Config.CustomCompletionSound)) { soundPath = Config.CustomCompletionSound; } else { this.logger.LogError(string.Format("Cound not find custom completion sound \"{0}\" . Using default.", Config.CustomCompletionSound)); } } if (soundPath == null) { soundPath = Path.Combine(Utilities.ProgramFolder, "Encode_Complete.wav"); } var soundPlayer = new SoundPlayer(soundPath); try { soundPlayer.Play(); } catch (InvalidOperationException) { this.logger.LogError(string.Format("Completion sound \"{0}\" was not a supported WAV file.", soundPath)); } } switch (actionType) { case EncodeCompleteActionType.DoNothing: break; case EncodeCompleteActionType.EjectDisc: this.systemOperations.Eject(this.EncodeCompleteAction.DriveLetter); break; case EncodeCompleteActionType.Sleep: case EncodeCompleteActionType.LogOff: case EncodeCompleteActionType.Shutdown: WindowManager.OpenWindow(new ShutdownWarningViewModel(actionType)); break; default: throw new ArgumentOutOfRangeException(); } } else { this.EncodeNextJob(); } } if (this.encodeStopped || this.EncodeQueue.Count == 0) { this.main.WindowManagerVM.CloseEncodeDetailsWindow(); } string encodeLogPath = encodeLogger.LogPath; encodeLogger.Dispose(); if (Config.CopyLogToOutputFolder) { string logCopyPath = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileName(encodeLogPath)); try { File.Copy(encodeLogPath, logCopyPath); } catch (IOException exception) { this.logger.LogError("Could not copy log file to output directory: " + exception); } catch (UnauthorizedAccessException exception) { this.logger.LogError("Could not copy log file to output directory: " + exception); } } }); }
/// <summary> /// Encode Completed Event Handler. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.NotifyOfPropertyChange(() => this.EncodeLog); }
void job2_EncodeCompleted(object sender, EncodeCompletedEventArgs e) { label1.Text = "处理完成..."; }
private void OnJobFinished(EncodeCompletedEventArgs e) { this.JobFinished?.Invoke(this, new ActiveJobCompletedEventArgs(this, e)); }
/// <summary> /// The encode completed callback. /// </summary> /// <param name="eventArgs"> /// The event Args. /// </param> public virtual void EncodeCompletedCallback(EncodeCompletedEventArgs eventArgs) { }
/// <summary> /// Invoke the Encode Completed Event /// </summary> /// <param name="e"> /// The EncodeCompletedEventArgs. /// </param> public void InvokeEncodeCompleted(EncodeCompletedEventArgs e) { var handler = EncodeCompleted; handler?.Invoke(this, e); }