Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add audio cue for task end and terminal bell #160828

Merged
merged 9 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/vs/workbench/contrib/audioCues/browser/audioCueService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ export class Sound {
public static readonly foldedArea = Sound.register({ fileName: 'foldedAreas.mp3' });
public static readonly break = Sound.register({ fileName: 'break.mp3' });
public static readonly quickFixes = Sound.register({ fileName: 'quickFixes.mp3' });
public static readonly taskEnded = Sound.register({ fileName: 'taskEnded.mp3' });
public static readonly terminalBell = Sound.register({ fileName: 'terminalBell.mp3' });
meganrogge marked this conversation as resolved.
Show resolved Hide resolved

private constructor(public readonly fileName: string) { }
}
Expand Down Expand Up @@ -211,6 +213,18 @@ export class AudioCue {
settingsKey: 'audioCues.noInlayHints'
});

public static readonly taskEnded = AudioCue.register({
name: localize('audioCues.taskEnded', 'Task Ended'),
sound: Sound.taskEnded,
settingsKey: 'audioCues.taskEnded'
});

public static readonly terminalBell = AudioCue.register({
name: localize('audioCues.terminalBell', 'Terminal Bell'),
sound: Sound.terminalBell,
settingsKey: 'audioCues.terminalBell'
});

private constructor(
public readonly sound: Sound,
public readonly name: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
'description': localize('audioCues.noInlayHints', "Plays a sound when trying to read a line with inlay hints that has no inlay hints."),
...audioCueFeatureBase,
},
'audioCues.taskEnded': {
'description': localize('audioCues.taskEnded', "Plays a sound when a task ends."),
...audioCueFeatureBase,
},
}
});

Expand Down
Binary file not shown.
Binary file not shown.
6 changes: 4 additions & 2 deletions src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import { IPreferencesService } from 'vs/workbench/services/preferences/common/pr
import { TerminalExitReason } from 'vs/platform/terminal/common/terminal';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';

const QUICKOPEN_HISTORY_LIMIT_CONFIG = 'task.quickOpen.history';
const PROBLEM_MATCHER_NEVER_CONFIG = 'task.problemMatchers.neverPrompt';
Expand Down Expand Up @@ -263,7 +264,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
@IThemeService private readonly _themeService: IThemeService,
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
@IInstantiationService private readonly _instantiationService: IInstantiationService
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IAudioCueService private readonly _audioCueService: IAudioCueService
) {
super();

Expand Down Expand Up @@ -1927,7 +1929,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
this._modelService, this._configurationResolverService,
this._contextService, this._environmentService,
AbstractTaskService.OutputChannelId, this._fileService, this._terminalProfileResolverService,
this._pathService, this._viewDescriptorService, this._logService, this._configurationService, this._notificationService,
this._pathService, this._viewDescriptorService, this._logService, this._configurationService, this._notificationService, this._audioCueService,
this,
(workspaceFolder: IWorkspaceFolder | undefined) => {
if (workspaceFolder) {
Expand Down
10 changes: 9 additions & 1 deletion src/vs/workbench/contrib/tasks/browser/taskTerminalStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ITerminalStatus } from 'vs/workbench/contrib/terminal/browser/terminalS
import { MarkerSeverity } from 'vs/platform/markers/common/markers';
import { spinningLoading } from 'vs/platform/theme/common/iconRegistry';
import { IMarker } from 'vs/platform/terminal/common/capabilities/capabilities';
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';

interface ITerminalData {
terminal: ITerminalInstance;
Expand All @@ -39,18 +40,25 @@ const INFO_INACTIVE_TASK_STATUS: ITerminalStatus = { id: TASK_TERMINAL_STATUS_ID
export class TaskTerminalStatus extends Disposable {
private terminalMap: Map<string, ITerminalData> = new Map();
private _marker: IMarker | undefined;
constructor(taskService: ITaskService) {
constructor(taskService: ITaskService, @IAudioCueService private readonly _audioCueService: IAudioCueService) {
super();
this._register(taskService.onDidStateChange((event) => {
switch (event.kind) {
case TaskEventKind.ProcessStarted:
case TaskEventKind.Active: this.eventActive(event); break;
case TaskEventKind.Inactive: this.eventInactive(event); break;
case TaskEventKind.ProcessEnded: this.eventEnd(event); break;
case TaskEventKind.End: this._playEndSound(event.exitCode); break;
}
}));
}

private _playEndSound(exitCode?: number): void {
//TODO: determine sound based on exit code
this._audioCueService.playAudioCue(AudioCue.taskEnded);
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
}


addTerminal(task: Task, terminal: ITerminalInstance, problemMatcher: AbstractProblemCollector) {
const status: ITerminalStatus = { id: TASK_TERMINAL_STATUS_ID, severity: Severity.Info };
terminal.statusList.add(status);
Expand Down
4 changes: 3 additions & 1 deletion src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { IOutputService } from 'vs/workbench/services/output/common/output';
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
import { IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';

interface ITerminalData {
terminal: ITerminalInstance;
Expand Down Expand Up @@ -239,6 +240,7 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
private _logService: ILogService,
private _configurationService: IConfigurationService,
private _notificationService: INotificationService,
audioCueService: IAudioCueService,
taskService: ITaskService,
taskSystemInfoResolver: ITaskSystemInfoResolver,
) {
Expand All @@ -252,7 +254,7 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
this._sameTaskTerminals = Object.create(null);
this._onDidStateChange = new Emitter();
this._taskSystemInfoResolver = taskSystemInfoResolver;
this._register(this._terminalStatusManager = new TaskTerminalStatus(taskService));
this._register(this._terminalStatusManager = new TaskTerminalStatus(taskService, audioCueService));
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
}

public get onDidStateChange(): Event<ITaskEvent> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/b
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';

interface IWorkspaceFolderConfigurationResult {
workspaceFolder: IWorkspaceFolder;
Expand Down Expand Up @@ -89,7 +90,8 @@ export class TaskService extends AbstractTaskService {
@ILogService logService: ILogService,
@IThemeService themeService: IThemeService,
@IInstantiationService instantiationService: IInstantiationService,
@IRemoteAgentService remoteAgentService: IRemoteAgentService
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
@IAudioCueService audioCueService: IAudioCueService
) {
super(configurationService,
markerService,
Expand Down Expand Up @@ -126,7 +128,8 @@ export class TaskService extends AbstractTaskService {
themeService,
lifecycleService,
remoteAgentService,
instantiationService
instantiationService,
audioCueService
);
this._register(lifecycleService.onBeforeShutdown(event => event.veto(this.beforeShutdown(), 'veto.tasks')));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ok } from 'assert';
import { Emitter, Event } from 'vs/base/common/event';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
import { ACTIVE_TASK_STATUS, FAILED_TASK_STATUS, SUCCEEDED_TASK_STATUS, TaskTerminalStatus } from 'vs/workbench/contrib/tasks/browser/taskTerminalStatus';
import { AbstractProblemCollector } from 'vs/workbench/contrib/tasks/common/problemCollectors';
import { CommonTask, ITaskEvent, TaskEventKind, TaskRunType } from 'vs/workbench/contrib/tasks/common/tasks';
Expand All @@ -24,6 +25,12 @@ class TestTaskService implements Partial<ITaskService> {
}
}

class TestAudioCueService implements Partial<IAudioCueService> {
async playAudioCue(cue: AudioCue): Promise<void> {
return;
}
}

class TestTerminal implements Partial<ITerminalInstance> {
statusList: TerminalStatusList = new TerminalStatusList(new TestConfigurationService());
}
Expand Down Expand Up @@ -56,7 +63,7 @@ suite('Task Terminal Status', () => {
setup(() => {
instantiationService = new TestInstantiationService();
taskService = new TestTaskService();
taskTerminalStatus = instantiationService.createInstance(TaskTerminalStatus, taskService);
taskTerminalStatus = instantiationService.createInstance(TaskTerminalStatus, taskService, new TestAudioCueService());
testTerminal = instantiationService.createInstance(TestTerminal);
testTask = instantiationService.createInstance(TestTask);
problemCollector = instantiationService.createInstance(TestProblemCollector);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { IColorTheme, ICssStyleCollector, IThemeService, registerThemingParticip
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views';
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
import { TaskSettingId } from 'vs/workbench/contrib/tasks/common/tasks';
import { IDetectedLinks, TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
import { TerminalLinkQuickpick } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkQuickpick';
Expand Down Expand Up @@ -376,7 +377,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
@IHistoryService private readonly _historyService: IHistoryService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@IOpenerService private readonly _openerService: IOpenerService,
@ICommandService private readonly _commandService: ICommandService
@ICommandService private readonly _commandService: ICommandService,
@IAudioCueService private readonly _audioCueService: IAudioCueService
) {
super();

Expand Down Expand Up @@ -730,6 +732,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
icon: Codicon.bell,
tooltip: nls.localize('bellStatus', "Bell")
}, this._configHelper.config.bellDuration);
this._audioCueService.playSound(AudioCue.terminalBell.sound);
Tyriar marked this conversation as resolved.
Show resolved Hide resolved
}
});
}, 1000);
Expand Down