diff --git a/.gitignore b/.gitignore index ea95dc1c3..c1d3f4887 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,9 @@ tmtags .project .metadata +# WebStorm +.idea + # ============================================================================== # Temp generated code # ============================================================================== diff --git a/debugger/assets/styles/app.css b/debugger/assets/styles/app.css new file mode 100644 index 000000000..006be6480 --- /dev/null +++ b/debugger/assets/styles/app.css @@ -0,0 +1,255 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +.full-width { + width: 100%; +} + +body { + margin: 0; +} + +.app-main { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + overflow: hidden; + min-width: 900px; + min-height: 350px; + display: flex; + flex-flow: column nowrap; +} +.app-header { + order: 1; + flex: 0 0 auto; + align-self: auto; +} +.app-header .navbar { + border-radius: 0; + min-height: 0; + margin-bottom: 0; +} + +.app-body { + order: 2; + flex: 1 1 auto; + align-self: auto; + position: relative; + left: 0; + top: 0; + right: 0; + bottom: 0; +} +.tab-pane { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} + +.app-console { + order: 3; + flex: 0 0 auto; + align-self: auto; + border-top-width: 2px; + border-top-style: solid; +} +.console { + display: flex; + flex-flow: column nowrap; + padding: 5px; +} +.console-part-log { + order: 1; + flex: 1 1 auto; + align-self: auto; +} +.console-log-outer { + position: relative; + left: 0; + top: 0; + right: 0; + bottom: 0; + border: 1px solid #ddd; + overflow-y: scroll; + height: 100px; +} +.console-part-input { + order: 2; + flex: 0 0 auto; + align-self: auto; + display: flex; + flex-flow: row nowrap; + padding-top: 5px; +} +.console-input-left { + order: 1; + flex: 0 0 auto; + min-width: 0; +} +.console-input-middle { + order: 2; + flex: 1 1 auto; +} +.console-input-right { + order: 3; + flex: 0 0 auto; + padding-left: 10px; +} + +.debugger-main { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + display: flex; + flex-flow: column nowrap; +} +.debugger-header { + order: 1; + flex: 0 0 auto; + align-self: auto; + border-bottom: 1px solid #ddd; + padding: 5px; +} +.debugger-body { + order: 2; + flex: 1 1 auto; + align-self: auto; + display: flex; + flex-flow: row nowrap; +} +.debugger-fnlist { + order: 1; + flex: 0 0 auto; + display: flex; + flex-flow: column nowrap; + max-width: 200px; +} +.debugger-fnlist-header { + order: 1; + flex: 0 0 auto; + padding: 5px; +} +.debugger-fnlist-body { + order: 2; + flex: 1 1 auto; + padding: 5px; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + position: relative; +} +.debugger-fnlist-list { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + padding: 5px; + overflow: scroll; +} +.debugger-fnlist-footer { + order: 3; + flex: 0 0 auto; + padding: 5px; +} +.debugger-fnview { + order: 2; + flex: 1 1 auto; + display: flex; + flex-flow: column nowrap; + border-left: 2px solid #ddd; + border-right: 2px solid #ddd; +} +.debugger-fnview-header { + order: 1; + flex: 0 0 auto; + padding: 5px; + display: flex; + flex-flow: row nowrap; +} +.debugger-fnview-header-left { + order: 1; + flex: 1 1 auto; + padding: 5px; +} +.debugger-fnview-header-name { + font-size: 21px; + font-family: monospace; +} +.debugger-fnview-header-address { + font-family: monospace; +} +.debugger-fnview-header-right { + order: 2; + flex: 0 0 auto; + padding: 5px; +} +.debugger-fnview-body { + order: 2; + flex: 1 1 auto; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + display: flex; + flex-flow: row nowrap; +} +.debugger-fnview-codeview { + order: 1; + flex: 1 1 auto; + position: relative; +} +.debugger-fnview-codeview .CodeMirror { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + height: 100%; +} +.debugger-fnview-graphview { + order: 2; + flex: 0 0 auto; + position: relative; + border-left: 1px solid #ddd; + min-width: 100px; +} +.debugger-fnview-footer { + order: 3; + flex: 0 0 auto; + padding: 5px; +} +.debugger-tools { + order: 3; + flex: 0 0 auto; + display: flex; + flex-flow: column nowrap; + min-width: 200px; +} +.debugger-tools-threads { + order: 1; + flex: 0 0 auto; + padding: 5px; +} +.debugger-tools-callstack { + order: 2; + flex: 1 1 auto; + padding: 5px; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + position: relative; +} +.debugger-tools-registers { + order: 3; + flex: 1 1 auto; + padding: 5px; +} diff --git a/debugger/assets/ui/apu/apu-tab.html b/debugger/assets/ui/apu/apu-tab.html new file mode 100644 index 000000000..f57223d9b --- /dev/null +++ b/debugger/assets/ui/apu/apu-tab.html @@ -0,0 +1 @@ +TODO: APU diff --git a/debugger/assets/ui/code/code-tab.html b/debugger/assets/ui/code/code-tab.html new file mode 100644 index 000000000..48388c9c4 --- /dev/null +++ b/debugger/assets/ui/code/code-tab.html @@ -0,0 +1,93 @@ +
+
+ debug header/toolbar/etc +
+
+
+
+
+
+ + +
+
+
+
+ fn
fn
fn +
+
+ +
+
+
+
+ function name + (0x80000000-0x80000000) +
+
+ +
+
+
+
+ +
+
+ graph! +
+
+ +
+
+
+
+ + +
+
+
+ callstack +
+
+ registers +
+
+
+
diff --git a/debugger/assets/ui/code/function-view.html b/debugger/assets/ui/code/function-view.html new file mode 100644 index 000000000..980b207bb --- /dev/null +++ b/debugger/assets/ui/code/function-view.html @@ -0,0 +1,2 @@ +TODO: function +
diff --git a/debugger/assets/ui/console/console.html b/debugger/assets/ui/console/console.html new file mode 100644 index 000000000..d1a485271 --- /dev/null +++ b/debugger/assets/ui/console/console.html @@ -0,0 +1,26 @@ +
+
+
+
    +
  • {{line}}
  • +
+
+
+
+
+
+
+
+ @ + +
+
+
+
+ + + +
+
+
+
diff --git a/debugger/assets/ui/console/console.js b/debugger/assets/ui/console/console.js new file mode 100644 index 000000000..6a07556b2 --- /dev/null +++ b/debugger/assets/ui/console/console.js @@ -0,0 +1,34 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +'use strict'; + +var module = angular.module('xe.ui.console', [ + 'xe.log' +]); + + +module.controller('ConsoleController', function($scope, log) { + $scope.log = log; + + $scope.commandText = ''; + + $scope.issueCommand = function() { + var command = $scope.commandText; + $scope.commandText = ''; + if (!command) { + return; + } + + log.appendLine('@' + command); + + // TODO(benvanik): execute. + console.log(command); + }; +}); diff --git a/debugger/assets/ui/gpu/gpu-tab.html b/debugger/assets/ui/gpu/gpu-tab.html new file mode 100644 index 000000000..cf32ac752 --- /dev/null +++ b/debugger/assets/ui/gpu/gpu-tab.html @@ -0,0 +1 @@ +TODO: GPU diff --git a/debugger/assets/ui/kernel/kernel-tab.html b/debugger/assets/ui/kernel/kernel-tab.html new file mode 100644 index 000000000..92d33f5ee --- /dev/null +++ b/debugger/assets/ui/kernel/kernel-tab.html @@ -0,0 +1 @@ +TODO: kernel diff --git a/debugger/assets/ui/memory/memory-tab.html b/debugger/assets/ui/memory/memory-tab.html new file mode 100644 index 000000000..f15b42831 --- /dev/null +++ b/debugger/assets/ui/memory/memory-tab.html @@ -0,0 +1 @@ +TODO: memory diff --git a/debugger/assets/ui/navbar.html b/debugger/assets/ui/navbar.html new file mode 100644 index 000000000..9c94802d1 --- /dev/null +++ b/debugger/assets/ui/navbar.html @@ -0,0 +1,37 @@ + diff --git a/debugger/assets/ui/navbar.js b/debugger/assets/ui/navbar.js new file mode 100644 index 000000000..a96f64d4d --- /dev/null +++ b/debugger/assets/ui/navbar.js @@ -0,0 +1,52 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +'use strict'; + +var module = angular.module('xe.ui.navbar', []); + + +module.controller('NavbarController', function( + $scope, $state, app, log) { + + $scope.connectClicked = function() { + // TODO(benvanik): show a fancy dialog or something. + var oldSession = app.session; + app.connect().then(function(session) { + if (!oldSession || oldSession.id != session.id) { + $state.go('session', { + 'sessionId': session.id + }, { + notify: true + }); + } + }, function(e) { + $state.go('/', { + }, { + notify: true + }); + }); + }; + + $scope.openClicked = function() { + var inputEl = document.createElement('input'); + inputEl.type = 'file'; + inputEl.accept = '.xe-trace,application/x-extension-xe-trace'; + inputEl.onchange = function(e) { + $scope.$apply(function() { + if (inputEl.files.length) { + //app.open(inputEl.files[0]); + log.info('Not implemented yet'); + } + }); + }; + inputEl.click(); + }; + +}); diff --git a/debugger/assets/ui/session.html b/debugger/assets/ui/session.html new file mode 100644 index 000000000..31800c0de --- /dev/null +++ b/debugger/assets/ui/session.html @@ -0,0 +1 @@ +
diff --git a/debugger/debugger.js b/debugger/debugger.js index f0c54052e..5056af365 100644 --- a/debugger/debugger.js +++ b/debugger/debugger.js @@ -7,41 +7,7 @@ ****************************************************************************** */ -// TODO(benvanik): closure or something fancy - - -var DebugClient = function(endpoint) { - /** - * Target websocket endpoint. - * @type {string} - * @private - */ - this.endpoint_ = endpoint; - - /** - * Connected socket. - * @type {!WebSocket} - * @private - */ - this.socket_ = new WebSocket(endpoint, []); - - this.socket_.onopen = (function() { - console.log('opened'); - }).bind(this); - - this.socket_.onerror = (function(e) { - console.log('error', e); - }).bind(this); - - this.socket_.onmessage = (function(e) { - console.log('message', e.data); - }).bind(this); -} - - -var client = new DebugClient('ws://127.0.0.1:6200'); - - +/* var myTextArea = document.querySelector('.debugger-fnview-textarea'); var myCodeMirror = CodeMirror.fromTextArea(myTextArea, { mode: 'javascript', @@ -58,3 +24,4 @@ var myCodeMirror = CodeMirror.fromTextArea(myTextArea, { //readOnly: true, }); +*/ diff --git a/debugger/index.html b/debugger/index.html index d24aa955c..76e2d1fec 100644 --- a/debugger/index.html +++ b/debugger/index.html @@ -1,445 +1,36 @@ - + Xenia Debugger + + + - + + - +
-
- -
-
- -
-
-
- debug header/toolbar/etc -
-
-
-
-
- - -
-
-
-
- fn
fn
fn -
-
- -
-
-
-
- function name - (0x80000000-0x80000000) -
-
- -
-
-
-
- -
-
- graph! -
-
- -
-
-
-
- - -
-
-
- callstack -
-
- registers -
-
-
-
-
- -
- TODO: memory -
- -
- TODO: kernel -
- -
- TODO: GPU -
- -
- TODO: APU -
- -
- +
+
+
- - - + + + + + + + + + + + + diff --git a/debugger/src/app.js b/debugger/src/app.js new file mode 100644 index 000000000..e7b3eceeb --- /dev/null +++ b/debugger/src/app.js @@ -0,0 +1,107 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +'use strict'; + +var module = angular.module('app', [ + 'ui.bootstrap', + 'ui.router', + 'xe.datasources', + 'xe.directives', + 'xe.log', + 'xe.router', + 'xe.session', + 'xe.ui.console', + 'xe.ui.navbar' +]); + + +module.controller('AppController', function($scope, app) { + this.app = app; +}); + + +module.service('app', function( + $rootScope, $q, $state, log, Session) { + var App = function() { + this.loading = false; + this.session = null; + }; + + App.prototype.setSession = function(session) { + this.close(); + + this.session = session; + }; + + App.prototype.close = function() { + this.loading = false; + if (this.session) { + this.session.dispose(); + this.session = null; + } + }; + + App.prototype.open = function(sessionId) { + this.close(); + + var d = $q.defer(); + this.loading = true; + + log.info('Opening session ' + sessionId); + + var session = new Session(sessionId); + this.loading = false; + this.setSession(session); + d.resolve(session); + + return d.promise; + }; + + App.prototype.connect = function(opt_host) { + this.close(); + + var d = $q.defer(); + this.loading = true; + + Session.query(opt_host).then((function(infos) { + var info = infos[0]; + var id = info.titleId; + if (id == '00000000') { + id = info.name; + } + var session = new Session(id); + var p = session.connect(opt_host); + p.then((function(session) { + this.loading = false; + this.setSession(session); + d.resolve(session); + }).bind(this), (function(e) { + this.loading = false; + d.reject(e); + }).bind(this), function(update) { + d.notify(update); + }); + }).bind(this), (function(e) { + this.loading = false; + log.info('No sessions found at ' + Session.getHost(opt_host)); + d.reject(e); + }).bind(this)); + + return d.promise; + }; + + return new App(); +}); + + +module.run(function($rootScope, app, log) { + $rootScope.app = app; + $rootScope.log = log; +}); diff --git a/debugger/src/base.js b/debugger/src/base.js new file mode 100644 index 000000000..352cac84a --- /dev/null +++ b/debugger/src/base.js @@ -0,0 +1,19 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +'use strict'; + + +function inherits(childCtor, parentCtor) { + function tempCtor() {}; + tempCtor.prototype = parentCtor.prototype; + childCtor.superClass_ = parentCtor.prototype; + childCtor.prototype = new tempCtor(); + childCtor.prototype.constructor = childCtor; +}; diff --git a/debugger/src/datasources.js b/debugger/src/datasources.js new file mode 100644 index 000000000..f24d8dd51 --- /dev/null +++ b/debugger/src/datasources.js @@ -0,0 +1,122 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +'use strict'; + +var module = angular.module('xe.datasources', []); + + +var DataSource = function(source) { + this.source = source; + this.online = false; + this.status = 'disconnected'; +}; +DataSource.prototype.open = function() {}; +DataSource.prototype.dispose = function() {}; + + +module.service('RemoteDataSource', function($q) { + var RemoteDataSource = function(url) { + DataSource.call(this, url); + this.url = url; + this.socket = null; + }; + inherits(RemoteDataSource, DataSource); + + RemoteDataSource.prototype.open = function() { + var url = this.url; + + this.online = false; + this.status = 'connecting'; + + var d = $q.defer(); + + this.socket = new WebSocket(url, []); + this.socket.onopen = (function() { + // TODO(benvanik): handshake + + this.online = true; + this.status = 'connected'; + d.resolve(); + }).bind(this); + + this.socket.onclose = (function(e) { + this.online = false; + if (this.status == 'connecting') { + this.status = 'disconnected'; + d.reject(e.code + ' ' + e.reason); + } else { + this.status = 'disconnected'; + } + }).bind(this); + + this.socket.onerror = (function(e) { + // ? + }).bind(this); + + this.socket.onmessage = (function(e) { + console.log('message', e.data); + }).bind(this); + + return d.promise; + }; + + RemoteDataSource.prototype.dispose = function() { + this.online = false; + this.status = 'disconnected'; + if (this.socket) { + this.socket.close(); + this.socket = null; + } + DataSource.prototype.dispose.call(this); + }; + + return RemoteDataSource; +}); + + +module.service('FileDataSource', function($q) { + var FileDataSource = function(file) { + DataSource.call(this, file.name); + this.file = file; + }; + inherits(FileDataSource, DataSource); + + FileDataSource.prototype.open = function() { + this.status = 'connecting'; + + var d = $q.defer(); + + var self = this; + window.setTimeout(function() { + $scope.$apply((function() { + // TODO(benvanik): scan/load trace + + this.online = true; + this.status = 'connected'; + d.resolve(); + }).bind(self)); + }); + + return d.promise; + }; + + FileDataSource.prototype.dispose = function() { + this.online = false; + if (this.file) { + if (this.file.close) { + this.file.close(); + } + this.file = null; + } + DataSource.prototype.dispose.call(this); + }; + + return FileDataSource; +}); diff --git a/debugger/src/directives.js b/debugger/src/directives.js new file mode 100644 index 000000000..8dca19af3 --- /dev/null +++ b/debugger/src/directives.js @@ -0,0 +1,26 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +'use strict'; + +var module = angular.module('xe.directives', []); + + +module.directive('uiEnter', function() { + return function($scope, element, attrs) { + element.bind("keydown keypress", function(e) { + if(e.which === 13) { + $scope.$apply(function(){ + $scope.$eval(attrs.uiEnter); + }); + e.preventDefault(); + } + }); + }; +}); diff --git a/debugger/src/log.js b/debugger/src/log.js new file mode 100644 index 000000000..5768e849c --- /dev/null +++ b/debugger/src/log.js @@ -0,0 +1,45 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +'use strict'; + +var module = angular.module('xe.log', []); + + +module.service('log', function($rootScope) { + var Log = function() { + this.lines = []; + + this.progressActive = false; + this.progress = 0; + }; + + Log.prototype.appendLine = function(line) { + this.lines.push(line); + }; + + Log.prototype.info = function(line) { + this.appendLine('I ' + line); + }; + + Log.prototype.error = function(line) { + this.appendLine('E ' + line); + }; + + Log.prototype.setProgress = function(value) { + this.progressActive = true; + this.progress = value; + }; + + Log.prototype.clearProgress = function() { + this.progressActive = false; + }; + + return new Log(); +}); diff --git a/debugger/src/router.js b/debugger/src/router.js new file mode 100644 index 000000000..07e261ae7 --- /dev/null +++ b/debugger/src/router.js @@ -0,0 +1,144 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +'use strict'; + +var module = angular.module('xe.router', [ + 'ui.router', +]); + + +module.config(function($stateProvider, $urlRouterProvider) { + $urlRouterProvider.otherwise('/'); + + $stateProvider.state('/', { + template: 'empty' + }); + + $stateProvider.state('session', { + url: '/:sessionId', + templateUrl: 'assets/ui/session.html', + resolve: { + app: 'app', + session: function($stateParams, $urlRouter, $state, $q, $timeout, + Session, app) { + // If we are given a session we assume the user is trying to connect to + // it. Attempt that now. If we fail we redirect to home, otherwise we + // check whether it's the same game down below. + var d = $q.defer(); + if ($stateParams.sessionId) { + if (!app.session || + app.session.id != $stateParams.sessionId) { + Session.query().then(function(infos) { + var id = (infos[0].titleId == '00000000') ? + infos[0].name : infos[0].titleId; + if (!app.session || app.session.id == id) { + // Same session, continue. + var p = app.connect(); + p.then(function(session) { + d.resolve(session); + }, function(e) { + $state.go('session', { + 'sessionId': session.id + }, { + notify: true + }); + d.reject(e); + }) + } else { + // Different session. Create without connection. + var p = app.open(id); + p.then(function(session) { + d.resolve(session); + }, function(e) { + d.reject(e); + }); + } + }, function(e) { + var p = app.open($stateParams.sessionId); + p.then(function(session) { + d.resolve(session); + }, function(e) { + d.reject(e); + }); + }); + } else { + var p = app.open($stateParams.sessionId); + p.then(function(session) { + d.resolve(session); + }, function(e) { + d.reject(e); + }); + } + } else { + d.resolve(null); + } + return d.promise; + } + }, + controller: function($scope, $stateParams, $q, app, session) { + }, + onEnter: function() { + }, + onExit: function() {} + }); + + $stateProvider.state('session.code', { + url: '/code', + templateUrl: 'assets/ui/code/code-tab.html', + controller: function($stateParams) { + }, + onEnter: function() {}, + onExit: function() {} + }); + $stateProvider.state('session.code.function', { + url: '/:module/:function', + templateUrl: 'assets/ui/code/function-view.html', + controller: function($stateParams) { + }, + onEnter: function() {}, + onExit: function() {} + }); + + $stateProvider.state('session.memory', { + url: '/memory', + templateUrl: 'assets/ui/memory/memory-tab.html', + controller: function($stateParams) { + }, + onEnter: function() {}, + onExit: function() {} + }); + + $stateProvider.state('session.kernel', { + url: '/kernel', + templateUrl: 'assets/ui/kernel/kernel-tab.html', + controller: function($stateParams) { + }, + onEnter: function() {}, + onExit: function() {} + }); + + $stateProvider.state('session.gpu', { + url: '/gpu', + templateUrl: 'assets/ui/gpu/gpu-tab.html', + controller: function($stateParams) { + }, + onEnter: function() {}, + onExit: function() {} + }); + + $stateProvider.state('session.apu', { + url: '/apu', + templateUrl: 'assets/ui/apu/apu-tab.html', + controller: function($stateParams) { + }, + onEnter: function() {}, + onExit: function() {} + }); +}); diff --git a/debugger/src/session.js b/debugger/src/session.js new file mode 100644 index 000000000..fef58b745 --- /dev/null +++ b/debugger/src/session.js @@ -0,0 +1,92 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +'use strict'; + +var module = angular.module('xe.session', []); + + +module.service('Session', function( + $q, $http, log, FileDataSource, RemoteDataSource) { + var Session = function(id, opt_dataSource) { + this.id = id; + + this.dataSource = opt_dataSource || null; + }; + + Session.prototype.dispose = function() { + this.disconnect(); + }; + + Session.DEFAULT_HOST = '127.0.0.1:6200'; + + Session.getHost = function(opt_host) { + return opt_host || Session.DEFAULT_HOST; + }; + + Session.query = function(opt_host) { + var url = 'http://' + Session.getHost(opt_host); + var p = $http({ + method: 'GET', + url: url + '/sessions', + cache: false, + timeout: 500, + responseType: 'json' + }); + var d = $q.defer(); + p.then(function(response) { + if (!response.data || !response.data.length) { + d.reject(new Error('No session data')); + return; + } + d.resolve(response.data); + }, function(e) { + d.reject(e); + }); + return d.promise; + }; + + Session.prototype.connect = function(opt_host) { + this.disconnect(); + + var url = 'ws://' + Session.getHost(opt_host); + + log.info('Connecting to ' + url + '...'); + log.setProgress(0); + + var d = $q.defer(); + + var dataSource = new RemoteDataSource(url); + var p = dataSource.open(); + p.then((function() { + log.info('Connected!'); + log.clearProgress(); + this.dataSource = dataSource; + d.resolve(this); + }).bind(this), (function(e) { + log.error('Unable to connect: ' + e); + log.clearProgress(); + d.reject(e); + }).bind(this), function(update) { + log.setProgress(update.progress); + d.notify(update); + }); + + return d.promise; + }; + + Session.prototype.disconnect = function() { + if (this.dataSource) { + this.dataSource.dispose(); + this.dataSource = null; + } + }; + + return Session; +});