Skip to content

Commit

Permalink
webapp setup: Add support for VBox capture cards
Browse files Browse the repository at this point in the history
  • Loading branch information
bennettpeter committed Apr 5, 2023
1 parent 5ddd46b commit b90cb4c
Show file tree
Hide file tree
Showing 13 changed files with 369 additions and 14 deletions.
14 changes: 11 additions & 3 deletions mythtv/html/assets/i18n/en_US.json
Expand Up @@ -531,12 +531,20 @@
"tunerindex_label": "Tuner Index",
"deviceid_label": "Device ID",
"diseqcpos_label": "DiSEqC position",
"diseqcpos_desc": "Position of the LNB on the DiSEqC switch. Leave at 1 if there is no DiSEqC switch and the LNB is directly connected to the SatIP server. This value is used as signal source (attribute src) in the SatIP tune command."
"diseqcpos_desc": "Position of the LNB on the DiSEqC switch. Leave at 1 if there is no DiSEqC switch and the LNB is directly connected to the SatIP server. This value is used as signal source (attribute src) in the SatIP tune command.",
"friendly_desc": "Friendly name of the Sat>IP server"
},
"friendly_desc": "Friendly name of the Sat>IP server",
"tunertype_desc": "Type of the selected tuner",
"tunerindex_desc": "Index of the tuner on the Sat>IP server",
"deviceid_desc": "Device ID of the Sat>IP tuner."
"deviceid_desc": "Device ID of the Sat>IP tuner.",
"vbox": {
"manuallyenter": "Manually Enter IP Address",
"title": "V@Box TV Gateway networked tuner",
"device_desc": "Device IP or ID, tuner number and tuner type of available VBox devices.",
"deviceid_label": "Device ID",
"description_label": "Description",
"deviceid_desc": "Device ID of VBox device"
}
},
"common": {
"successful_delete": "Successful delete",
Expand Down
2 changes: 2 additions & 0 deletions mythtv/html/backend/src/app/app.module.ts
Expand Up @@ -73,6 +73,7 @@ import { BackendWarningComponent } from './config/backend-warning/backend-warnin
import { V4l2Component } from './config/settings/capture-cards/v4l2/v4l2.component';
import { HdpvrComponent } from './config/settings/capture-cards/hdpvr/hdpvr.component';
import { SatipComponent } from './config/settings/capture-cards/satip/satip.component';
import { VboxComponent } from './config/settings/capture-cards/vbox/vbox.component';

// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
Expand Down Expand Up @@ -142,6 +143,7 @@ export function HttpLoaderFactory(http: HttpClient) {
V4l2Component,
HdpvrComponent,
SatipComponent,
VboxComponent,
],
imports: [
BrowserModule,
Expand Down
Expand Up @@ -69,7 +69,7 @@ <h2>{{ 'settings.common.ru_sure' | translate }}</h2>
[disabled]="disabledTab[ix]" [(selected)]="activeTab[ix]">
<ng-template pTemplate="header">
<div class="grid w-full">
<div class="col-9 pr-1">
<div class="col-11 pr-1">
{{m_CaptureCardsFiltered[ix].CardType}}
{{m_CaptureCardsFiltered[ix].VideoDevice}}
({{m_CaptureCardsFiltered[ix].DisplayName}})
Expand Down Expand Up @@ -118,6 +118,8 @@ <h2>{{ 'settings.common.ru_sure' | translate }}</h2>
</app-hdpvr>
<app-satip *ngSwitchCase="'SATIP'" [card]="m_CaptureCardsFiltered[ix]" [cardList]="m_CaptureCardList">
</app-satip>
<app-vbox *ngSwitchCase="'VBOX'" [card]="m_CaptureCardsFiltered[ix]" [cardList]="m_CaptureCardList">
</app-vbox>
<div *ngSwitchDefault><br>Not Supported </div>
</div>
</ng-template>
Expand Down
Expand Up @@ -29,7 +29,8 @@ export class CaptureCardsComponent implements OnInit, CanComponentDeactivate {
'DEMO',
'V4L2ENC',
'HDPVR',
'SATIP'
'SATIP',
'VBOX'
];

currentTab: number = -1;
Expand Down
Expand Up @@ -35,7 +35,7 @@
{{ currentDevice.FriendlyName}} &nbsp;
</div>
<small class="block">
{{ 'settings.capture.friendly_desc' | translate }}
{{ 'settings.capture.satip.friendly_desc' | translate }}
</small>
</div>

Expand Down
@@ -1,4 +1,4 @@
import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
import { CaptureCardService } from 'src/app/services/capture-card.service';
Expand All @@ -10,7 +10,7 @@ import { SetupService } from 'src/app/services/setup.service';
templateUrl: './satip.component.html',
styleUrls: ['./satip.component.css']
})
export class SatipComponent implements OnInit {
export class SatipComponent implements OnInit , AfterViewInit {
@Input() card!: CardAndInput;
@Input() cardList!: CaptureCardList;

Expand Down Expand Up @@ -61,14 +61,20 @@ export class SatipComponent implements OnInit {
});
}

ngAfterViewInit(): void {
this.setupService.setCurrentForm(this.currentForm);
this.topElement.nativeElement.scrollIntoView({ behavior: "smooth", block: "start" });
}

// After load of devices, make sure the current record is selected in list
setupDevice(): void {
// Add one blank entry at the start if it is a new card
// This is to prevent the system automaitically selecting the first entry
// in the list when you add a new card
if (!this.card.VideoDevice) {
let dummy = <CaptureDevice>{
VideoDevice: '',
FrontendName: this.messages.noDevSelected,
InputNames: [''],
VideoDevicePrompt: this.messages.noDevSelected,
}
this.captureDeviceList.CaptureDeviceList.CaptureDevices.unshift(dummy);
}
Expand All @@ -79,8 +85,7 @@ export class SatipComponent implements OnInit {
else {
this.currentDevice = <CaptureDevice>{
VideoDevice: this.card.VideoDevice,
FrontendName: this.messages.devNotExist,
InputNames: ['']
FriendlyName: this.messages.devNotExist,
};
this.captureDeviceList.CaptureDeviceList.CaptureDevices.push(this.currentDevice);
}
Expand Down
@@ -1,4 +1,4 @@
import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
import { CaptureCardService } from 'src/app/services/capture-card.service';
Expand All @@ -11,7 +11,7 @@ import { CaptureCardsComponent } from '../capture-cards.component';
templateUrl: './v4l2.component.html',
styleUrls: ['./v4l2.component.css']
})
export class V4l2Component implements OnInit {
export class V4l2Component implements OnInit, AfterViewInit {

@Input() card!: CardAndInput;
@Input() cardList!: CaptureCardList;
Expand Down Expand Up @@ -62,9 +62,16 @@ export class V4l2Component implements OnInit {
});
}

ngAfterViewInit(): void {
this.setupService.setCurrentForm(this.currentForm);
this.topElement.nativeElement.scrollIntoView({ behavior: "smooth", block: "start" });
}

// After load of devices, make sure the current record is selected in list
setupDevice(): void {
// Add one blank entry at the start if it is a new card
// This is to prevent the system automaitically selecting the first entry
// in the list when you add a new card
if (!this.card.VideoDevice) {
let dummy = <CaptureDevice>{
VideoDevice: '',
Expand Down
Empty file.
@@ -0,0 +1,109 @@
<form class="ml-3 mr-3" name="vboxform" #vboxform="ngForm">
<span #top></span>
<p-card class="m-5">
<ng-template pTemplate="title">
{{ 'settings.capture.vbox.title' | translate }}
</ng-template>
<ng-template pTemplate="subtitle">
</ng-template>
<ng-template pTemplate="content">
<div class="grid">
<div class="mb-4 w-full">

<div class="form-group field">
<label for="VideoDevicePrompt" class="block">{{ 'settings.capture.satip.device_label' | translate
}}</label>
<p-dropdown *ngIf="isReady" [options]="captureDeviceList.CaptureDeviceList.CaptureDevices"
[(ngModel)]="currentDevice" [editable]="false" optionLabel="VideoDevicePrompt"
(onChange)="updateDevice();" [maxlength]="0" [style]="{'minWidth':'83%'}" name="VideoDevicePrompt"
#VideoDevicePrompt="ngModel">
</p-dropdown>
<div *ngIf="warningMessage">
<small class="p-error block">
{{ warningMessage }}
</small>
</div>
<small class="block">
{{ 'settings.capture.vbox.device_desc' | translate }}
</small>
</div>

<div class="form-group field">
<label class="block">{{ 'settings.capture.vbox.deviceid_label' | translate
}}</label>
<div class="col-10 bg-blue-100">
{{ card.VideoDevice}} &nbsp;
</div>
<small class="block">
{{ 'settings.capture.vbox.deviceid_desc' | translate }}
</small>
</div>

<div class="form-group field">
<label class="block">{{ 'settings.capture.vbox.description_label' | translate
}}</label>
<div class="col-10 bg-blue-100">
{{ currentDevice.FriendlyName}} &nbsp;
</div>
<small class="block">
</small>
</div>

<div class="form-group field">
<label for="ip" class="block">{{ 'settings.capture.ceton.ipaddress_label' | translate }}</label>
<input pInputText id="ip" [(ngModel)]="currentDevice.IPAddress" name="ip" #ipAddress="ngModel"
class="mb-2 form-control w-full" [disabled]="currentDevice !== manualDevice"/>
<small class="block">
{{ 'settings.capture.ceton.ipaddress_desc' | translate }}
</small>
</div>

<div class="form-group field">
<label for="tuner" class="block">{{ 'settings.capture.ceton.tuner_label' | translate }}</label>
<input pInputText id="tuner" [(ngModel)]="currentDevice.TunerNumber" name="tuner" #ipAddress="ngModel"
class="mb-2 form-control w-full" [disabled]="currentDevice !== manualDevice"/>
<small class="block">
{{ 'settings.capture.ceton.tuner_desc' | translate }}
</small>
</div>

<div class="form-group field">
<label for="SignalTimeout" class="block">{{ 'settings.capture.sigtimeout_label' | translate
}}</label>
<p-inputNumber [(ngModel)]="card.SignalTimeout" name="SignalTimeout" id="SignalTimeout"
[showButtons]="true" [min]="250" [max]="60000" [step]="250"></p-inputNumber>
<small class="block">
{{ 'settings.capture.sigtimeout_desc' | translate }}
</small>
</div>

<div class="form-group field">
<label for="ChannelTimeout" class="block">{{ 'settings.capture.tunetimeout_label' | translate
}}</label>
<p-inputNumber [(ngModel)]="card.ChannelTimeout" name="ChannelTimeout" id="ChannelTimeout"
[showButtons]="true" [min]="2000" [max]="65000" [step]="250"></p-inputNumber>
<small class="block">
{{ 'settings.capture.tunetimeout_desc' | translate }}
</small>
</div>

</div>
</div>
</ng-template>

<ng-template pTemplate="footer">
<div class="grid nogutter">
<div class="col-12">
<p-message *ngIf="this.successCount > 0 && this.errorCount == 0 && !vboxform.dirty"
severity="success" text="{{ 'common.savesuccess' | translate }}"></p-message>
<p-message *ngIf="this.errorCount > 0" severity="error"
text="{{ 'common.networkfail' | translate }}"></p-message>
</div>
<p-button class="col pr-1" label="{{'common.save' | translate}}" icon="pi pi-save" iconPos="left"
(onClick)="saveForm(); vboxform.form.markAsPristine()"
[disabled]="!vboxform.dirty || !card.VideoDevice || setupService.schedulingEnabled"></p-button>
</div>
</ng-template>

</p-card>
</form>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { VboxComponent } from './vbox.component';

describe('VboxComponent', () => {
let component: VboxComponent;
let fixture: ComponentFixture<VboxComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ VboxComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(VboxComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

0 comments on commit b90cb4c

Please sign in to comment.